A mobile robot offers many interfaces for controlling. In my project RADU, a two-wheel movable robot, I implemented a wrap for movements commands from the Robot Operating System ROS. Commands have two parts in which we are interested: The linear velocity in meter/second, which moves the robot along its x-axis, and the angular velocity on radians/second, which turns the robot around its z-axis, also called pitch. Any controller that sends input which can be converted to these movements messages is usable by the project.
This article is a quick tutorial how to use a game console controller, from a PlayStation or Xbox, to move a robot. You will learn how to connect and read gamepad data, and how to convert it to ROS compatible commands.
The technical context of this article is
Ubuntu 20.04 LTS with latest
Connect and Read Gamepad Data
We need to connect a gamepad and check that your Linux system correctly recognizes it. Use whatever gamepad you have - in my case, it’s a PlayStation 3 controller, and plug it into a USB port
Then, run the Linux command
dmesg to show decent Kernel messages about the detected device.
[412373.206747] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [412373.206749] usb 1-2: Product: PLAYSTATION(R)3 Controller [412373.206751] usb 1-2: Manufacturer: Sony [412373.562080] input: Sony PLAYSTATION(R)3 Controller Motion Sensors as /devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0/0003:054C:0268.001C/input/input102 [412373.624511] input: Sony PLAYSTATION(R)3 Controller as /devices/pci0000:00/0000:00:15.0/usb1/1-2/1-2:1.0/0003:054C:0268.001C/input/input101 [412373.625435] sony 0003:054C:0268.001C: input,hiddev1,hidraw3: USB HID v81.11 Joystick [Sony PLAYSTATION(R)3 Controller] on usb-0000:00:15.0-2/input0
Next, we need to figure out where joystick data can be accessed. Execute the command
cat /proc/bus/input/devices and look for a text block that mentions the controller that you connected. In my case, I see this:
I: Bus=0003 Vendor=054c Product=0268 Version=8111 N: Name="Sony PLAYSTATION(R)3 Controller" P: Phys=usb-0000:00:15.0-3.1/input0 S: Sysfs=/devices/pci0000:00/0000:00:15.0/usb1/1-3/1-3.1/1-3.1:1.0/0003:054C:0268.0059/input/input224 U: Uniq=00:21:4f:08:f6:c8 H: Handlers=event17 js0 B: PROP=0 B: EV=20001b B: KEY=f00000000 0 0 0 7fdb000000000000 0 0 0 0 B: ABS=3f B: MSC=10 B: FF=107030000 0
In the line
p, we see
/input0, and in line
H, we see
js0. We combine this information to the device file
/dev/input/js0. This device file provides a byte stream about controller commands.
Now, we will read this byte stream with ROS.
Reading Gamepad Data with ROS
In order to work with any gamepad, we need to install additional ROS packages. In a terminal, execute this command:
sudo apt-get install ros-noetic-joy-teleop ros-noetic-teleop-twist-joy ros-noetic-joy
These packages provide several ways to interact with a connected joypad. To get started, we will run a ROS node called
joy_node with the parameter of the detected device file. Run the following command ...
rosrun joy joy_node dev:=/dev/input/js0
... and you should see this output.
[ INFO] [1627219939.885877257]: Opened joystick: /dev/input/js0 (Sony PLAYSTATION(R)3 Controller). deadzone_: 0.050000.
This node published data at the topic
/joy. Let’s subscribe to this topic and see the messages.
$> rostopic echo /joy header: seq: 177 stamp: secs: 1627219968 nsecs: 437779598 frame_id: "/dev/input/js0" axes: [0.04505977779626846, -0.0, 0.0, -0.0, -0.0, 0.0] buttons: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] --- header: seq: 178 stamp: secs: 1627219968 nsecs: 447620065 frame_id: "/dev/input/js0" axes: [-0.0, -0.0, 0.0, -0.0, -0.0, 0.0] buttons: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ---
Each message contains two vectors. The first vector
axes contains the left/right and top/down position of the two control sticks and the cross key as float values. The second vector
buttons contains integer values about which buttons are pressed. See the button mapping documentation.
Converting Gamepad Data to Twist Messages
The last step is to translate the messages from the
/joy topic to TWIST messages. Another ROS package already performs this translation, we just need to start the
Start the node with ...
rosrun teleop_twist_joy teleop_node
... and you should see the following output.
[ INFO] [1627221588.156287628]: Teleop enable button 0. [ INFO] [1627221588.161486651]: Linear axis x on 1 at scale 0.500000. [ INFO] [1627221588.161570308]: Angular axis yaw on 0 at scale 0.500000.
Before continuing, be sure to check that all required ROS nodes are running and connected as shown in the following picture:
Subscribe to the topic
/cmd_vel. Then, on your gamepad, identify the
deadman switch button, a safe guard to prevent sending commands that you did not intent. From the above mentioned message
Teleop enable button 0. and the button mapping documentation, I can see that this button is
X on my PlayStation 3 controller.
Now comes the big moment: Hold down the
X button, move the joystick, and you should see these messages:
--- linear: x: 0.036096855998039246 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.0 z: -0.5 --- linear: x: -0.0 y: 0.0 z: 0.0 angular: x: 0.0 y: 0.0 z: -0.45583534240722656
Cool! Now you just need feed these messages to your robot, and you can start moving around, controlled with a gamepad.
This article showed you how to use a gamepad for controlling your robot. We learned how to identify a connected controller on Linux by reading the build-in proc log to identify which device file represents the controller. Then we continued to install the required ROS packages
teleop-twist-joy and started a simple node that shows which game stick or buttons are pressed. And with the help of another node we can transform these messages to movement messages in the Twist format. Now, grab your favourite controller and move your robot in realtime.