Autonomous RC Car Part 2
So far in parts zero and one we’ve talked mostly about hardware. Let’s dive in to the softer side of robots.
Hint: If you’re optimizing for time, do this software work early on since the compilation steps that a very long time.
Raspberry Pi
Let’s assume we have a fresh Raspberry Pi 2 B+, a Raspberry Pi Camera module, and a 32gb SD card.
- Download Raspian Stretch.
- Download and install Etcher. This is an easy to use graphical tool for writing images to flash drives.
- Use Etcher to flash the Raspian Stretch image to your drive.
- Attach your Raspberry Pi Camera ribbon cable to the connector labeled ‘camera’ on the Pi.
- Insert the drive and boot up your RPi.
- Unlike previous versions, Raspian Stretch suggests you change the root password at first boot. Good feature!
Configuration Changes
Normally I would prefer to script these kinds of changes so they’re repeatable and reliable. For this one instance I’m going to break the cattle/pets rule and manually configure this host.
Configure Wireless Networking
Using sudo raspi-config
, configure ‘Network Options’
Configure you’re wifi network.
I’ll skip showing your my wireless network name and passphrase. Just … because.
Set a static IP
Edit your ‘/etc/dhcpcd.conf’ file to specify a static ip for your wireless interface. The entries to add a static IP should be in the file and commented out. You can uncomment and edit the few lines necessary. It should look something like this:
Note: Don’t do this with the ‘/etc/network/interfaces’ like previous versions of Raspian. Your changes will be overwritten and you will cry.
Why set a static IP for the wireless interface and not eth0? Later on we’ll have this thing roaming around on the back of a robot. WiFi is useful. And when you want to pull large amounts of data off of the device, WiFi is terrible. Clicking in an ethernet cable and letting the Pi find a DHCP address makes for fast connections. I’ve found this setup to be convenient, YMMV.
Enable the Camera
Run sudo raspi-config
, select ‘Interfacing Options’:
The first option will be to ‘enable/disable’ the camera:
Test the camera
You can take a picture with the camera with the included ‘raspistill’ command. raspistill -o output.jpg
will open the camera wait a few seconds, and take a picture. If you’re running this over the network then you’ll notice the program pause a moment and then return. You may start thinking: What was it doing all that time? If you’re running by typing directly on the Pi and watching the HDMI output, then you’ll notice a graphical window pop up and show the current output from the camera, then close and save the image. It makes a lot more sense when you see the direct video output.
OpenCV
You’ll really want to be on a hard LAN for this step. The package updates may take a while depending on your version drift. More importantly the OpenCV compilation step takes 3.5–4 hours. We’ll add a few optimization steps here, but even then you could probably brew a batch of beer while this one package compiles.
Start by updating apt packages and upgrading installed packages:
sudo apt-get update
sudo apt-get upgrade
Then install all the dependencies needed for OpenCV. Some of these may look unexpected if you’re familiar with packaged versions of OpenCV. However, we’re going to be installing some of the optional extra features of OpenCV, so you do actually need ‘gfortran’, ‘virtualenv’, etc.
sudo apt-get install build-essential cmake unzip pkg-config libjpeg-dev libpng-dev libtiff-dev libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev libatlas-base-dev gfortran python3-dev virtualenv
Download both OpenCV and the contrib packages:
wget -O opencv.zip https://github.com/opencv/opencv/archive/4.0.1.zip
wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.0.1.zip
unzip opencv.zip && unzip opencv_contrib.zip
Let increase the swap size to speed up the compilation.
- Edit ‘/etc/dphys-swapfile’
- Change the ‘CONF_MAXSWAP’ variable to 2048.
Restart the swap service so the new value takes effect
sudo /etc/intid.dphys-swapfile stop
sudo /etc/intid.dphys-swapfile start
Here I suggest you use a python Virtual Environment. Yes, I know pipenv
is great, but it’s too slow to run on a Raspberry Pi. You have to mess around with timeouts and it’s just not worth it. Use virtualenv
like our forebears and it will be fine.
mkdir robocar && cd robocar
virtualenv -p python3 .
source bin/activate
This last step will activate the python virtual environment, encapsulate your pip libraries, and make sure the correct versions of python and pip are used. So, let’s use it to install numpy
. This is the only python dependency we should need to compile OpenCV.
pip install numpy
Compiling OpenCV
This is the big one. Head back to your opencv
directory, make a build directory to hold the cmake output, and run the compile step.
cd ~/opencv
mkdir build && cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-4.0.1/modules \
-D ENABLE_NEON=ON \
-D ENABLE_VFPV3=ON \
-D BUILD_TESTS=OFF \
-D OPENCV_ENABLE_NONFREE=ON \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D BUILD_EXAMPLES=OFF ..make -j4
This last make command is what will take a long time. Even after the output says it’s [100%]
done, the linker will continue to run for most of an hour. The -j4
will let it use all four cores of the Raspberry Pi. The last step is to install the compiled libraries and link them to our Python environment.
sudo make install
sudo ldconfig
cd ~/robocar && ln -s /usr/local/lib/python3.5/site-packages/cv2/python-3.5/cv2.cpython-35m-arm-linux-gnueabihf.so lib/python3.5/site-packages/cv2.so
When you’re done, remember to edit ‘/etc/dphys-swapfile’ again and return your swap value from 2048 to 100 megabytes. Reboot the swap service like before so the changes will take effect.
Test OpenCV
Make sure you’re still using ‘robocar’ the virtualenv from earlier and use the Python REPL to test your OpenCV installation:
You’re good!
::Whew::
That’s enough for today. When we come back we’ll test our Python setup and see about getting some images from the camera into OpenCV. We’ll need to do some pre-processing to store our training telemetry, so we’ll get to that in the next steps.
Update: Continue on to Part 3.