Testing Turtle Rover ROS nodes

In this tutorial, we will show how you can run and test ROS nodes for Turtle Rover.

It will be helpful to have some basic knowledge about ROS before attempting it. To learn some basics, you can head to official ROS wiki tutorials

Prepare your environment

In this tutorial, we assume you have Turtle Rover ROS packages already installed.

It will also be required to open multiple terminal sessions through ssh

Instead of creating a new ssh connection for each terminal session, we recommend using tmux to manage many sessions at once

1. Run Master Node

Before you can start other nodes, you need to have Master node running first. Let's start with sourcing our workspace

source ~/turtle_ws/devel/setup.bash

When you source the environment setup file, it creates an overlay only for the current terminal session so you need to do this in each newly opened session.

Alternatively, add this line to ~/.bashrc file (e.g. with nano). It will then be executed automatically at the start of every session.

To start Master node just type


2. Test tr_ros packages

To learn more about each node's parameters and subscribed, published topics, head to README pages in tr_ros GitHub Repository

If you found some nodes not working correctly or have some enhancement proposition, feel free to open a new issue on GitHub

2.1 tr_hat_bridge

This package contains a node that lets you communicate with Turtle Hat (RaspberryPi shield) through ROS API.

To run it, make sure you have roscore running first, and then on another terminal session, type:

rosrun tr_hat_bridge tr_hat_bridge

By default, Hat Bridge tries to communicate using /dev/ttyAMA0 device (which is UART port on RPi 3 GPIO Header). If you need to use a different device, you can do it by setting ~device parameter, either by setting it on the parameter server

rosparam set /tr_hat_bridge/device "/dev/ttyS0"

or by passing it directly when running a node

rosrun tr_hat_bridge tr_hat_bridge _device:=/dev/ttyS0

For Hat Bridge to work correctly, you need to have the latest firmware installed on Turtle Hat.

Now let's test some functionalities.

setting motor power

To set motor power values, you need to publish messages on tr_hat_bridge/motors topic. A message consists of 4 floating point numbers in the range [-1.0, 1.0] describing power on each wheel (the order of the wheels is RR, RL, FR, FL).

Let's test it with rostopic tool by setting half power on RR wheel

rostopic pub /tr_hat_bridge/motors tr_hat_msgs/MotorPower "[0.5, 0, 0, 0]"

The wheel should start moving and won't stop until we send it another message. To stop the motors, just type:

rostopic pub /tr_hat_bridge/motors tr_hat_msgs/MotorPower "[0, 0, 0, 0]"

setting servo angles

To set servo angle, you need to publish a message on tr_hat_bridge/servo topic. A message contains the servo channel (1, 2 or 3) and the angle (0 to 180 degrees). For example, to set servo 1 on 90 degrees position, type:

rostopic pub /tr_hat_bridge/servo tr_hat_msgs/ServoAngle "{channel: 1, angle: 90.0}"

getting battery voltage

To get battery voltage reading from Turtle Hat you need to call tr_hat_bridge/get_battery service. To do this we can use rosservice tool

rosservice call /tr_hat_bridge/get_battery

2.2 tr_control

This node lets you drive the Rover using Twist messages. To test it, first make sure you have tr_hat_bridge running, then on another terminal session, run:

rosrun tr_control tr_control

Now we can publish velocity command to cmd_vel topic (Twist) or cmd_vel_stamped topic (TwistStamped). Let's write a simple Python script to test it:

#!/usr/bin/env python
import rospy
from geometry_msgs.msg import Twist
# Initialize ROS node
# Create ROS publisher
cmd_pub = rospy.Publisher("cmd_vel", Twist, queue_size=1)
# Write a function that drives the Rover with specified
# linear and angular speed for 2 seconds
def drive(linear, angular):
# Initialize ROS message object
twist = Twist()
twist.linear.x = linear
twist.angular.z = angular
for _ in range(20): # repeat 20 times
cmd_pub.publish(twist) # publish message
rospy.sleep(0.1) # sleep for 100ms
# Now let's actually test driving the Rover
# linear speed is in m/s and angular speed in rad/s
drive(0.2, 0.0)
drive(0.0, 0.0)
drive(-0.2, 0.0)
drive(0.0, 0.0)
drive(0.0, 1.0)
drive(0.0, 0.0)
drive(0.0, -1.0)
drive(0.0, 0.0)

Copy this script to clipboard and paste it to test_drive.py using cat

cat > test_drive.py

Shift+Ins when using Putty or Ctrl+Shift+V when using Linux terminal. Hit Ctrl+D to end the file.

Add execute permission to this file:

chmod +x test_drive.py

Now, run the script by typing:


The Rover should drive forward and backward. then turn in place in left and right direction


There is a couple of ROS parameters that can be adjusted.

wheel_radius, wheel_track and max_wheel_speed are used to evaluate motor power values based on linear and angular speeds. They are specific to the Rover model and there is no point in changing them unless you put some modifications to the wheels.

If you change differential_drive parameter to false, the driver won't support driving along a curve. It will only move straight or turn in-place depending on the greater value among linear an angular speeds.

By default, controller will stop the motors if it doesn't receive a velocity command for half a second. You can adjust this duration by changing input_timeout parameter or turning it off by setting it to 0.

If you publish velocity commands using TwistStamped messages, you can set check_timestamp parameter. When timestamp checking is enabled, controller will skip velocity command that have timestamps that differ too much from Rover's system time. For example settings it to 1.0 will skip velocity commands whose timestamps are more than 1 second in the past.

2.3 tr_teleop

This package contains nodes that let you teleoperate the Rover. They work by publishing velocity commands to cmd_vel_stamped topic, so be sure to have tr_control and tr_hat_bridge nodes running.


This node lets you control the Rover via keyboard input. To run it just type:

rosrun tr_teleop tr_teleop_key

A help message with key mappings should appear

Keep in mind that this node is a console application and can't access keyboard events. Instead, it reads raw keyboard input in the console. It assumes the key is up when it doesn't receive an input for a specified time.

You can control this behavior by settings ~key_timeout parameter. The lower the value, the more responsive the Rover will be, but remember to set keyboard repeat delay on your system below this value. You can also disable this behavior by setting it to 0


This node takes joy messages (e.g. from joy_node) and converts them to velocity commands. To run it together with joy_node you can use our launch file. Simply type:

roslaunch tr_teleop joy.launch

You can configure joy axis mapping by editing config/joy.mapping.yaml file.

To test joy axis numbers you can run joy_node and display messages published in joy topic (the axes are numbered starting from 0):

rosrun joy joy_node
rostopic echo /joy

Or you can use jstest tool

jstest /dev/input/js0

To adjust speed scales, change scale_linear and scale_angular parameters in joy.launch file.

2.4 tr_webui

A sample web user interface that lets you control the rover via keyboard or nipplejs, set servo angles, check battery voltage and display video stream (uv4l webrtc streaming).

To run the server, type:

roslaunch tr_webui webui.launch

you can access webui by your internet browser at this location:

This package is experimental at the moment. The webui isn't best looking and can be buggy. If you happen to have made some improvements, we would highly appreciate a PR on Github ;)