Skip to content

Line following improvements #132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Binary file removed course/line_following/media/print_error.png
Binary file not shown.
Binary file removed course/line_following/media/sumo.png
Binary file not shown.
119 changes: 77 additions & 42 deletions course/line_following/on_off_control.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand All @@ -34,47 +33,18 @@ 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).

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
Expand All @@ -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!
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
17 changes: 10 additions & 7 deletions course/line_following/parking_garage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading