How to remote control your car via ROS-Mobile App
This blog shows my current progress on turning a remote controlled car into an autonomous robot. A RaspberryPi 4 runs ROS Noetic and sends pwm signals to the throttle and steering of the rc car via a 16 channel servo driver board. The goal is to teach the robot how to navigate autonomously in its environment to a desired point. Follow this project on GitHub via https://github.com/moritzboeker/ros_raspi_car
Steps to remote control your robot via the ROS-Mobile App:
- Install an image with Ubuntu and ROS Noetic from https://learn.ubiquityrobotics.com/noetic_pi_image_downloads on your Raspberry Pi 4
- ROS package
cmd_vel_to_pwm
(requires ROS package ros-pwm-pca9685)- ROS node
cmd_vel_to_ackermann_drive
subscribes the velocity command via ROS topiccmd_vel
asTwist
, converts it to the Ackermann-suitable typeAckermannDriveStamped
and publishes it to/ackermann_cmd_topic
- ROS node
ackermann_drive_to_pwm
Subscribes to ROS topicackermann_cmd_topic
asAckermannDriveStamped
, converts it to PWM values for servo motors and publishes it asInt32MultiArray
to/command
, from there it is sent to the PWM board and eventually to the servo motors
- ROS node
- Download & install & launch ROS-Mobile App for Android on your phone
- Enter the IP-address of your Raspberry Pi and connect
- method 1 (at home): Raspberry Pi and your phone are connected to same local Wifi, the Ubuntu image from Ubiquity does so automatically if your local Wifi is present
- method 2 (on field): Raspberry Pi creates its own access point and your phone connects to it, the Ubuntu image from Ubiquity does so automatically if your local Wifi is NOT present
- Add a joystick widget
- Enter the IP-address of your Raspberry Pi and connect
- Remote control your car and enjoy!
How to add odometry to a remote controlled car
Your are the feedback of the control loop
When you drive around your car via the remote, the harder you press the throttle the faster the vehicle moves. With your own eyes you see how fast the car is going. Unconsiously, you then compare its current speed with the velocity you intended the car to run with. Based on this comparison you realize whether it is driving “too fast” or “too slowly” and then initiate the control action by releasing the throttle or pressing it further, respectively. In terms of a control loop, your eyes therefore represent the sensor feedback and your mind is the controller telling your finger at the remote how to move in order to control the car.
An autonomous car needs a speed sensor
But since we want our car to drive around autonomously, we need a sensor that tells us the current velocity. One of the easiest ways is to add magnets to the drive shaft and detect them by means of a hall sensor. Hence, I printed a disk and attached 16 small neodymium magnets on its perimeter. The magnets have to alternate with their north and south pole, as presented in the datasheet of the Allegro A1127 Hall Sensor. The sensor is attached to one of the Raspberry Pi’s digital inputs according to the circuit portrayed in the image gallery. It is equipped with an indicator led that turns on and off according to the output voltage: When a magnetic south pole (positive magnetic field strength) passes the sensor, the sensor switches off and the led with it. When afterwards a magnetic north pole (negative magnetic field strength) passes the sensor, it switches on and the led shines. This is referred to as a tick.
Measure the speed of your rc car with a hall sensor
The Raspberry Pi reads the low and high signals of the hall sensor with one of its digital inputs and can determine the tick speed a in ticks per second. To yield a speed c in meters per second, we need to know what distance the car drives for one tick. Let me call this constant the tick distance b. Its value is determined by letting the car drive a certain distance measured with a measuring tape and dividing it by the number of ticks counted during the ride. This is exactly what the node calibrate_encoder_node
of the ROS package wheel_encoder
in my Github project does. You then simply calculate:
$latex a \frac{ticks}{s} \cdot b \frac{m}{ticks}=c \frac{m}{s}$
Retrieve the steering angle
Besides the current speed of the vehicle, we further need the current steering angle to be able to compute the odometry. The steering angle is subscribed from the topic /command
that publishes the PWM values for the steering servo. This is done in the ROS node odometry_node
in the odometry
package.
Compute the odometry of your rc car
The first step is to determine the current longitudinal, lateral and angular velocity of the car. Here, the speed that we measure with our hall sensor is denoted as symbol s. The steering angle that we obtain from the PWM values sent to the steering servo are referred to as the symbol theta. See the following equations that define the x-, y, and theta-velocity for an Ackermann drive (further references: Ackermann Steering):
$latex \dot{x}=s\cdot cos(\theta)\\\dot{y}=s\cdot sin(\theta)\\\dot{\theta}=\frac{s}{l}\cdot tan(\phi)$ ,where $latex \theta = \text{orientation of car}\\\phi = \text{steering angle}\\s = \text{speed}\\l = \text{wheelbase}$As a second step we calculate the increase or decrease of the translation and rotation in the previous time step (further references: Publishing Odometry Information over ROS):
$latex \Delta t = (t_i – t_{i-1})\\\Delta x = \dot{x}\cdot cos(\theta)-\dot{y}\cdot sin(\theta)\cdot \Delta t\\\Delta y = \dot{x}\cdot sin(\theta)+\dot{y}\cdot cos(\theta)\cdot \Delta t\\\Delta \theta = \dot{\theta}\cdot \Delta t$
As a third step, the position and orientation of the car is computed by
$latex x=x+\Delta x\\y=y+\Delta y\\\theta = \theta + \Delta \theta$
All this is done by the node odometry_node
in package odometry
of my project.