Go Driving
Let's make RVR+ and RVR move!
important
During this tutorial, your RVR+/RVR will be driving. We strongly recommend that you set up SSH access on your Pi and mount it securely to the RVR+/RVR development plate before continuing.
Start with a standard template
Let's go ahead and make a new script in ~/rvr-projects
and name it drive_rvr.py
. We'll drop in the following standard boiler-plate code as a starting point. (This will look familiar from the previous tutorial):
import sys # Allows us to use sys.path.append below
import time # Allows us to insert delays in our script
# sys.path tells the interpreter where to look for modules.
# Tell it to look in the SDK directory as well.
sys.path.append('/home/pi/sphero-sdk-raspberrypi-python')
# We're
from sphero_sdk import SpheroRvrObserver
# Instantiate (create) a SpheroRvrObserver object
rvr = SpheroRvrObserver()
# This tells the Python interpreter that we are defining
# a function named main that takes no arguments
def main():
# Make sure RVR is awake and ready to receive commands
rvr.wake()
# Wait for RVR to wake up
time.sleep(2)
# Now RVR is ready for action. Add new stuff here.
# This block gets executed if the interpreter is directly running this
# file, not importing it as a module. It's a good general practice
if __name__ == '__main__':
try:
# Stuff we want to do (in this case, just call our main function)
main()
except KeyboardInterrupt:
# What to do if there's a keyboard interrupt (ctrl+c) exception
# In this case, we're just going to print a message
print('\nProgram terminated with keyboard interrupt.')
finally:
# What to do before we exit the block
rvr.close()
You can now use this template to write driving programs, just by starting with your commands under time.sleep(2)
.
Add In Driving
For this tutorial, we're going to use the drive_control
, which is a helper class within SpheroRvrObserver
designed to make basic driving operations simpler.
- To start we want to navigate to below
time.sleep(2)
. We'll be driving RVR by specifying a heading (0-359 degrees) and a speed to drive along that heading. When RVR powers on, its initial heading will be 0. By using the following command it won't matter if you don't remember which way it was pointing when you powered it on. We can reset the heading to zero like so:
# Resetting our heading makes the current heading 0
rvr.drive_control.reset_heading()
Next we can go ahead and do some driving! Let's add a few method calls to our program:
# This helper method drives RVR forward on the specified heading # and returns to our main function when the specified time has # elapsed. This means it is a "blocking" function. rvr.drive_control.drive_forward_seconds( speed=64, # This is out of 255, where 255 corresponds to 2 m/s heading=0, # Valid heading values are 0-359 time_to_drive=1 # Driving duration in seconds ) # This version drives RVR in reverse rvr.drive_control.drive_backward_seconds( speed=64, # This is out of 255, where 255 corresponds to 2 m/s heading=0, # Valid heading values are 0-359 time_to_drive=1 # Driving duration in seconds )
The entire program should now look like this:
import sys # Allows us to use sys.path.append below import time # Allows us to insert delays in our script # sys.path tells the interpreter where to look for modules. # Tell it to look in the SDK directory as well. sys.path.append('/home/pi/sphero-sdk-raspberrypi-python') # Now that it can find the SDK, we can import some useful SDK modules from sphero_sdk import SpheroRvrObserver # Instantiate (create) a SpheroRvrObserver object rvr = SpheroRvrObserver() # This tells the Python interpreter that we are defining # a function named main that takes no arguments def main(): # Make sure RVR is awake and ready to receive commands rvr.wake() # Wait for RVR to wake up time.sleep(2) # Resetting our heading makes the current heading 0 rvr.drive_control.reset_heading() # This helper method drives RVR forward on the specified heading # and returns to our main function when the specified time has # elapsed. This means it is a "blocking" function. rvr.drive_control.drive_forward_seconds( speed=64, # This is out of 255, where 255 corresponds to 2 m/s heading=0, # Valid heading values are 0-359 time_to_drive=1 # Driving duration in seconds ) # Now back up. rvr.drive_control.drive_backward_seconds( speed=64, # This is out of 255, where 255 corresponds to 2 m/s heading=0, # Valid heading values are 0-359 time_to_drive=1 # Driving duration in seconds ) # This tells the interpreter to run our main() function if it is running this script # directly (and not importing it as a module from elsewhere) if __name__ == '__main__': try: # Stuff we want to do (in this case, just call our main function) main() except KeyboardInterrupt: # What to do if there's a keyboard interrupt (ctrl+c) exception # In this case, we're just going to print a message print('\nProgram terminated with keyboard interrupt.') finally: # What to do before we exit the block rvr.close()
Let's run our program and see what happens.
pi@raspberrypi:~/rvr-projects $ python3 drive_rvr.py
Your RVR+/RVR should drive forward for 1 second, then reverse for 1 second. Feel free to play around with different heading, speed, and time values, or add extra movements. Make it your own!
note
If RVR+/RVR is stationary and commanded to drive along a new heading, it will first turn in place to face that heading, then drive forward or backward. The turn-in-place operation will be included in the driving time, so the turn angle will affect driving distance.
Driving by distance can be done with far greater precision using the drive to position controller, though the usage is more complex. Check
~/sphero-sdk-raspberrypi-python/getting_started/observer/driving/drive_to_position_si.py
for an example.