diff --git a/course/line_following/media/print_error.png b/course/line_following/media/print_error.png deleted file mode 100644 index 6581be0..0000000 Binary files a/course/line_following/media/print_error.png and /dev/null differ diff --git a/course/line_following/media/sumo.png b/course/line_following/media/sumo.png deleted file mode 100644 index 9edab52..0000000 Binary files a/course/line_following/media/sumo.png and /dev/null differ diff --git a/course/line_following/on_off_control.rst b/course/line_following/on_off_control.rst index c512370..d086c5b 100644 --- a/course/line_following/on_off_control.rst +++ b/course/line_following/on_off_control.rst @@ -5,21 +5,20 @@ Now, let's turn our attention towards one of the core challenges in the final project - following a line. In the project, the robot will need to drive to multiple different locations, but doing this just based on distance can result in the robot not getting to exactly the right place. What if the wheels slip -while driving? What if the robot needs to drive along a complex curve? It's +while driving? What if the robot needs to drive along a more complicated path? It's easier to follow a line than it is to exactly measure out the course the robot needs to follow and program it. How do we follow a line? ------------------------ -Consider using one of the reflectance sensors. As a refresher, gives a reading -from 0 (black) to 1 (white). Assuming that the reflectance sensor is -approximately at the center of the robot, it will at least partially reading the -black line when the robot is centered on the line. What type of logic would we -need if we wanted to follow the center of the line? +Consider using just one of the reflectance sensors. As a refresher, it gives a reading +from 0 (black) to 1 (white). Assuming that the reflectance sensor is at the center of the robot, +it will sense part of the black line when the robot is centered on the line. +What logic would we need if we wanted to follow the center of the line? -Well, if the reflectance sensor reads black, it means the robot is perfectly on -the line, and we'd want to go straight, setting the motors at the same speed. +If the reflectance sensor reads black, it means the robot is perfectly on +the line, and we'd want to go straight, setting both motors at the same speed. But if the reflectance sensor reads grey or white, it would mean that the robot is partially or completely off the line. We'd want to correct this by steering it back to the center, but does it turn left or right? @@ -34,9 +33,9 @@ which the robot reacts. * If the sensor reads closer to black, that means we're too far to the right, so we need to turn slightly to the left. -And that's it! We want to keep polling (getting the value of) the reflectance +And that's it! We want to keep reading values from the reflectance sensor quickly, and at each time determine whether it's closer to white (with a -value less than 0.5) or closer to black (with a value greater than 0.5), and +value less than the threshold) or closer to black (with a value greater than 0.5), and depending on the result, either set the motor to turn right (set left motor speed to be faster than right) or turn left (set right motor speed to be faster than left). @@ -44,37 +43,8 @@ than left). This seems like a solution involving an if-else statement. Our condition would be related to whether the value is greater or less than 0.5. -An :code:`if` / :code:`else` statement allows you to run different blocks of -code based on a *condition* (the same kind of *condition* you used in a -:code:`while` loop) - -Consider the following example code: - -.. tab-set:: - - .. tab-item:: Python - - .. code-block:: python - - from XRPLib.defaults import * - - while True: - if drivetrain.get_left_encoder_position() > 20: - print("Left encoder is greater than 20 cm") - else: - print("Left encoder is less than 20 cm") - - .. tab-item:: Blockly - - .. image:: media/if-else.png - :width: 300 - - -In this example code we just show different messages on the computer based -on the value of the left encoder, but you could put whatever code you want -in the blocks instead. For example, you could have the robot turn clockwise -or counterclockwise depending on a condition using an :code:`if` / -:code:`else` statement. +As you may remember, an :code:`if` / :code:`else` statement allows you to run different blocks of +code based on a *condition* (the same kind of *condition* you used in a :code:`while` loop) .. figure:: media/on_off_control.png :align: center @@ -97,4 +67,69 @@ of the sensor. high and your robot will drive off the line before it gets a chance to correct for it, too low and your robot will not correct in time and will spin in circles. Try to get your robot to follow the line as fast as you - can! \ No newline at end of file + can! + +.. tab-set:: + + .. tab-item:: Hide + + Click the other tab to see a hint. + + .. tab-item:: Hint + + Consider the following example code: + + .. tab-set:: + + .. tab-item:: Python + + .. code-block:: python + + from XRPLib.defaults import * + import time + + while True: + if drivetrain.get_left_encoder_position() > 20: + print("Left encoder is greater than 20 cm") + else: + print("Left encoder is less than 20 cm") + time.sleep(0.1) + + .. tab-item:: Blockly + + .. image:: media/if-else.png + :width: 300 + + + In this example code we print different things based on the left motor's encoder position. + You can use a similar structure to set different speeds based on the reading from the reflectance sensor. + + .. tab-item:: Solution + + .. tab-set:: + + .. tab-item:: Python + + .. code-block:: python + + from XRPLib.defaults import * + import time + + # This is a tuning value! Based on your line, sensors, and lighting, + # the exact value for this variable may vary. + line_threshold = 0.5 + + while True: + if reflectance.get_right() > line_threshold: + # if the right sensor is on the line, turn slightly left + drivetrain.set_effort(0.5,0.35) + else: + # if the right sensor is on the line, turn slightly left + drivetrain.set_effort(0.35,0.5) + time.sleep(0.1) + + .. tab-item:: Blockly + + TODO: Add blockly code + .. .. image:: media/if-else.png + .. :width: 300 diff --git a/course/line_following/parking_garage.rst b/course/line_following/parking_garage.rst index c12c7cb..656eac4 100644 --- a/course/line_following/parking_garage.rst +++ b/course/line_following/parking_garage.rst @@ -21,26 +21,29 @@ The main process we will employ here is simple: 1. Go forward the length of a parking spot 2. Turn 90 degrees right and check to see if the parking spot is open 3. If the parking spot is not open, turn 180 degrees left and check to see if the parking spot on the left is open -4. If both parking spots are not open, turn back to straight using the line following understanding_the_sensor +4. If both parking spots are not open, turn back to straight using the line following sensors to know when we are over the line. +5. When an open parking spot is found, drive forward into the parking spot until you see a line (the end of the parking spot) In order to see if a parking spot is open, we can use our ultrasonic range finder and see if there is any object in a parking spot. Leveraging the Line Following Sensors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In this activity, we can use our line following sensors for three main purposes: +In this activity, we want to use our line following sensors for three main purposes: 1. To follow the line on the ground to the next parking spot 2. To detect the "end" of the parking spot 3. To turn back to straight after checking the left parking spot In terms of following the line, we can use the same proportional controller that we used in the previous activities. +In fact, we've wrote most of the code you will need for this already! +For example, we can use the same logic that we used when detecting an intersection for detecting the end of the parking spot, +and again for when we are turning back to straight after checking the parking spot. -As for detecting the end of the parking spot, we can use the same logic that we used when detecting an intersection. +By breaking this complicated problem down into a series of smaller steps, we can easily program our XRP to park itself! -Finally, to turn back to straight, we can turn the XRP clockwise until the left line following sensor detects the line. +.. .. error:: -By breaking this complicated problem down into a series of smaller steps, we can easily program our XRP to park itself! +.. TODO a graphic would be super useful throughout this section -.. TODO a graphic would be super useful throughout this section -.. also include code and a video of the robot parking itself +.. also include code and a video of the robot parking itself diff --git a/course/line_following/proportional_control.rst b/course/line_following/proportional_control.rst index a85262c..aefc9a2 100644 --- a/course/line_following/proportional_control.rst +++ b/course/line_following/proportional_control.rst @@ -9,17 +9,14 @@ following problem too! The perks of proportional control --------------------------------- -Let's circle back to the previous exercise - following the line by either -turning left or right depending on whether the robot is situated to the left or -the right of the line. - -What is immediately striking about following the line in this way? Well, the -robot must constantly oscillate in order to stay on the edge of the line, -because even the smallest deviation from the edge of the line results in the -robot wildly turning to compensate. In addition, it does not react any more -forcefully to bigger deviations like when the line starts curving, and as soon -as it loses sight of the line, it has no way of recovering. - +Let's think back to the previous exercise - following the line by either +turning slightly left or right depending on whether the robot is situated to the left or +the right of the line. +The issue with that approach is that the robot oscillates (bounces back and forth) around the line, +and if the robot strays too far from the line, it loses track of where the line is. +Since there were only two cases, where the robot turns at a set speed left or right, +being just slightly from the line result in the robot turning too much, +and the robot may not be able to recover. Instead of only having two cases, it seems like we'd want a whole bunch of cases, for anywhere from a sharp left turn to going perfectly straight to a sharp right turn, and everything in between, based on whether the reflectance @@ -40,16 +37,15 @@ concept here? Calculating error ----------------- -With proportional control, we have an error value we desire for it to tend to -zero, and some motor output is controlled proportional to the error to minimize -that error - in the case of maintaining a certain distance to the wall, the -error was the difference between the target and actual distance, and the output -was the speed of both drive motors. In the case of line following, the error is -the difference from 0.5 - since ideally, the robot follows the grey edge of the -line and goes straight - and the motor output is how the robot should turn. - +When we were using proportional control to control the robot's distance to the wall, +we calculated the error as the difference between the desired distance and the +actual distance. We can do the same here: the error is the difference between +some threshold value (representing being on the edge of the line) and the actual reflectance value. +In the initial reflectance sensor exercise, you found an approximate threshold value +for the reflectance sensor to determine whether the robot was on or off the line. +We're going to start by using that threshold value to calculate the error. -So, we can obtain error value with the following code: +So, the error is the following: .. tab-set:: @@ -57,38 +53,21 @@ So, we can obtain error value with the following code: .. code-block:: python - error = reflectance.get_left() - 0.5 + # Input your threshold value here: + threshold = 0.5 + error = reflectance.get_right() - threshold .. tab-item:: Blockly .. image:: media/set_error.png :width: 300 -Above, we subtract 0.5 to *normalize* the reflectance value: the error is +Above, we subtract the threshold to center the reflectance value, so that the error is negative when the robot is too far left and needs to turn right, and positive -when the robot is too far right and needs to turn left. Let's put that code into -the test. We can put it in the loop, print out the error at each iteration, and -move the robot around the line to see how the error changes. The code is as -follows: - -.. tab-set:: - - .. tab-item:: Python - - .. code-block:: python - - from XRPLib.defaults import * - from time import sleep +when the robot is too far right and needs to turn left. - while True: - error = reflectance.get_left() - 0.5 - print("Error: ", error) - sleep(0.1) # This sleep makes the loop run 10 times every second - - .. tab-item:: Blockly - - .. image:: media/print_error.png - :width: 300 +If you want to test to make sure the error is being calculated correctly, you +can print the error to the console in a loop. Implementing proportional control --------------------------------- @@ -103,74 +82,114 @@ Based on the computed error, we want that to determine how much the robot turns. This image illustrates how the error impacts how much we want to turn. Remember: making the robot turn is simply setting the left and right motors to different -efforts. So, the solution is to set a base effort, say, 50% effort, that both -motors move at when the error is at 0. Then, have the calculated error influence -the difference in efforts between the two motors. As explained through code: +efforts. Similarly to how we did wall following, we'll need to apply a base speed +and use the error to adjust it as needed. .. tab-set:: - .. tab-item:: Python + .. tab-item:: Hide - .. code-block:: python + Now it's your turn. Try and implement proportional control for line following using the error. + If you need a hint or want to view the solution, take a look at the next tabs. - drivetrain.set_effort(base_effort - KP * error, base_effort + KP * error) + .. tab-item:: Hint - .. tab-item:: Blockly - - .. image:: media/set_effort_error.png - :width: 300 + .. tab-set:: -This would be run inside the loop. The base_effort represents the average effort -of the motors, no matter how much the robot turns. KP scales how much the robot -should turn based on the error - a higher KP means the robot will react more -violently to small deviations in error. + .. tab-item:: Python -Let's do a quick check to make sure the code makes sense. We assume base_effort -= 0.5 and KP = 1. If the reflectance reads whitish-grey and yields a value of -around 0.25, the error would be -0.25, meaning that the left motor's effort is: + .. code-block:: python -.. math:: + drivetrain.set_effort(base_effort - KP * error, base_effort + KP * error) - 0.5 - 1 \cdot -0.25 \\ - \begin{align} - & = 0.5 + 0.25 \\ - & = 0.75 - \end{align} + .. tab-item:: Blockly + + .. image:: media/set_effort_error.png + :width: 300 -and the right motor's speed is: + This would be run inside the loop. The base_effort represents the average effort + of the motors, no matter how much the robot turns. KP scales how much the robot + should turn based on the error - a higher KP means the robot will react more + to smaller deviations in error. -.. math:: + Let's do a quick check to make sure the code makes sense. We assume base_effort + = 0.5 and KP = 1. If the reflectance reads whitish-grey and yields a value of + around 0.25, the error would be -0.25, meaning that the left motor's effort is: - 0.5 + 1 \cdot -0.25 \\ - \begin{align} - & = 0.5 - 0.25 \\ - & = 0.25 - \end{align} + .. math:: -Motor efforts of 0.75 and 0.25 would indicate a turn to the right, and the code -does as desired. + 0.5 - 1 \cdot -0.25 \\ + \begin{align} + & = 0.5 + 0.25 \\ + & = 0.75 + \end{align} -This is a video illustrating line following with one-sensor control. Notice the -smoother tracking compared to on/off control, yet the robot is still unable to -recover from the last bend, because even a small amount of strafing from the -line results in the robot completely losing where it is. Also, the KP value was -not equal to 1 here; it's up to you to figure out the best KP value for your -bot. + and the right motor's speed is: + .. math:: -.. figure:: media/proportional_line_following.gif - :align: center + 0.5 + 1 \cdot -0.25 \\ + \begin{align} + & = 0.5 - 0.25 \\ + & = 0.25 + \end{align} + + Motor efforts of 0.75 and 0.25 would indicate a turn to the right, and the code + does as desired. + + .. tab-item:: Solution + + .. tab-set:: + + .. tab-item:: Python + + .. code-block:: python + + # Input your threshold value here: + threshold = 0.5 + base_effort = 0.5 + KP = 1 + while True: + error = reflectance.get_right() - threshold + drivetrain.set_effort(base_effort + KP * error, base_effort - KP * error) + time.sleep(0.01) + + .. tab-item:: Blockly + + .. image:: media/one_edge_line_follow.png + :width: 1000 + + Just to review, let's take this code line-by-line and make sure we understand what's going on. + + :code:`threshold = 0.5` sets the threshold value to 0.5. + This is the value that the reflectance sensor will use to determine whether the robot is on or off the line. + This is a tuned value that may differ depending on your line, sensor, and lighting. + + :code:`base_effort = 0.5` sets the base effort to 0.5. + This is the average effort of the motors, which controls how fast we want the robot to follow the line. + A higher base effort means the robot will follow the line faster, but also means the robot will be less able to recover from errors. + + :code:`KP = 1` sets the KP value to 1. + This is the proportional constant, which controls how much the robot reacts to the error. + This is our main tuning value, and you'll have to try different values to see what works best for your robot. + + :code:`error = reflectance.get_right() - threshold` calculates the error. + As we discussed earlier, the error basically is our measurement of how far the robot is from the line. + + :code:`drivetrain.set_effort(base_effort + KP * error, base_effort - KP * error)` sets the motor efforts. + This is where we actually use the error to determine how much the robot turns. + A positive error means we are too far left, and need the left power to be higher than the right power, + and a negative error means we are too far right, and need the right power to be higher than the left power. + +This is a video illustrating line following with one-sensor control. Notice the +smoother tracking compared to on/off control, yet the robot is still unable to +recover perfectly, because even a small amount of strafing from the +line results in the robot completely losing where it is. +We'll look at how to improve this in the next section. +Also, the KP value was not equal to 1 here; it's up to you to figure out the best +KP value for your bot. - XRP following a line with proportional control. The robot would not be able - to follow a curved line this quickly using on-off control! +.. error:: -.. admonition:: Try it out - - Write code for the robot to follow the line with proportional control, as - shown in the video above. Note: this isn't much more than calculating error - as shown in the previous section then integrating the above line of code in - a loop. + Missing one-sensor line following video - Play around with the value of KP. How does a higher or lower KP affect the - amount of oscillation when following the line, and how responsive the robot - is to curved lines? What is the optimal value of KP? \ No newline at end of file diff --git a/course/line_following/proportional_control_with_two_sensors.rst b/course/line_following/proportional_control_with_two_sensors.rst index d40a2c2..25ccdce 100644 --- a/course/line_following/proportional_control_with_two_sensors.rst +++ b/course/line_following/proportional_control_with_two_sensors.rst @@ -10,7 +10,7 @@ crosses over the center of the line, it's game over. Desired steering actions based on what the sensor sees. -The issue is - the robot has no way of knowing which side of the line it is +The issue is - the robot still has no way of knowing which side of the line it is following at all! If it sees the right edge of the line, it will assume it still is detecting the left edge, and thus keep turning right past the point of no return! @@ -49,27 +49,33 @@ Sensors read ~0 and ~1. Robot knows it is on the left side and turns right. Sensors read ~0.5 and ~0.5. Robot knows it is on the center and goes straight. -The other two major categories you can extrapolate for yourself. +The other two cases you can extrapolate for yourself. So, how can we effectively combine the readings of the left and right reflectance sensors using proportional control to have the robot follow the -line? There's quite an elegant solution that I encourage for you to try to -figure out yourselves before the answer is revealed. +line? -Implementation --------------- .. tab-set:: - .. tab-item:: Python + .. tab-item:: Hide - .. code-block:: python + There's a few ways to do this, but there's a really elegant solution that + we'll use here. Try to figure it out yourself before reading on! - error = reflectance.get_left() - reflectance.get_right() + .. tab-item:: Solution: - .. tab-item:: Blockly + .. tab-set:: - .. image:: media/error.png - :width: 300 + .. tab-item:: Python + + .. code-block:: python + + error = reflectance.get_left() - reflectance.get_right() + + .. tab-item:: Blockly + + .. image:: media/error.png + :width: 300 At the beginning this line of code may not make a lot of sense - but let's dissect it. Remember our previous convention of positive error meaning the robot @@ -102,40 +108,64 @@ sensor values are the same and so the error is 0, and as the robot starts drifting towards either direction, the magnitude of the error increases and thus the robot compensates accordingly. -The most interesting case is when the robot is completely off the line - in this +When the robot is completely off the line - in this case, both sensors read white, leaving an error of 0, and so the robot just goes straight. Given that the robot wouldn't know which direction to compensate if it -was completely off the line, this seems like a reasonable result. +was completely off the line, this seems like a reasonable result. +The same behavior occurs if the robot is completely on the line. -And so, our final code is as follows: +There is one last case to cover. What happens if the robot is only slightly off the line? + +.. math:: + + \begin{align} + \text{error} & = 1 - 0.5 \\ + & = 0.5 + \end{align} + +Well in this case, the error will be smaller, which means that a smaller correction is needed. +This is an important property of proportional control - the further the robot is +from the desired state, the more it will try to correct itself, +but will only slightly correct itself for small errors, which minimuxes the chanse of overshooting the target. + +Let's try it out! .. tab-set:: - .. tab-item:: Python + .. tab-item:: Hide + + Try to figure out how to use this error to line follow before reading on! + + .. tab-item:: Solution - .. code-block:: python + .. tab-set:: - from XRPLib.defaults import * + .. tab-item:: Python - # Try different values for KP and base_effort to get things working smoothly - KP = 1 - base_effort = 0.5 + .. code-block:: python - while True: - error = reflectance.get_left() - reflectance.get_right() - drivetrain.set_effort(base_effort - KP * error, base_effort + KP * error) - - .. tab-item:: Blockly - - .. image:: media/set_effort_program.png - :width: 550 + from XRPLib.defaults import * + + # Try different values for KP and base_effort to get things working smoothly + KP = 1 + base_effort = 0.5 + + while True: + error = reflectance.get_left() - reflectance.get_right() + drivetrain.set_effort(base_effort - KP * error, base_effort + KP * error) + + .. tab-item:: Blockly + + .. image:: media/set_effort_program.png + :width: 550 Here's what that looks like. Note that KP used in this video was not equal to 1: -.. error:: - - TODO add video +.. figure:: media/proportional_line_following.gif + :align: center + XRP following a line with proportional control. The robot would not be able + to follow a curved line this quickly using on-off control! .. admonition:: Try it out diff --git a/course/line_following/staying_in_the_circle.rst b/course/line_following/staying_in_the_circle.rst deleted file mode 100644 index e9b65e9..0000000 --- a/course/line_following/staying_in_the_circle.rst +++ /dev/null @@ -1,24 +0,0 @@ -Staying in the Circle -===================== - -Your robot is now capable of stopping when it sees a line. You can use this -functionality to keep your robot trapped inside a circle! You'll find out why -you'd want to do this in the next module, which is a challenge activity! - -Let's break this problem down into a series of steps: - -#. Drive forward until a line is seen (the edge of the circle) -#. Stop driving so that the robot doesn't leave the circle -#. Turn around -#. Repeat - -You already have code which does steps 1 and 2 (``drive_until_line()``), and you -learned back in the robot driving module how to do step 3 -(``drivetrain.turn()``, see :doc:`/course/driving/calling_drive_functions` for a -refresher) - -.. admonition:: Try it out - - Write an infinite loop which keeps the robot in a circle. Try out different - angles when turning around. You may want to try not turning a full 180 - degrees. \ No newline at end of file diff --git a/course/line_following/stopping_at_a_line.rst b/course/line_following/stopping_at_a_line.rst index 92abde3..696f2c1 100644 --- a/course/line_following/stopping_at_a_line.rst +++ b/course/line_following/stopping_at_a_line.rst @@ -22,12 +22,12 @@ certain distance: from XRPLib.defaults import * while drivetrain.get_left_encoder_position() < 20: - drivetrain.set_speed(5, 5) + drivetrain.set_speed(10, 10) drivetrain.stop() In this code, the condition being checked is ``drivetrain.get_left_encoder_position() < 20`` meaning that the robot will - drive forward at 5 cm/s until the left encoder reads a distance of 20 cm. This + drive forward at 10 cm/s until the left encoder reads a distance of 20 cm. This code can be easily modified to replace the current condition with a condition that uses the function you wrote. @@ -40,7 +40,7 @@ certain distance: :height: 3ex In this code, the condition being checked is |ico1| meaning that the robot will - drive forward at 5 cm/s until the left encoder reads a distance of 20 cm. This + drive forward at 10 cm/s until the left encoder reads a distance of 20 cm. This code can be easily modified to replace the current condition with a condition that uses the function you wrote. @@ -59,17 +59,84 @@ Once you've tested your code and proved it to meet the challenge, make a new function called ``drive_until_line()`` and put your code in it. Don't delete this function, as you'll need it later! -Challenge activity ------------------- +Challenge activity - Counting Lines +----------------------------------- For an added challenge, try to write code which makes the robot capable of driving over and stopping at several lines. The robot should drive over a line, stop for some amount of time, say two seconds, and then start driving again -until it sees another line. This cycle should repeat forever. +until it sees another line. Then, modify your code to stop after having seen 5 lines. .. tip:: You'll need to write some logic which handles the robot driving *off* of the line too! Your code from the main activity might not be enough to handle this! Think about what your code would do if it started out *already on* a - line. \ No newline at end of file + line. + +Challenge Activity - Staying in the Circle +------------------------------------------ + +Your robot is now capable of stopping when it sees a line. You can use this +functionality to keep your robot trapped inside a circle! This is meant to be a +challenge activity, so you'll need to figure out how to do it on your own. +Start by breaking down the problem into smaller steps + +.. tab-set:: + + .. tab-item:: Hide + + Press the other tab to see a hint. + + .. tab-item:: Hint + + #. Drive forward until a line is seen (the edge of the circle) + #. Stop driving so that the robot doesn't leave the circle + #. Turn around + #. Repeat + + .. tab-item:: Solution + + .. tab-set:: + + .. tab-item:: Python + .. code-block:: python + + def is_over_line(): + # This a slightly modified version of the example from the previous section! + # We now are checking that the average of the two sensors is above the threshold. + line_threshold = 0.75 + return (reflectance.get_right() + reflectance.get_left())/2 > line_threshold + + while True: + # Drive forward until a line is seen + drivetrain.set_effort(0.5, 0.5) + # Check if robot is over a line + if is_over_line(): + # Stop and turn around + drivetrain.turn(180) + + .. tab-item:: Blockly + + TODO: Add blockly code + .. .. image:: media/error.png + .. :width: 300 + + +You already have code which does steps 1 and 2 (``drive_until_line()``), and you +learned back in the robot driving module how to do step 3 +(``drivetrain.turn()``, see :doc:`Calling Drive Functions ` for a +refresher) + +.. admonition:: Tip + + Try out different angles when turning around. + You may want to try not turning a full 180 degrees. + +.. admonition:: Extension + + If you want to give yourself an extra challenge, turn this into a sumo competition! + Put two robots in the center of the same circle facing opposide directions, + and modify your code to try to push the other robot out of the circle while staying in yourself. + You can use the distance sensor to detect the other robot. + There's many way to optimize a sumo robot program, so try to be creative! \ No newline at end of file diff --git a/course/line_following/sumo.rst b/course/line_following/sumo.rst deleted file mode 100644 index 7ff7c71..0000000 --- a/course/line_following/sumo.rst +++ /dev/null @@ -1,22 +0,0 @@ -Challenge: Sumo-Bots! -===================== - -.. image:: media/sumo.png - -It's time for SUMO bots! Two XRP bots battle it out in the ring in a completely -autonomous match to push the other robot outside of the ring. - -Robots start facing away from each other in the orientation above, and have one -minute to knock the other robot outside. They may utilize distance sensors to -detect the presence and location of the other robot, and use the reflectance -sensors to keep themselves inside the ring. - -.. hint:: - - A basic SUMO-bots program may consist of a robot continuously point turning - until an enemy robot is found with the distance sensor, and then charging at - the robot until the black line is detected, so that the robot stays inside - the ring. However, worthy extensions include: aligning the robot to be - perpendicular from the black line so that the robot is not misaligned, and - devising an algorithm to attack the opponent robot from the side to avoid a - head-on collision and gain more leverage. \ No newline at end of file diff --git a/course/line_following/understanding_the_sensor.rst b/course/line_following/understanding_the_sensor.rst index 473b789..914e3e6 100644 --- a/course/line_following/understanding_the_sensor.rst +++ b/course/line_following/understanding_the_sensor.rst @@ -101,7 +101,34 @@ is not seeing a line. (value above the threshold) or ``False`` if it does not. Don't delete this function when you're done, because you'll use it for the rest of the module! - Use the webserver to log the result of calling your function in an infinite - loop. Move your robot around a surface with lines on it to make sure it + Use :code:`print()` to view the result of calling your function in an infinite + loop (Or use the webserver to log values). + Move your robot around a surface with lines on it to make sure it always returns the correct value based on what the sensor is seeing. If you - are getting incorrect values, adjust your threshold value. \ No newline at end of file + are getting incorrect values, adjust your threshold value. + +.. tab-set:: + +.. tab-item:: Hide + + Give it a try yourself before checking the solution! + +.. tab-item:: Solution: + + .. tab-set:: + + .. tab-item:: Python + + .. code-block:: python + + def is_over_line(): + # This is a tuning value! Depending on your exact line, lighting, and robot, + # the value of what counts as a line may differ! + line_threshold = 0.75 + return reflectance.get_right() > line_threshold + + .. tab-item:: Blockly + + TODO: Add blockly code + .. .. image:: media/error.png + .. :width: 300 \ No newline at end of file diff --git a/index.rst b/index.rst index 89b3ebb..48319fd 100644 --- a/index.rst +++ b/index.rst @@ -91,8 +91,6 @@ ways that make it available to all. course/line_following/index course/line_following/understanding_the_sensor course/line_following/stopping_at_a_line - course/line_following/staying_in_the_circle - course/line_following/sumo course/line_following/on_off_control course/line_following/proportional_control course/line_following/proportional_control_with_two_sensors