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
3639namespace PokemonAutomation {
3740namespace 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
353388expanded_hand_bb (i.e. m_box field in SandwichHandLocator).
354389Then updates the current location of expanded_hand_bb.
355390Then 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
522582void 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