Skip to content
Tom Howard edited this page Jul 19, 2021 · 12 revisions

Getting to Grips with ROS (and Linux)

Quick Links

First Steps

Exercise 1: Launching a robot in simulation and making it move

  1. If you haven't done so already, launch the WSL-ROS environment. This should open up the Windows Terminal and an Ubuntu terminal instance. We'll refer to this terminal instance as TERMINAL 1

  2. In TERMINAL 1 enter the following command to launch a simulation of a TurtleBot3 Waffle in an empty world:

     [TERMINAL 1] $ roslaunch turtlebot3_gazebo turtlebot3_empty_world.launch
    
  3. A Gazebo simulation window should open and within this you should see a TurtleBot3 Waffle in empty space:

  4. With your Gazebo Simulation up and running, return to the terminal application and open up a new Ubuntu terminal instance (TERMINAL 2) by pressing the New Tab button:

    (or, alternatively, press the Ctrl+Shift+T keyboard shortcut). In TERMINAL 2 enter the following command:

     [TERMINAL 2] $ roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch
    
  5. Follow the instructions provided in the terminal to drive the robot around in its simulated environment!

Summary:

You have just launched two separate ROS applications using the roslaunch command. roslaunch is one way to launch ROS programs and we use this command in the following way:

roslaunch [package name] [launch file]

The command takes two input parameters:

  • [package name]: the name of the ROS package containing the functionality that we want to execute
  • [launch file]: a .launch file within the package that tells ROS exactly what functionality to launch.

All ROS applications are organised into packages, which are collections of scripts, parameters and configurations relating to some common robot functionality. ROS uses packages as a way to organise all the programs running on a robot: The package system is a fundamental concept of ROS, and all ROS programs are organised in this way.

Exercise 2: Exploring a package

roscd is a ROS command that allows us to navigate to the directory of any ROS package installed on our system, without us needing to know the path to the package beforehand.

  1. Open up a new terminal instance (TERMINAL 3) and use the roscd command to navigate to the turtlebot3_teleop package directory on our Linux filesystem:

     [TERMINAL 3] $ roscd turtlebot3_teleop
    

    The terminal prompt should change to illustrate where on the filesystem the roscd command has just taken you:

  2. pwd is a Linux command which tells us where the terminal is currently located in the filesystem. Use this to confirm what the terminal prompt is telling you:

     [TERMINAL 3] $ pwd
    

    We now know where the turtlebot3_teleop package is located on our machine, and we can then use more Linux commands to explore this further:

  3. ls is a Linux command which lists the contents of the current directory. Use this to list the contents of the turtlebot3_teleop package directory.

     [TERMINAL 3] $ ls
    

    This will simply list the items in the current directory, but we can use the -F option to find out a little more:

     [TERMINAL 3] $ ls -F
    

    You will notice that the output has now changed slightly: items followed by a / are folders (aka "directories") and items without the / are files (files will often have a file extension too). How many items are there in the turtlebot3_teleop package directory? How many of these are directories and how many are files?

    Launch files for a package are typically located in a launch folder within the package directory. You should have noticed a launch folder in the output of the ls command above.

  4. cd is a Linux command that allows us to change the directory that the terminal is currently located in. Use this to navigate to the turtlebot3_teleop package launch folder and then use ls again to see what's in there. In this folder you should see the turtlebot3_teleop_key.launch file that we executed with the roslaunch command in Exercise 1. We will now have a look at the contents of this file...

  5. cat is a Linux command that we can use to display the contents of a file in the terminal. Use this to display the contents of the turtlebot3_teleop_key.launch file.

     [TERMINAL 3] $ cat turtlebot3_teleop_key.launch
    
Summary:

From the output of cat in the step above you should have noticed that the contents of a launch file are contained within a <launch> tag:

<launch>
... 
</launch>

Within that, we also have (amongst other things) a <node> tag which tells ROS exactly what script (or "executable") to launch and how to launch it:

<node pkg="turtlebot3_teleop" type="turtlebot3_teleop_key" name="turtlebot3_teleop_keyboard"  output="screen">
</node>

The attributes here have the following meaning:

  • pkg: The name of the ROS package containing the functionality that we want to launch
  • type: The name of the script (or ROS Node) that we want to execute within that package
  • name: A descriptive name that we want to give to the ROS node (we can call it anything, as long as it's unique on the ROS network)
  • output: The place where any output from the node will be printed (either screen where the output will be printed to our terminal window, or log where the output will be printed to a log file)

You can include multiple <node> tags in a .launch file in order to launch multiple nodes simultaneously.

ROS Nodes are executable programs that perform specific robot tasks and operations, such as remote (or "teleoperational") control, as we have just seen in the above example.

The Publisher-Subscriber communication method

A ROS Robot may have hundreds of individual nodes running simultaneously to carry out all its necessary operations and actions. Each node runs independently, but uses ROS communication methods to communicate and share data with other nodes on the system. In the following exercises we will create our own ROS package and start to build some nodes which will leverage this communication method.

Exercise 3: Visualising the ROS network and interrogating topics and messages

You can use the ROS command rosnode to view all the nodes that are currently active on a ROS system.

You should currently have three terminal windows active: the first in which you launched the Gazebo simulation (TERMINAL 1), the second with your turtlebot3_teleop node active (TERMINAL 2), and the third where you explored the contents of the turtlebot3_teleop package directory (TERMINAL 3). TERMINAL 3 should now be idle.

  1. In TERMINAL 3 enter cd ~ to go back to your home directory (remember that ~ is an alias for this)

  2. Use the following command to have a look at what nodes are currently active:

     [TERMINAL 3] $ rosnode list
    

    Only a handful of nodes should be listed:

     /gazebo
     /gazebo_gui
     /rosout
     /turtlebot3_teleop_keyboard
    
  3. We can visualise the connections between the active nodes by using a script called rqt_graph from the rqt_graph package. We can use rosrun to launch this node directly:

     [TERMINAL 3] $ rosrun rqt_graph rqt_graph
    

    (you might notice some error messages here, but don't worry about them)

    A new window should open, displaying something similar to the following (hover over the diagram to enable colour highlighting, as shown below):

    This tool shows us that the /turtlebot3_teleop_keyboard and /gazebo nodes are communicating with one another. The direction of the arrow tells us that the /turtlebot3_teleop_keyboard node is a Publisher and the /gazebo node is a Subscriber. The two nodes communicate via a ROS Topic, in this case the /cmd_vel topic, and on this topic the /turtlebot3_teleop_keyboard node publishes messages to make the robot move.

  4. We can find out more about the /cmd_vel topic by using the rostopic ROS command. In a new terminal instance (TERMINAL 4) type the following:

     [TERMINAL 4] $ rostopic info /cmd_vel
    

    This should provide an output similar to the following:

     Type: geometry_msgs/Twist
    
     Publishers:
      * /turtlebot3_teleop_keyboard (http://localhost:#####/)
    
     Subscribers:
      * /gazebo (http://localhost:#####/)
    

    This confirms what we discovered earlier about the publisher(s) and subscriber(s) to the /cmd_vel topic. In addition, this also tells us the topic type, or the type of message that is being published on this topic.

  5. We can use the rosmsg ROS command to provide further information about this message (or indeed any other message that we may be interested in):

     [TERMINAL 4] $ rosmsg info geometry_msgs/Twist
    

    From this, we should obtain the following:

     geometry_msgs/Vector3 linear
       float64 x
       float64 y
       float64 z
     geometry_msgs/Vector3 angular
       float64 x
       float64 y
       float64 z
    

    We'll learn more about what this means later.

  6. To finish, shut down any active terminal processes by entering Ctrl+C in any that still have processes running (Terminals 1, 2 and 3). The associated Gazebo and rqt_graph windows should close as a result of this too.

Exercise 4: Creating a publisher node

In the following exercises we will create some simple publisher and subscriber nodes in Python and send messages between them. As we learnt earlier though, ROS applications should be contained within packages and so we firstly need to create a package to store our ROS nodes in. ROS provides a tool to do this: catkin_create_pkg. It's important to work in a specific filesystem location when we create and work on our own ROS packages, so that ROS can access and build everything appropriately. These spaces are called "Catkin Workspaces" and one has been created for you already, called catkin_ws.

  1. We can navigate to the catkin_ws folder by using the Linux cd command. In TERMINAL 1 enter the following:

     [TERMINAL 1] $ cd ~/catkin_ws/
    
  2. Inside the Catkin Workspace there is a directory called src (use the ls command to confirm this). All new packages need to be located in the src folder, so we need to be here when we use the catkin_create_pkg tool to create a new package. So, use the cd command again to navigate to the catkin_ws/src folder:

     [TERMINAL 1] $ cd src
    
  3. Now, use the catkin_create_pkg script to create a new package called ros_training which will have std_msgs and rospy as dependencies:

     [TERMINAL 1] $ catkin_create_pkg ros_training rospy std_msgs
    

    What did the catkin_create_pkg tool just do? (Hint: there are four things and it will have told you about them!)

  4. Navigate into this new package directory and use ls to list the content that has been created by the catkin_create_pkg tool.

    Catkin packages are typically organised in the following way, and have a few essential features that must be present in order for the package to be valid:

     package_folder/    -- All packages must be self-contained within their own root folder
     |-src/             -- A folder for source files (python scripts etc)
     |-CMakeLists.txt   -- Rules for compiling the package
     `-package.xml      -- Information about the package
    

    You will have noticed that the catkin_create_pkg tool made sure that the essential features of your own ros_training package were created when you asked it to build it in the step above.

  5. Within the ros_training package directory, navigate to the src folder using the cd command

  6. touch is a Linux command that we can use to create an empty file. In TERMINAL 1 create an empty file called publisher.py, which we will add content to shortly:

     [TERMINAL 1] $ touch publisher.py
    
  7. Because we want to execute this script, we will need to give the file execute permissions, which may not have been set by default when the file was created in the previous step. To do this, we can use the Linux chmod command in the following way: chmod +x [name of the python script]. First though have a look at the file as it is using ls again, but this time with an additional option:

     [TERMINAL 1] $ ls -lF  
    

    Which should provide the following output:

     -rw-r--r-- 1 student student 0 Jan 01 12:00 publisher.py
    

    The first bit of the output here tells us the file permissions: -rw-r--r--. This tells us who has permission to do what with this file and currently, the first bit: -rw-, tells us that we have permission to Read or Write to it.

    Now run the chmod command:

     [TERMINAL 1] $ chmod +x publisher.py
    

    And then run the ls -lF command again to see what has changed:

     [TERMINAL 1] $ ls -lF
    
     -rwxr-xr-x 1 student student 0 Jan 01 12:00 publisher.py*
    

    We can now see that we have granted everyone (including ourselves) permission to eXecute the file too. Job done.

  8. We can now open this file in a text editor. In this case we will use Atom. Launch this app now from TERMINAL 1 now:

     [TERMINAL 1] $ atm .
    
  9. Then open the publisher.py file that should be visible in the file tree on the left hand side.

  10. Once opened, copy the code provided here into the empty file and save it. Note: It is important that you understand how this code works, so you should have a look at the explainer, provided below the code.

  11. We can now run this node using the ROS command rosrun. However, we closed everything down earlier on, so the ROS Master is no longer active. First then, we need to re-launch it manually using roscore:

     [TERMINAL 1] $ roscore
    
  12. Then, in TERMINAL 2, use rosrun to execute the publisher.py script that you have just created by providing the relevant information to the rosrun command as follows: rosrun [package name] [script name] If you see a message in the terminal similar to the following then the node has been launched successfully:

     publisher node is active...
    

    We can further verify that our publisher node is running using a number of different tools. Try the following in TERMINAL 3:

  13. $ rosnode list: This will provide a list of all the nodes that are currently active on the system. Verify that the /publisher_node is visible in this list.

  14. $ rostopic list: This will provide a list of the topics that are currently being used by nodes on the system. Verify that the /chatter topic is present within this list.

Using the rostopic command

So far we have used the rostopic ROS command with two additional arguments:

  • list to provide us with a list of all the topics that are active on our ROS system, and
  • info to provide us with information on a particular topic of interest.

We can use the autocomplete functionality of the Linux terminal to provide us with a list of all the available options that we can use with the rostopic command. To do this you can type rostopic followed by a space and then press the Tab key twice:

rostopic[SPACE][TAB][TAB]

You should then be presented with a list of the available arguments for the rostopic command:

  • rostopic hz [topic name] provides information on the frequency (in Hz) at which messages are being published to a topic:

      [TERMINAL 3] $ rostopic hz /chatter
    

    This should tell us that our publisher node is publishing messages to the /chatter topic at (or close to) 10 Hz, which is exactly what we ask for in the publisher.py file (in the __init__ part of our Publisher class). Press Ctrl+C to stop this command.

  • rostopic echo [topic name] shows the messages being published to a topic:

      [TERMINAL 3] $ rostopic echo /chatter
    

    This will provide a live stream of the messages that our publisher.py node is publishing to the /chatter topic. Press Ctrl+C to stop this.

  • We can see some additional options for this command by viewing the help documentation:

      [TERMINAL 3] $ rostopic echo -h
    

    From here, for instance, we can learn that if we just wanted the echo command to display a set number of messages from the /chatter topic we could use the -n option. To display the most recent two message only for example:

      [TERMINAL 3] $ rostopic echo /chatter -n2
    

Exercise 5: Creating a subscriber node

You will now create another node to subscribe to the /chatter topic and access the information that our publisher node is outputting.

  1. In TERMINAL 3 use the filesystem commands that were introduced earlier (cd, ls and roscd) to navigate to the src folder of the ros_training package that we created earlier.

  2. Use the same procedure as before to create a new empty Python file called subscriber.py and make it executable.

  3. Then, open the newly created subscriber.py file in Atom, paste in the code provided here and save it. Once again, it's important that you understand how this code works, so we have provided an explainer for this too.

  4. Use rosrun (remember: rosrun [package name] [script name]) to run your newly created subscriber.py node. If your publisher and subscriber nodes are working correctly then you should see a continuous stream of messages in the terminal.

  5. As before, we can find out what nodes are running on our system by using the $ rosnode list command. Run this in TERMINAL 4 and see if you can identify the nodes that you have just launched.

  6. Finally, close down your publisher and subscriber nodes and the ROS Master by entering Ctrl+C in Terminals 1, 2 and 3.

Summary:

The ROS Master always needs to be running in order for any other nodes to be able to operate on a ROS system. We launched this in Exercise 4 by using the roscore command. You now have two of your own ROS nodes that are able to communicate with one another on a ROS Network using the Publisher-Subscriber communication method. You executed these nodes individually in the above exercises using rosrun, but there is a more effective way to do this...

Launch files

Launch files allow us to launch multiple ROS Nodes simultaneously using the roslaunch command. The added bonus is that launch files will also launch the ROS Master (if it isn't already running). We use the roslaunch command to execute launch files, much like you did in Exercise 1. You'll now create a launch file of your own to invoke all of the ROS functionality that you have created so far...

Exercise 6: Creating a launch file

  1. In TERMINAL 1, use roscd to navigate to the root of the ros_training package directory.

  2. Use the Linux mkdir command to create a new directory here called launch:

     [TERMINAL 1] $ mkdir launch
    
  3. Use the cd command to enter the launch folder that you have just created, then use the touch command (in the same way as before) to create a new, empty file called pub_sub.launch.

  4. Open this launch file in Atom ([TERMINAL 1] $ atm pub_sub.launch) and enter the following text:

     <launch>
       <node pkg="ros_training" type="publisher.py" name="pub_node"  output="screen">
       </node>
     </launch>
    
  5. Use roslaunch to launch this file and test it out as it is (remember: roslaunch [package name] [launch file]). If everything looks OK then close it down again and carry on to the next step.

  6. The launch file that you have just created should launch the publisher.py node, but not the subscriber.py node. Add another <node> tag to the file, formatted in order to launch the subscriber node as well.

  7. The publisher and subscriber nodes and the ROS Master can now all be launched with the roslaunch command and the pub_sub.launch file that you have now created!

  8. Launch this in TERMINAL 1 and then use $ rosnode list in TERMINAL 2 to check that everything has worked correctly.

~~~ End of Part 1 ~~~

Saving your work

Save the work you have done here by running the following script in any idle WSL-ROS Terminal Instance:

$ rosbackup.sh

This will export your home directory to your University U: Drive, allowing you to restore it at any point, should you need to.

Navigating This Wiki:
← Getting Started | Part 2: Sensors and Control →