This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 5 years have passed since last update.

8.d. The Main Loop(s) (Pololu 3pi Robot User’s Guide) 日本語訳【非公式】

Last updated at Posted at 2019-05-18

これは Pololu 3pi Robot User’s Guide ≫ 8.d. The Main Loop(s) の非公式日本語訳です。
目次
前: 8.c. Left Hand on the Wall
次: 8.e. Simplifying the Solution

8.d. The Main Loop(s)

The strategy of our program is expressed in the file maze-solve.c. Most importantly, we want to keep track of the path that we have followed, so we define an array storing up to 100; these will be the same characters used in the turn() function. We also need to keep track of the current path length so that we know where to put the characters in the array.

私たちのプログラムの方法はmaze-solve.cに表現されています。最も重要なことは、辿った経路を追跡したいため、100まで格納する配列を定義します。これらはturn()関数で使用される文字と同じです。配列のどこに文字を格納するかを知るために、現在の経路長も追う必要があります。

libpololu-avr\examples\atmega328p\3pi-mazesolver\maze-solve.c
char path[100] = "";
unsigned char path_length = 0; // the length of the path

Our “main loop” is found in the function maze_solve(), which is called after calibration, from main.c. This function actually includes two main loops – a first one that handles solving the maze, and a second that replays the solution for the fastest possible time. In fact, the second loop is actually a loop within a loop, since we want to be able to replay the solution many times. Here’s an outline of the code:

"メインループ"は、main.cからキャリブレーションの後に呼び出されるmaze_solve()関数の中にあります。この関数は、実際には2つのメインループが含まれています。1つ目は迷路の解決を処理するもので、2つ目は導き出した解を可能な限り最短時間でリプレイするためのものです。実際は、解を何度でもリプレイしたいため、2つ目のループはループ内のループです。コードの概要はこちらです:

libpololu-avr\examples\atmega328p\3pi-mazesolver\maze-solve.c
// This function is called once, from main.c.
void maze_solve()
{
    while(1)
    {
        // FIRST MAIN LOOP BODY
        // (when we find the goal, we use break; to get out of this)
    }

    // 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 finished the maze.
        // Wait for the user to press a button...

        int i;
        for(i=0;i<path_length;i++)
        {
            // SECOND MAIN LOOP BODY
        }

        // Follow the last segment up to the finish.
        follow_segment();

        // Now we should be at the finish!  Restart the loop.
    }
}

The first main loop needs to drive down a segment of the course, decide how to turn, and record the turn in the path variable. To pass the correct arguments to select_turn(), we need to carefully examine the intersection as we cross it. Note that there is a special exception for finding the end of the maze. The following code works pretty well, at least at the slow speeds that we’re using:

最初のメインループでは、コースの一部を下に進み、ターンの方法を決定し、ターンを変数pathに記録する必要があります。select_turn()に正しい引数を渡すために、交差点を横切るときに、交差点を慎重に調べる必要があります。迷路の終わりを見つけるための特別な例外があることに注意してください。以下のコードは、少なくとも私たちが使用している遅い速度ではかなりうまくいきます。

libpololu-avr\examples\atmega328p\3pi-mazesolver\maze-solve.c
// FIRST MAIN LOOP BODY
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.
set_motors(50,50);
delay_ms(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];
read_line(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.
set_motors(40,40);
delay_ms(200);

// Check for a straight exit.
read_line(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();

We’ll discuss the call to simplify_path() in the next section. Before that, let’s take a look at the second main loop, which is very simple. All we do is drive to the next intersection and turn according to our records. After doing the last recorded turn, the robot will be one segment away from the finish, which explains the final follow_segment() call in the outline of maze_solve() above.

次のセクションでsimplify_path()の呼び出しを説明します。その前に、2つ目のメインループを見てみましょう。これは非常に単純です。私たちがすることは、次の交差点へ進み、記録に従ってターンすることです。最後の記録をターンした後、ロボットはゴールから1区間離れたところにあります。これは、上記のmaze_solve()の概要の最後のfollow_segment()呼び出しを説明しています。

libpololu-avr\examples\atmega328p\3pi-mazesolver\maze-solve.c
// SECOND MAIN LOOP BODY
follow_segment();

// Drive straight while slowing down, as before.
set_motors(50,50);
delay_ms(50);
set_motors(40,40);
delay_ms(200);

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up