Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

3pi maze solving doubt

hello ben,

i am preparing for a maze solving competiton with a very difficult problem statement to solve
the problem statement is

i can reach the end point given by just optimizing the mazesolver code given by pololu libs but the problem is how do i make the robot traverse along the exact same path it came from the start point and again reach the start point once it has reached the end point in the exact same path

what i mean is (start point ------endpoint---------back to startpoint)in the exact same path it came by solving the maze
i know that i have to make a function reversing the turn operations that is
s will remain same
R to L
L to R

i tried doing this on 3pi first up by adding this funtion at the second while loop which runs infinitely once the maze is solved,although it reverses the path[i],but it isnt executing the reversed path please suggest me a correct way to achieve this operation
it doesnt execute the reversed path

this is the function i made to reverse the path

void reverse_path()
{ int i;
  for (i = path_length-1; i >=0; i++)
  {
    if(path[i] == 'S')
    {
      path[i] = 'S';
    }
     if(path[i] == 'R')
    {
      path[i] = 'L';
    }
     if(path[i] == 'L')
    {
      path[i] = 'R';
    }
 }}

And this is the void loop in arduino(i do coding using arduino)

void loop()
{
  while (0)
  {
    follow_segment();

    // Drive straight a bit.  This helps us in case we entered the
    // intersection at an angle.
    // Note that we are slowing down - this prevents the robot
    // from tipping forward too much.
    OrangutanMotors::setSpeeds(50, 50);
    delay(50);

    // These variables record whether the robot has seen a line to the
    // left, straight ahead, and right, whil examining the current
    // intersection.
    unsigned char found_left = 0;
    unsigned char found_straight = 0;
    unsigned char found_right = 0;

    // Now read the sensors and check the intersection type.
    unsigned int sensors[5];
    robot.readLine(sensors, IR_EMITTERS_ON);

    // Check for left and right exits.
    if (sensors[0] > 100)
      found_left = 1;
    if (sensors[4] > 100)
      found_right = 1;

    // Drive straight a bit more - this is enough to line up our
    // wheels with the intersection.
    OrangutanMotors::setSpeeds(40, 40);
    delay(200);

    // Check for a straight exit.
    robot.readLine(sensors, IR_EMITTERS_ON);
    if (sensors[1] > 200 || sensors[2] > 200 || sensors[3] > 200)
      found_straight = 1;

    // Check for the ending spot.
    // If all three middle sensors are on dark black, we have
    // solved the maze.
    if (sensors[1] > 600 && sensors[2] > 600 && sensors[3] > 600)
      break;

    // Intersection identification is complete.
    // If the maze has been solved, we can follow the existing
    // path.  Otherwise, we need to learn the solution.
    unsigned char dir = select_turn(found_left, found_straight, found_right);

    // Make the turn indicated by the path.
    turn(dir);

    // Store the intersection in the path variable.
    path[path_length] = dir;
    path_length++;

    // You should check to make sure that the path_length does not
    // exceed the bounds of the array.  We'll ignore that in this
    // example.

    // Simplify the learned path.
    simplify_path();

    // Display the path on the LCD.
    display_path();
  }

  // Solved the maze!

  // Now enter an infinite loop - we can re-run the maze as many
  // times as we want to.
  while (1)
  {
    // Beep to show that we solved the maze.
    OrangutanMotors::setSpeeds(0, 0);
    OrangutanBuzzer::play(">>a32");
    done = 1;
    // Wait for the user to press a button, while displaying
    // the solution.
    while (!OrangutanPushbuttons::isPressed(BUTTON_B))
    {
      if (millis() % 2000 < 1000)
      {
        OrangutanLCD::clear();
        OrangutanLCD::print("Solved!");
        OrangutanLCD::gotoXY(0, 1);
        OrangutanLCD::print("Press B");
      }
      else
        display_path();
      delay(30);
    }
    while (OrangutanPushbuttons::isPressed(BUTTON_B));

    delay(1000);

    // Re-run the maze.  It's not necessary to identify the
    // intersections, so this loop is really simple.
    int i;
    for (i = 0; i < path_length; i++)
    {
      follow_segment();

      // Drive straight while slowing down, as before.
      OrangutanMotors::setSpeeds(50, 50);
      delay(50);
      OrangutanMotors::setSpeeds(40, 40);
      delay(200);

      // Make a turn according to the instruction stored in
      // path[i].
      turn(path[i]);
     
     
    }

  follow_segment();
  
    reverse_path();
  OrangutanMotors::setSpeeds(80,-80);// reverse after execution of the path then now on to reversing the path so gets aligned to execute the   reverse   path 
    for (i = path_length-1; i >=0; i++)
     {
                                                              // Drive straight while slowing down, as before.
      OrangutanMotors::setSpeeds(50, 50);
      delay(50);
      OrangutanMotors::setSpeeds(40, 40);
      delay(200);

      // Make a turn according to the instruction stored in
      // path[i].
      turn(path[i]);
     }
    follow_segment();
    
}
  

 
  }

thanks for any help


Hi,

I think you need to add a call to follow_segment to the inside of your for loop. Also, don’t you need to turn around when you reach the end?

- Ryan

sorry ryan

and yes i just forgot to include that follow_segment inside the for loop,yes the code which isnt working for me is this how do i run one complete cycle from start to end then back to the start of the maze.
sorry but the code below is exact same code which is not working for reversing and rerunning the loop

void loop()
{
  while (0)
  {
    follow_segment();

    // Drive straight a bit.  This helps us in case we entered the
    // intersection at an angle.
    // Note that we are slowing down - this prevents the robot
    // from tipping forward too much.
    OrangutanMotors::setSpeeds(50, 50);
    delay(50);

    // These variables record whether the robot has seen a line to the
    // left, straight ahead, and right, whil examining the current
    // intersection.
    unsigned char found_left = 0;
    unsigned char found_straight = 0;
    unsigned char found_right = 0;

    // Now read the sensors and check the intersection type.
    unsigned int sensors[5];
    robot.readLine(sensors, IR_EMITTERS_ON);

    // Check for left and right exits.
    if (sensors[0] > 100)
      found_left = 1;
    if (sensors[4] > 100)
      found_right = 1;

    // Drive straight a bit more - this is enough to line up our
    // wheels with the intersection.
    OrangutanMotors::setSpeeds(40, 40);
    delay(200);

    // Check for a straight exit.
    robot.readLine(sensors, IR_EMITTERS_ON);
    if (sensors[1] > 200 || sensors[2] > 200 || sensors[3] > 200)
      found_straight = 1;

    // Check for the ending spot.
    // If all three middle sensors are on dark black, we have
    // solved the maze.
    if (sensors[1] > 600 && sensors[2] > 600 && sensors[3] > 600)
      break;

    // Intersection identification is complete.
    // If the maze has been solved, we can follow the existing
    // path.  Otherwise, we need to learn the solution.
    unsigned char dir = select_turn(found_left, found_straight, found_right);

    // Make the turn indicated by the path.
    turn(dir);

    // Store the intersection in the path variable.
    path[path_length] = dir;
    path_length++;

    // You should check to make sure that the path_length does not
    // exceed the bounds of the array.  We'll ignore that in this
    // example.

    // Simplify the learned path.
    simplify_path();

    // Display the path on the LCD.
    display_path();
  }

  // Solved the maze!

  // Now enter an infinite loop - we can re-run the maze as many
  // times as we want to.
  while (1)
  {
    // Beep to show that we solved the maze.
    OrangutanMotors::setSpeeds(0, 0);
    OrangutanBuzzer::play(">>a32");
    done = 1;
    // Wait for the user to press a button, while displaying
    // the solution.
    while (!OrangutanPushbuttons::isPressed(BUTTON_B))
    {
      if (millis() % 2000 < 1000)
      {
        OrangutanLCD::clear();
        OrangutanLCD::print("Solved!");
        OrangutanLCD::gotoXY(0, 1);
        OrangutanLCD::print("Press B");
      }
      else
        display_path();
      delay(30);
    }
    while (OrangutanPushbuttons::isPressed(BUTTON_B));

    delay(1000);

    // Re-run the maze.  It's not necessary to identify the
    // intersections, so this loop is really simple.
    int i;
    for (i = 0; i < path_length; i++)
    {
      follow_segment();

      // Drive straight while slowing down, as before.
      OrangutanMotors::setSpeeds(50, 50);
      delay(50);
      OrangutanMotors::setSpeeds(40, 40);
      delay(200);

      // Make a turn according to the instruction stored in
      // path[i].
      turn(path[i]);
     
     
    }

  follow_segment();
 
    reverse_path();
  OrangutanMotors::setSpeeds(80,-80);// reverse after execution of the path then now on to reversing the path so gets aligned to execute the   reverse   path
    for (i = path_length-1; i >=0; i++)
     {  follow_segment();
                                                              // Drive straight while slowing down, as before.
      OrangutanMotors::setSpeeds(50, 50);
      delay(50);
      OrangutanMotors::setSpeeds(40, 40);
      delay(200);

      // Make a turn according to the instruction stored in
      // path[i].
      turn(path[i]);
     }
    follow_segment();
   
}
 


  }

and yes there is a reverse operation which reverses and align the robot for moving back towards the start
but first of all the loop is not getting executed properly and ,may be my logic could be wrong please point it out if my logic in the while() loop
is wrong in calling the reverse() function

thanks for your help ryan,

I noticed your first while loop says “while(0).” Are you purposefully skipping that code? If so, why post it here? Can you simplify your code to the smallest possible bit of code that doesn’t do what you want?

- Ryan

sorry ryan ,
yes i dont use the first while loop so i make it while (0)

i dont want the maze solving part because i will give the path to be travelled by the bot that is SSLRS…etc to path variable so i dont need the maze exploration part

but i want the path execution to take place that is go from start and come back to the start once it has completey travelled the path i have given ,here i will solve the maze myself not the bot and then store the path in the path variable so that it can execute the turns.
once the the complete path is executed i want to reverse the path which i had stored so that the robot can come back to the point where it started from in the same way it came to the end point.

here i want one complete cycle like (start point----------->endpoint ------back in the same path which it came from-------------->start)
this is the main loop which does the execution part

void loop()
{
    while (1)
  {
    // Beep to show that we solved the maze.
    OrangutanMotors::setSpeeds(0, 0);
    OrangutanBuzzer::play(">>a32");
    done = 1;
    // Wait for the user to press a button, while displaying
    // the solution.
    while (!OrangutanPushbuttons::isPressed(BUTTON_B))
    {
      if (millis() % 2000 < 1000)
      {
        OrangutanLCD::clear();
        OrangutanLCD::print("Solved!");
        OrangutanLCD::gotoXY(0, 1);
        OrangutanLCD::print("Press B");
      }
      else
        display_path();
      delay(30);
    }
    while (OrangutanPushbuttons::isPressed(BUTTON_B));

    delay(1000);

    // Re-run the maze.  It's not necessary to identify the
    // intersections, so this loop is really simple.
    int i;
    for (i = 0; i < path_length; i++)
    {
      follow_segment();

      // Drive straight while slowing down, as before.
      OrangutanMotors::setSpeeds(50, 50);
      delay(50);
      OrangutanMotors::setSpeeds(40, 40);
      delay(200);

      // Make a turn according to the instruction stored in
      // path[i].
      turn(path[i]);
     
     
    }

  follow_segment();

    reverse_path();
  OrangutanMotors::setSpeeds(80,-80);// reverse after execution of the path then now on to reversing the path so gets aligned to execute the   reverse   path
    for (i = path_length-1; i >=0; i--)
     {  follow_segment();
                                                              // Drive straight while slowing down, as before.
      OrangutanMotors::setSpeeds(50, 50);
      delay(50);
      OrangutanMotors::setSpeeds(40, 40);
      delay(200);

      // Make a turn according to the instruction stored in
      // path[i].
      turn(path[i]);
     }
    follow_segment();
   
}



  }

this is the function i wrote for reversing the path

void reverse_path()
{ int i;
  for (i = path_length-1; i >=0; i--)
  {
    if(path[i] == 'S')
    {
      path[i] = 'S';
    }
     if(path[i] == 'R')
    {
      path[i] = 'L';
    }
     if(path[i] == 'L')
    {
      path[i] = 'R';
    }
}}

thanks for the reply,

It looks like your code to turn around might not be correct. You don’t give the robot any time to turn around after you have

OrangutanMotors::setSpeeds(80,-80);// reverse after execution of the path then now on to reversing the path so gets aligned to execute the   reverse   path

What is the problem you are facing? What part of the code do you think is responsible for this problem?

- Ryan