Remote Controlling the Robot with a Gamepad

In this post, I want to give a quick overview how you can remote control a small mobile robotics platform with a game controller. We will use the joy package of ROS to have the device publishing ROS messages. The necessary steps are described in “Setting up the Joystick” in the teleop ROS tutorial. I will quickly summarize them here.

Controller Setup

Plug in your controller and check if its available with

$ ls -l /dev/input/js*

The star is the wildcard operator. Change the permissions to the device so that all have read and write accessibility through

$ sudo chmod a+rw /dev/input/jsX

Now, start the roscore, set parameters, start the publisher node

$ roscore
$ rosparam set joy_node/dev "/dev/input/jsX"
$ rosrun joy joy_node
$ rostopic echo joy

and when you push a button or move a joystick you should see a new message arriving. Find out which part of the message corresponds to the joysticks. We will map each of the two to one wheel of the differential drive robot.

Network Setup

We will have the controller plugged in our laptop / PC and not directly in the robot (which uses the Beagle Bone Blue). Therefore we have a multiple machine setup. Run the roscore on the laptop. If automatic host resolving is not working, you also have to set

$ export ROS_IP=machine_IP

on both the BBBL and the laptop. Remember that environment variables are only set for one terminal, if you open a new one they are not available. On the BBBL you also have to

(BBBL) $ export ROS_MASTER_URI=laptop_ip:port

Implementing the Callback

On the BBBL, we will run a subscriber to the topic joy. Each time a message is received, a callback function is called - here we will set the motor speeds.

(BBBL) $ rostopic echo joy

You should see the exact same output as when running the command on your laptop. In the callback function, I additionally print out the received value and make the LED light up if the joystick value is larger than 0.5. The full code is available also on github.

void chatterCallback(const sensor_msgs::Joy::ConstPtr& msg)
{
  ROS_INFO_STREAM("I heard: " << msg->axes[1]);
  ROS_INFO_STREAM("I heard: " << msg->axes[3]);

  rc_motor_set(1, msg->axes[1]);
  rc_motor_set(2, msg->axes[3]);

  if (msg->axes[1] > 0.5)
  {
    rc_led_set(RC_LED_GREEN, 1);
  }
  else
  {
    rc_led_set(RC_LED_GREEN, 0);
  }
  if (msg->axes[3] > 0.5)
  {
    rc_led_set(RC_LED_RED, 1);
  }
  else
  {
    rc_led_set(RC_LED_RED, 0);
  }
}

Having Fun

See the video below for the project in action.