Skip to content

Commit 1ad3c3d

Browse files
authored
Merge pull request #605 from jw098/sandwich
Fix Sandwich maker
2 parents 64af268 + d32aeaa commit 1ad3c3d

File tree

3 files changed

+97
-16
lines changed

3 files changed

+97
-16
lines changed

SerialPrograms/Source/PokemonSV/Inference/Picnics/PokemonSV_SandwichPlateDetector.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77

8+
#include "Common/Cpp/Exceptions.h"
89
#include "CommonFramework/ImageTypes/ImageViewRGB32.h"
910
#include "CommonFramework/VideoPipeline/VideoOverlayScopes.h"
1011
#include "CommonTools/Images/ImageFilter.h"
@@ -35,6 +36,9 @@ SandwichPlateDetector::SandwichPlateDetector(Logger& logger, Color color, Langua
3536
case Side::RIGHT:
3637
m_box = ImageFloatBox(0.699, 0.269, 0.201, 0.044);
3738
break;
39+
default:
40+
throw InternalProgramError(&logger, PA_CURRENT_FUNCTION,
41+
"Invalid Side for SandwichPlateDetector()");
3842
}
3943
}
4044

SerialPrograms/Source/PokemonSV/Inference/Picnics/PokemonSV_SandwichPlateDetector.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ class SandwichPlateDetector : public StaticScreenDetector{
3232
enum class Side{
3333
LEFT,
3434
MIDDLE,
35-
RIGHT
35+
RIGHT,
36+
NOT_APPLICABLE,
3637
};
3738
SandwichPlateDetector(Logger& logger, Color color, Language language, Side side);
3839
virtual ~SandwichPlateDetector();

SerialPrograms/Source/PokemonSV/Programs/Sandwiches/PokemonSV_SandwichRoutines.cpp

Lines changed: 91 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
#include "PokemonSV/Programs/Sandwiches/PokemonSV_IngredientSession.h"
3333
#include "PokemonSV/Inference/Picnics/PokemonSV_SandwichPlateDetector.h"
3434

35+
// #include <iostream>
36+
// using std::cout;
37+
// using std::endl;
3538

3639
namespace PokemonAutomation{
3740
namespace NintendoSwitch{
@@ -347,22 +350,56 @@ bool move_then_recover_sandwich_hand_position(
347350
);
348351
}
349352

353+
// return true if the current plate is empty.
354+
// i.e. the current plate label is not yellow.
355+
// Assumes that we are in a grabbing state.
356+
bool check_plate_empty(VideoStream& stream, SandwichPlateDetector::Side target_plate_label, Language language){
357+
auto screen = stream.video().snapshot();
358+
// screen.frame->save("test.png");
359+
360+
// switch(target_plate_label){
361+
// case SandwichPlateDetector::Side::LEFT:
362+
// cout << "left" << endl;
363+
// break;
364+
// case SandwichPlateDetector::Side::MIDDLE:
365+
// cout << "middle" << endl;
366+
// break;
367+
// case SandwichPlateDetector::Side::RIGHT:
368+
// cout << "right" << endl;
369+
// break;
370+
// default:
371+
// break;
372+
// }
373+
374+
SandwichPlateDetector plate_detector = SandwichPlateDetector(stream.logger(), COLOR_RED, language, target_plate_label);
375+
376+
return !plate_detector.is_label_yellow(screen);
377+
}
378+
379+
struct HandMoveData{
380+
ImageFloatBox end_box;
381+
bool plate_empty;
382+
};
383+
384+
350385
/*
351386
- moves the sandwich hand from start_box to end_box
352387
- It detects the location of the sandwich hand, from within the bounds of the last frame's
353388
expanded_hand_bb (i.e. m_box field in SandwichHandLocator).
354389
Then updates the current location of expanded_hand_bb.
355390
Then moves the sandwich hand closer towards end_box.
356391
*/
357-
ImageFloatBox move_sandwich_hand(
392+
HandMoveData move_sandwich_hand_and_check_if_plates_empty(
358393
const ProgramInfo& info,
359394
AsyncDispatcher& dispatcher,
360395
VideoStream& stream,
361396
ProControllerContext& context,
362397
SandwichHandType hand_type,
363398
bool pressing_A,
364399
const ImageFloatBox& start_box,
365-
const ImageFloatBox& end_box
400+
const ImageFloatBox& end_box,
401+
SandwichPlateDetector::Side target_plate_label = SandwichPlateDetector::Side::NOT_APPLICABLE,
402+
Language language = Language::None
366403
){
367404
context.wait_for_all_requests();
368405
stream.log("Start moving sandwich hand: " + SANDWICH_HAND_TYPE_NAMES(hand_type)
@@ -454,14 +491,24 @@ ImageFloatBox move_sandwich_hand(
454491

455492
std::pair<double, double> dif(target_loc.first - cur_loc.first, target_loc.second - cur_loc.second);
456493
// console.log("float diff to target: " + std::to_string(dif.first) + ", " + std::to_string(dif.second));
494+
495+
496+
// Reached the Target
457497
if (std::fabs(dif.first) < end_box.width/2 && std::fabs(dif.second) < end_box.height/2){
458498
stream.log(SANDWICH_HAND_TYPE_NAMES(hand_type) + " hand reached target.");
499+
bool plate_empty = false;
500+
501+
// check if the plate is empty. but only if the target_plate_label isn't NOT_APPLICABLE.
502+
if (target_plate_label != SandwichPlateDetector::Side::NOT_APPLICABLE){
503+
plate_empty = check_plate_empty(stream, target_plate_label, language);
504+
}
505+
459506
move_session.stop_session_and_rethrow(); // Stop the commands
460507
if (hand_type == SandwichHandType::GRABBING){
461508
// wait for some time to let hand release ingredient
462509
context.wait_for(std::chrono::milliseconds(100));
463510
}
464-
return hand_bb;
511+
return {hand_bb, plate_empty};
465512
}
466513

467514
// Assume screen width is 16.0, then the screen height is 9.0
@@ -517,6 +564,19 @@ ImageFloatBox move_sandwich_hand(
517564
}
518565
}
519566

567+
ImageFloatBox move_sandwich_hand(
568+
const ProgramInfo& info,
569+
AsyncDispatcher& dispatcher,
570+
VideoStream& stream,
571+
ProControllerContext& context,
572+
SandwichHandType hand_type,
573+
bool pressing_A,
574+
const ImageFloatBox& start_box,
575+
const ImageFloatBox& end_box
576+
){
577+
return move_sandwich_hand_and_check_if_plates_empty(info, dispatcher, stream, context, hand_type, pressing_A, start_box, end_box, SandwichPlateDetector::Side::NOT_APPLICABLE, Language::None).end_box;
578+
}
579+
520580
} // end anonymous namespace
521581

522582
void finish_sandwich_eating(
@@ -1013,7 +1073,8 @@ void run_sandwich_maker(ProgramEnvironment& env, VideoStream& stream, ProControl
10131073
SandwichPlateDetector left_plate_detector(stream.logger(), COLOR_RED, language, SandwichPlateDetector::Side::LEFT);
10141074
SandwichPlateDetector middle_plate_detector(stream.logger(), COLOR_RED, language, SandwichPlateDetector::Side::MIDDLE);
10151075
SandwichPlateDetector right_plate_detector(stream.logger(), COLOR_RED, language, SandwichPlateDetector::Side::RIGHT);
1016-
1076+
bool left_plate_absent = false;
1077+
bool right_plate_absent = false;
10171078
{
10181079
VideoSnapshot screen = stream.video().snapshot();
10191080

@@ -1045,7 +1106,8 @@ void run_sandwich_maker(ProgramEnvironment& env, VideoStream& stream, ProControl
10451106

10461107
//Get left (2nd) ingredient
10471108
std::string left_filling = left_plate_detector.detect_filling_name(screen);
1048-
if (left_filling.empty()){
1109+
left_plate_absent = left_filling.empty();
1110+
if (left_plate_absent){
10491111
stream.log("No ingredient found on left label.");
10501112
stream.overlay().add_log("No left plate");
10511113
}else{
@@ -1056,7 +1118,8 @@ void run_sandwich_maker(ProgramEnvironment& env, VideoStream& stream, ProControl
10561118

10571119
//Get right (3rd) ingredient
10581120
std::string right_filling = right_plate_detector.detect_filling_name(screen);
1059-
if (right_filling.empty()){
1121+
right_plate_absent = right_filling.empty();
1122+
if (right_plate_absent){
10601123
stream.log("No ingredient found on right label.");
10611124
stream.overlay().add_log("No right plate");
10621125
}else{
@@ -1139,12 +1202,14 @@ void run_sandwich_maker(ProgramEnvironment& env, VideoStream& stream, ProControl
11391202
//Find fillings and add them in order
11401203
for (const std::string& i : fillings_sorted){
11411204
//cout << "Placing " << i << endl;
1205+
stream.log("Placing " + i, COLOR_WHITE);
11421206
stream.overlay().add_log("Placing " + i, COLOR_WHITE);
11431207

11441208
int times_to_place = (int)(FillingsCoordinates::instance().get_filling_information(i).piecesPerServing) * (fillings.find(i)->second);
11451209
int placement_number = 0;
11461210

11471211
//cout << "Times to place: " << times_to_place << endl;
1212+
stream.log("Times to place: " + std::to_string(times_to_place), COLOR_WHITE);
11481213
stream.overlay().add_log("Times to place: " + std::to_string(times_to_place), COLOR_WHITE);
11491214

11501215
std::vector<int> plate_index;
@@ -1159,16 +1224,20 @@ void run_sandwich_maker(ProgramEnvironment& env, VideoStream& stream, ProControl
11591224
for (int j = 0; j < (int)plate_index.size(); j++){
11601225
//Navigate to plate and set target plate
11611226
//cout << "Target plate: " << plate_index.at(j) << endl;
1227+
stream.log("Target plate: " + std::to_string(plate_index.at(j)), COLOR_WHITE);
11621228
stream.overlay().add_log("Target plate: " + std::to_string(plate_index.at(j)), COLOR_WHITE);
1229+
SandwichPlateDetector::Side target_plate_label = SandwichPlateDetector::Side::MIDDLE;
11631230
switch (plate_index.at(j)){
11641231
case 0:
11651232
target_plate = center_plate;
11661233
break;
11671234
case 1:
11681235
target_plate = left_plate;
1236+
target_plate_label = SandwichPlateDetector::Side::LEFT;
11691237
break;
11701238
case 2:
11711239
target_plate = right_plate;
1240+
target_plate_label = SandwichPlateDetector::Side::RIGHT;
11721241
break;
11731242
case 3: case 4: case 5: case 6:
11741243
//Press R the appropriate number of times
@@ -1181,10 +1250,12 @@ void run_sandwich_maker(ProgramEnvironment& env, VideoStream& stream, ProControl
11811250
break;
11821251
}
11831252

1253+
// place down all the ingredients for the current plate.
11841254
//Place the fillings until label does not light up yellow on grab/the piece count is not hit
11851255
while (true){
11861256
//Break out after placing all pieces of the filling
11871257
if (placement_number == times_to_place){
1258+
stream.log("We have placed down enough ingredients of that type, so we assume our current plate is empty. Move on to the next plate/ingredient.", COLOR_ORANGE);
11881259
break;
11891260
}
11901261

@@ -1202,26 +1273,27 @@ void run_sandwich_maker(ProgramEnvironment& env, VideoStream& stream, ProControl
12021273
ImageFloatBox placement_target = FillingsCoordinates::instance().get_filling_information(i).placementCoordinates.at(
12031274
(int)fillings.find(i)->second).at(placement_number);
12041275

1205-
end_box = move_sandwich_hand(
1276+
HandMoveData hand_move_data = move_sandwich_hand_and_check_if_plates_empty(
12061277
env.program_info(), env.realtime_dispatcher(),
12071278
stream, context,
12081279
SandwichHandType::GRABBING,
12091280
true,
12101281
expand_box(end_box),
1211-
placement_target
1282+
placement_target,
1283+
target_plate_label
12121284
);
1285+
end_box = hand_move_data.end_box;
12131286
context.wait_for_all_requests();
12141287

1215-
//If any of the labels are yellow continue. Otherwise assume plate is empty move on to the next.
1216-
auto screen = stream.video().snapshot();
1217-
1218-
//The label check is needed for ingredients with multiple plates as we don't know which plate has what amount
1219-
if (!left_plate_detector.is_label_yellow(screen) && !middle_plate_detector.is_label_yellow(screen)
1220-
&& !right_plate_detector.is_label_yellow(screen)){
1288+
// If the current plate is empty, break out of the loop and move on to the next plate.
1289+
if (hand_move_data.plate_empty){
12211290
context.wait_for_all_requests();
1291+
stream.log("Our current plate label is NOT yellow, so we assume our current plate is empty. Move on to the next plate.", COLOR_ORANGE);
12221292
break;
12231293
}
12241294

1295+
stream.log("Our current plate label is yellow, so we assume our current plate is NOT empty. Continue with the current plate.", COLOR_YELLOW);
1296+
12251297
//If the plate is empty the increment is skipped using the above break
12261298
placement_number++;
12271299
}
@@ -1232,8 +1304,12 @@ void run_sandwich_maker(ProgramEnvironment& env, VideoStream& stream, ProControl
12321304
}
12331305
}
12341306
}
1307+
1308+
context.wait_for_all_requests();
1309+
context.wait_for(Milliseconds(500));
1310+
stream.log("All ingredients should now be empty. Wait for upper bread.", COLOR_YELLOW);
12351311
// Handle top slice by tossing it away
1236-
SandwichHandWatcher grabbing_hand(SandwichHandType::FREE, { 0, 0, 1.0, 1.0 });
1312+
SandwichHandWatcher grabbing_hand(SandwichHandType::GRABBING, { 0, 0, 1.0, 1.0 });
12371313
int ret = wait_until(stream, context, std::chrono::seconds(30), { grabbing_hand });
12381314
if (ret < 0){
12391315
OperationFailedException::fire(

0 commit comments

Comments
 (0)