Try Your Hand at Driving RVR with Your Keyboard
One of the best ways to get started with your RVR is by learning to drive using your keyboard! Gamers rejoice, as your beloved ASDW keys become your "keys" to letting your RVR know where it is you want it to go! 🏎️
In this tutorial, you'll use a Raspberry Pi mounted on your RVR, as well as your keyboard (to avoid getting tangled up in wires galore ➰, we would recommend that you SSH into your Raspberry Pi, though you could do this with a keyboard wired into your Raspberry Pi) to control your RVR using an asynchronous python script 🕹️.
If you haven't already connected your Raspberry Pi to your RVR, go ahead and check out our helpful docs on how to get up and running before attempting to follow along with this example (doing so will get most of the hardware setup completed already, as well 😉).
This intermediate tutorial should take about 20 minutes to complete (if you've already set up your Raspberry Pi and connected it to the RVR).
In additon to the materials necessary to connect the Raspberry Pi to the RVR, we'll need:
- A short USB-to-Micro USB cable (to allow the RVR to provide the Raspberry Pi with power from its USB port)
If you've gone through our Raspberry Pi Set Up Docs, you will have already downloaded/cloned the needed code for this example, in addition to installed the dependencies necessary for your Raspberry Pi to communicate with your RVR. Because the Raspberry Pi examples we have set up rely on files located throughout the file structure (not just the file we walk through below), we recommend that you use the version of the file included in those you downloaded/cloned from our GitHub, rather than trying to write the file from scratch as we walk through it together below (with that said, feel free to play with/add to the version you downloaded; we always love to see how creative our users are 🥰).
You can find the file for this example at 👩💻/projects/keyboard_control/drive_with_wasd_keys.py, in the file structure you downloaded; we'll repeat this later as we talk about how to actually run the code, but figured you might like to have the file in front of you as you follow along here...
Let's get started with our imports. Most of these will be similar across all of our examples. One of the elements that is unique about this example is the
Keyboard Helper is a helper file 🙋 that we created to simplify the code in this file that references keys on your keyboard, making communicating with the RVR via the keyboard a bit cleaner and easier. You can find the full
KeyboardHelper code here.
Line 3 of the code below is what allows us to pull from elsewhere in the file structure. It references files that are two layers above (
../../), as well as those within folders at that level, and appends the absolute path of the directory with the name after "
from" in the imports on lines 7-9:
import sys import os sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../../'))) import asyncio from projects.keyboard_control import KeyboardHelper from sphero_sdk import SerialAsyncDal from sphero_sdk import SpheroRvrAsync
Next, we'll initialize our global variables, including a specific asynchronous
loop 🔄 and defining
rvr 🤖 so that we can use it to call commands off of, later on:
key_helper = KeyboardHelper() break_loop = False red = [0xFF, 0x0, 0x0] blue = [0x0, 0x0, 0xFF] driving_keys = [119, 97, 115, 100, 113, 32] speed = 64 loop = asyncio.get_event_loop() rvr = SpheroRvrAsync( dal=SerialAsyncDal( loop ) )
As we dive into the actions, we'll start by setting some colors 🎨 Our first function will set all of the LEDs:
async def set_all_leds(rgb_triples): await rvr.set_all_leds_with_32_bit_mask( 0x3FFFFFFF, rgb_triples ) await asyncio.sleep(.01)
Second, we'll set some functions to to flip the LEDs back and forth between blue and red:
def construct_blue(): global red global blue colors =  for x in range(10): if (x % 2) == 0: colors.extend(red) else: colors.extend(blue) return colors def construct_red(): global red global blue colors =  for x in range(10): if (x % 2 - 1) == 0: colors.extend(red) else: colors.extend(blue) return colors
We'll also create a function to cause the lights to flash red and blue 🚔, using our
async def strobe_lights(): lights_red = True while True: lights_red = not lights_red if lights_red: rgb_red = construct_red() await set_all_leds(rgb_red) else: rgb_blue = construct_blue() await set_all_leds(rgb_blue) await asyncio.sleep(0.25)
Because the RVR has treads on each side, we can set the mode and speed of each, using
raw_motors. The following two functions control starting and stopping this function; you'll notice when we stop, we set all values to
async def run_raw_motors(left_mode, left_speed, right_mode, right_speed): await rvr.raw_motors(left_mode, left_speed, right_mode, right_speed) async def stop_raw_motors(): await rvr.raw_motors(0, 0, 0, 0)
We get to
drive now!! The following function allows you to assign keys (in this case, W ☝️, A 👈, S 👇 and D 👉) to control the direction that the RVR heads in, by attaching it to the
run_raw_motors method we defined above, associating a different heading with each key. The
speed was set in the global variables we initiated in the beginning and can be reassigned there. The following listens for one of the assigned keys and reacts with the corresponding behavior:
async def drive(): global loop global break_loop global speed while key_helper.key_code not in driving_keys: await asyncio.sleep(0.05) print('Drive with key code: ', str(key_helper.key_code)) if key_helper.key_code == 119: # W await run_raw_motors(1, speed, 1, speed) elif key_helper.key_code == 97: # A await run_raw_motors(2, speed, 1, speed) elif key_helper.key_code == 115: # S await run_raw_motors(2, speed, 2, speed) elif key_helper.key_code == 100: # D await run_raw_motors(1, speed, 2, speed) elif key_helper.key_code == 113: break_loop = True elif key_helper.key_code == 32: # SPACE await stop_raw_motors() key_helper.key_code = -1
The following three functions are more "functional" than "fun" 🤓, but are still very important! They allow us to
wake the RVR up when we are ready to start interacting with it (since we can ask the RVR for information about itself when it is in soft sleep, but we need to wake the RVR it before making any mechanical requests), maintain our ability to interact with the bot and flash its lights, and know when to continue and when to stop:
async def main(): await rvr.wake() while True: await drive() def run_loop(): global loop loop.run_until_complete( asyncio.gather( main(), strobe_lights() ) ) if __name__ == '__main__': loop.run_in_executor(None, key_helper.get_key_continuous) try: run_loop() except KeyboardInterrupt: print('Exiting...') finally: key_helper.end_get_key_continuous() exit(1)
The full code can be found on GitHub.
Running the Code!
To run the code, you simply need to go to your terminal,
cd into the correct directory (/keyboard_control) and type:
If you've taken our advice and decided to use SSH to access your fancy, wireless RVR 💁, you'll just need to take a few extra steps to create the connection between your RVR and the machine you are SSHing into it with before running the above command.
Write down the IP address it spits out and let's unplug the mouse/keyboard/monitor from your Raspberry Pi and jump over to the machine you'll be using to control your RVR!
On your remote machine (which must be on the same Wifi network you set your Raspberry Pi to connect to), you'll also want to jump into the terminal, where you'll use the IP address you just grabbed and type:
If it is successful in finding your Raspberry Pi using its IP address (ie if you are on the correct network and typed the correct IP address (and your Raspberry Pi is powered on and has been for at least 15 seconds)), you'll be prompted to type in the password to your Raspberry Pi. As you are doing so, you won't get an indication that the terminal is registering your keystrokes, but that is just to make you feel extra safe, so dangerous hackers can't see how long your password is and steal it 🦹.
If all went to plan with that, you should get a success message and be ready to
cd into your /keyboard_control folder in your terminal and run:
Once this is running (ie the command above didn't result in an error), you can start using your W ☝️, A 👈, S 👇 and D 👉 keys to control your RVR and Spacebar 🛑 to stop it, all from the terminal!
Once you are finished playing, you'll want to make sure you properly shut down your Raspberry Pi. You can do this by pressing Ctrl + C and then any other key to kill the program and then turning off your Raspberry Pi by running:
sudo shutdown now
Try to improve your Keyboard Controlled RVR! Here are some ideas to get you started:
- Play around with which keys control the RVR.
- Add more behaviors (like color changes!) triggered by additional keys.
- Use the sensors to trigger behaviors/ create an obstacle-style game where you have to navigate around colored pieces of paper on the floor.