Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the crayon-syntax-highlighter domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/moritzb/public_html/wp-includes/functions.php on line 6114
ROS Raspi Car – Moritz' Makings
Programming the RaspberryPi controlling the car

ROS Raspi Car

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 topic cmd_vel as Twist, converts it to the Ackermann-suitable type AckermannDriveStamped and publishes it to /ackermann_cmd_topic
    • ROS node ackermann_drive_to_pwm Subscribes to ROS topic ackermann_cmd_topic as AckermannDriveStamped, converts it to PWM values for servo motors and publishes it as Int32MultiArray to /command, from there it is sent to the PWM board and eventually to the servo motors
  • 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
  • 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.