Chapter 8. Controlling Your Robots with External Devices

In the past few chapters, we have used ROS to control mobile, armed, flying, and simulated robots. The similarities and differences between these robots have been discussed and we have shown the commonality that ROS has created between all these robot types. Commonality is not only in the structure of the software and the communications methods, but also in the simulation environment and the tools used for visualization and analysis.

The influence of ROS goes even further to provide a common interface to control devices external to the robot. These devices include game controllers (gamepads and joystick controllers), mobile devices (smart phones and tablets), and even controller boards (the Arduino and Raspberry Pi).

In this chapter, you will learn about the following topics:

  • Adding a game controller to a robot
  • Using mobile devices to control robot projects
  • Interfacing controller boards such as Arduino or Raspberry Pi

Creating a custom ROS game controller interface

If you have played with the joystick with either Baxter or Crazyflie, you may think that the function of certain buttons or joysticks would be better with your own special design. Each type of game controller has one or more joysticks and various buttons or triggers to cause events depending on the game software being used. Here, for the Microsoft Xbox controller, we will do the following:

  • Show how to determine the mapping between controller joysticks, buttons, and triggers and the number corresponding to each using a graphical package, jstest-gtk
  • Use the terminal command jstest; this will enable you to determine the corresponding numbers of controller joysticks, buttons, and triggers

The ensuing diagram shows the Xbox 360 game controller. Pushing a button changes the output from 0 (off) to 1 (on) on the channel corresponding to the pushed button, which in turn can be read by a program and used to start an application. Moving the stick outputs a numerical value that can be used to control a robot. The joystick movements are described by the axis of the movement; moving the stick up and down defines one axis, and moving the stick to the left and right defines another.

Creating a custom ROS game controller interface

Xbox 360 game controller

Testing a game controller

To determine the number of the channel or axis associated with a button or joystick of a game controller, the graphical program jstest-gtk can be used. The package jstest-gtk is a game controller testing and configuration tool. This package is described at https://launchpad.net/ubuntu/trusty/+package/jstest-gtk.

To download and install the package, use the following command:

$ sudo apt-get install jstest-gtk

The command to execute the program is:

$ jstest-gtk

The following screenshot shows the result with the Xbox controller connected to our computer. As shown, the Microsoft Xbox 360 controller has 8 axes and 11 buttons:

Testing a game controller

jstest-gtk Joystick Preference screen

By double-clicking on the name Generic X-Box pad, a GUI for the axes and buttons of the Xbox 360 controller appears, as in the following screenshot:

Testing a game controller

jstest-gtk Xbox screen

As you push a button on the controller, the number of the button will be highlighted in the display. The relative position of a joystick that is moved is shown graphically, and the numerical value associated with the motion is also displayed. More details on this are provided at http://manpages.ubuntu.com/manpages/trusty/en/man1/jstest-gtk.1.html.

Alternative test of a game controller

As an alternative to the graphical display of the game controller properties, terminal commands can be used. First, plug your game controller into a USB port of your computer and then determine the devices connected to the computer by issuing this command:

$ ls /dev/input/

The output should be similar to the following:

by-id      event0  event10  event2  event4  event6  event8  js0   mouse0

by-path  event1  event11  event3  event5  event7  event9  mice

The game controller will appear as a js device in this listing. Note that the system has the game controller as js0 in the list. To test the controller and determine the index number of the axes and buttons, type the following command:

$ jstest /dev/input/js0

The output for the Xbox controller, should be similar to the following:

Driver version is 2.1.0.
Joystick (Generic X-Box pad) has 8 axes (X, Y, Z, Rx, Ry, Rz, Hat0X, Hat0Y)
and 11 buttons (BtnX, BtnY, BtnTL, BtnTR, BtnTR2, BtnSelect, BtnThumbL, BtnThumbR, ?, ?, ?).
Testing ... (interrupt to exit)

Axes:  0:     0  1:     0  2:     0  3:     0  4:     0  5:     0  6:     0  7:     0
Buttons:  0:off  1:off  2:off  3:off  4:off  5:off  6:off  7:off  8:off  9:off 10:off

In this case, the controller is the Xbox controller. Experiment with your controller to understand the output when the joystick is moved or a button is pressed. When a button is pressed, the corresponding value changes to on. Also, when a joystick is moved horizontally or vertically, the selected axis value will change from its initial value to a new value.

Now for your controller, you can figure out which buttons or axes you will use for your application. Next, you must consider the type of software or hardware that is to be controlled by the game controller. For ROS, the /joy node is used to read the controller output.

A tutorial describing the use of Ubuntu commands is available at http://wiki.ros.org/joy/Tutorials/ConfiguringALinuxJoystick.

Using the joy ROS package

ROS has a driver for a generic controller with a joystick. The joy package contains the /joy node that interfaces a generic Linux joystick to ROS. This node publishes a joy message, which contains the current state of each one of the joystick's buttons and axes. Before using the /joy node in an application, see whether you have the joy package installed by typing this:

$ rospack find joy

The output should be as follows:

/opt/ros/indigo/share/joy

If you do not see the path to the joy package, install it with this command:

$ sudo apt-get install ros-indigo-joy

Controlling Turtlesim with a custom game controller interface

In this section, an example use of a game controller and the /joy node is presented utilizing the following code files:

  • An ROS package contains the launch file turtlesim_teleop.launch that executes three nodes: /joy, turtlesim, and turtlesim_joy. A Python program turtlesim_joy.py initiates the turtlesim_joy node and allows the joystick to control the movement of the turtle on the screen.
  • The program turtlesim_joy.py calls another Python program called move_circle.py when a button is pushed on the controller.

The Turtlesim simulator was introduced in the Turtlesim, the first ROS robot simulation section in Chapter 1, Getting Started with ROS. If you wish to create an ROS package for this example, refer to the instructions in the Creating and building a ROS package section in Chapter 2, Creating Your First Two-Wheeled ROS Robot (in Simulation). In our case, the files are copied to the ros_robotics package created in Chapter 2, Creating Your First Two-Wheeled ROS Robot (in Simulation).

Note

Downloading the example code

You can download the example code files and other support material for this book from www.PacktPub.com.

In the package directory, the launch file should be copied to a /launch directory. The Python code should be copied to a /src directory of the package. Make sure the Python scripts are executable by issuing the following command:

$ chmod +x <filename>.py

Here, <filename> is the name of the Python script. Alternatively, type the following:

$ chmod +x *.py

You can use the preceding command to make all the Python files in the directory executable.

After loading the files into the directories, issue the catkin_make command in the catkin workspace directory to link together the ROS files.

The code for the launch file turtlesim_teleop.launch is as follows:

<?xml version="1.0"?>
<launch>

  <!-- turtlesim and joy node-->
  <node name="turtlesim" pkg="turtlesim" type="turtlesim_node"/>
  <node name="joy" pkg="joy" type="joy_node"/>

  <!-- turtlesim_joy node interfaces Xbox controller to turtlesim -->
  <node name="turtlesim_joy" pkg="ros_robotics" type="turtlesim_joy.py" output="screen"/>

</launch>

Use the following command to launch the nodes:

$ roslaunch ros_robotics turtlesim_teleop.launch

You should see output similar to the following (edited):

.

.

SUMMARY
========

PARAMETERS
 * /rosdistro: indigo
 * /rosversion: 1.11.19

NODES
  /
    joy (joy/joy_node)
    turtlesim (turtlesim/turtlesim_node)
    turtlesim_joy (ros_robotics/turtlesim_joy.py)

auto-starting new master
process[master]: started with pid [22649]
ROS_MASTER_URI=http://localhost:11311

.

The preceding command will launch three ROS nodes as shown in the screen output after the launch file is executed with the roslaunch command. You can also check the list of nodes with this command:

$ rosnode list

The first Python program turtlesim_joy.py allows the turtle of Turtlesim to be controlled by the joystick axes [0] and [1] on the game controller. For the Xbox controller, these axes correspond to the vertical and horizontal left joystick movements, respectively. In addition, pushing the button corresponding to button number 0 will cause another Python program, move_circle.py, to drive the turtle in a circle. On the Xbox controller, this is the green button:

#!/usr/bin/env python

"""
Node converts joystick inputs into commands for Turtlesim
"""

import rospy
from geometry_msgs.msg import Twist
from sensor_msgs.msg import Joy
from move_circle import move_circle

def joy_listener():

  # start node
  rospy.init_node("turtlesim_joy", anonymous=True)

  # subscribe to joystick messages on topic "joy"
  rospy.Subscriber("joy", Joy, tj_callback, queue_size=1)

  # keep node alive until stopped
  rospy.spin()

# called when joy message is received
def tj_callback(data):

  # start publisher of cmd_vel to control Turtlesim
  pub = rospy.Publisher("turtle1/cmd_vel", Twist, queue_size=1)

  # Create Twist message & add linear x and angular z from left joystick
  twist = Twist()
  twist.linear.x = data.axes[1]
  twist.angular.z = data.axes[0]

  # record values to log file and screen
  rospy.loginfo("twist.linear: %f ; angular %f", twist.linear.x, twist.angular.z)

  # process joystick buttons
  if data.buttons[0] == 1:        # green button on xbox controller
      move_circle()

  # publish cmd_vel move command to Turtlesim
  pub.publish(twist)

if __name__ == '__main__':
  try:
      joy_listener()
  except rospy.ROSInterruptException:
      pass

This code initializes the turtlesim_joy node and subscribes to the joy topic. When a joy message is received, the tj_callback function reads the values from axes[0] and axes[1] and assigns them to a twist message. If the value of button[0] is 1, then this button was pressed and the move_circle function is called.

The listing of move_circle.py is as follows:

#!/usr/bin/env python
"""
Script to move Turtlesim in a circle
"""
import rospy
from geometry_msgs.msg import Twist

def move_circle():

  # Create a publisher which can "talk" to Turtlesim and tell it to move
  pub = rospy.Publisher('turtle1/cmd_vel', Twist, queue_size=1)
   
  # Create a Twist message and add linear x and angular z values
  move_cmd = Twist()
  move_cmd.linear.x = 1.0
  move_cmd.angular.z = 1.0

  # Save current time and set publish rate at 10 Hz
  now = rospy.Time.now()
  rate = rospy.Rate(10)

  # For the next 6 seconds publish cmd_vel move commands to Turtlesim
  while rospy.Time.now() < now + rospy.Duration.from_sec(6):
      pub.publish(move_cmd)
      rate.sleep()

if __name__ == '__main__':
  try:
      move_circle()
  except rospy.ROSInterruptException:
      pass

When executed, this code will create a twist message and set the linear.x and angular.z values. As the Python program turtlesim_joy.py is executed, you can move the turtle with the joystick. As the selected button is pushed, move_circle.py is executed, and the turtle then turns with a linear velocity of 1.0 units/second and an angular velocity of 1 radian/second for 6 seconds. Thus, the turtle moves in a circle. The following screenshot shows the result of one of our experiments with the Xbox 360 joystick control of Turtlesim:

Controlling Turtlesim with a custom game controller interface

Turtlesim screen

To see the message published by the /joy node, issue this command:

$ rostopic echo /joy

The results indicate the values of the axes and buttons and other information:

header:
  seq: 218
  stamp:
    secs: 1461884528
    nsecs: 370878390
  frame_id: ''
axes: [-0.0, 0.1265602558851242, 0.0, -0.06729009747505188, -0.0, 0.0, 0.0, 0.0]
buttons: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Move the stick to start and use Ctrl + C to end the output.

To see the nodes and topics, issue the following command:

$ rqt_graph

This yields the resulting screenshot:

Controlling Turtlesim with a custom game controller interface

Turtlesim_teleop.launch node and topic graph

A tutorial using a C++ program and a launch file for use with a Turtlesim and joystick is available at http://wiki.ros.org/joy/Tutorials/WritingTeleopNode.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.153.224