Skip to content

AMR31001 Lab 1

Tom Howard edited this page Aug 15, 2022 · 7 revisions

Industry 4.0: ROS and Mobile Robotics (Part I)

You should be able to complete the exercises on this page within a two-hour lab session.

Introduction

In this first AMR31001 'Industry 4.0' Lab you will learn how to use ROS (the Robot Operating System) to control a robot's motion.

ROS is an open-source, industry-standard robot programming framework, used in a range of applications such as agriculture, warehouse and factory automation and advanced manufacturing (the robot arms at the AMRC, for instance, are programmed and controlled using ROS!)

ROS allows us to programme robots using a range of different programming languages, but we'll be using Python for these labs. In addition to this, ROS runs on top of a Linux operating system called 'Ubuntu', and so we'll also learn a bit about how to use this too.

We'll be working with robots called 'TurtleBot3 Waffles', which you can find out a bit more about on the Home page of this Wiki.

Pre-Lab Work: You must have completed the Health & Safety Assessment before you can make a start on this lab. This is available on the AMR31001 Blackboard Course Page.

Aims & Intended Learning Outcomes

In this lab you'll learn how to use ROS to make a robot move, and we'll also look at how we can create our own basic ROS applications (or 'Nodes'), using Python.

By the end of this session you will be able to:

  1. Control a TurtleBot3 Robot from a laptop using ROS.
  2. Launch ROS applications using roslaunch and rosrun.
  3. Interrogate running ROS applications using key ROS command line tools.
  4. Create a ROS package containing some basic ROS nodes (Python scripts).
  5. Publish and Subscribe to ROS topics using ROS Communication Methods.
  6. Navigate a Linux filesystem and learn how to do various filesystem operations from within a Linux Terminal.

Quick Links

Exercises

TODO

Additional Resources

TODO

The Lab

Getting Started

Before you do anything, you'll need to get your robot up and running, and make sure ROS is launched.

Exercise 1: Launching ROS and Making the Robot Move

You should have already been provided with a Robot and a Laptop (you're probably already reading this on the laptop!)

  1. First, identify the robot that you have been provided with. Robots are named as follows:

     dia-waffle[NUM]
    

    ... where [NUM] is a unique 'Robot Number' (a number between 1 and 50). Check the label printed on top of the robot to find out which one you have!

  2. Open up a terminal instance on the laptop, either by using the Ctrl+Alt+T keyboard shortcut, or by clicking the Terminal App icon in the favourites bar on the left-hand side of the desktop:

    (we'll refer to this as TERMINAL 1).

  3. In the terminal type the following command to link the laptop and robot, so that they can work together:


    TERMINAL 1:

     waffle [NUM] link
    

    (replacing [NUM] with the number of the robot that you have been provided with).


  4. Enter the password for the robot when requested (we'll tell you what this is in the lab).

    You may see a message like this early on in the process:

    If so, just type yes and then hit Enter to confirm that you want to continue.

  5. Once the pairing process is finished you should see a message which says "pairing complete", displayed in blue.

  6. Then, in the same terminal, enter the following command:


    TERMINAL 1:

     waffle [NUM] term
    

    (again, replacing [NUM] with the number of your robot).


    Any text that was in the terminal should now disappear, and a green banner should appear across the bottom of the terminal window:

    ADAPT

    This is a terminal running on the robot, and any commands that you enter here will be executed on the robot (not the laptop!)

  7. Now, launch ROS on the robot, by entering the following command:


    TERMINAL 1:

     roslaunch tuos_tb3_tools ros.launch
    

    After a short while, you should see a message like this:

     [INFO] [#####] Calibration End  
    

    ROS is now up and running on the robot, and we are ready to go.

  8. Now open up a new terminal instance on the laptop (by pressing Ctrl+Alt+T or clicking the Terminal App desktop icon, as you did before). We'll call this one TERMINAL 2.

  9. In the new terminal instance enter the following command:


    TERMINAL 2:

     roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch
    

  10. Follow the instructions provided in the terminal to drive the robot around using specific buttons on the keyboard.

    image of keyboard mappings

  11. Enter Ctrl+C in TERMINAL 2 to stop the teleop node when you've had enough fun.

Packages

ROS applications are organised into packages. Packages are basically folders containing scripts, configurations and launch files (ways to launch those scripts and configurations). Each package typically provides some common robot functionality.

In Exercise 1 you actually launched a whole range of different ROS packages using only two roslaunch commands:

  1. roslaunch tuos_tb3_tools ros.launch (on the robot, in TERMINAL 1)
  2. roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch (on the laptop, in TERMINAL 2)

These command have two parts to them:

roslaunch {[1] Package name} {[2] Launch file}

Part [1] specifies the name of the ROS package that contains the functionality that we want to execute. Part [2] is a file within that package that tells ROS exactly what scripts (or 'Nodes') that we want to launch.

Post-lab Quiz Question: What were the names of the two packages that we invoked in Exercise 1?

Nodes

ROS Nodes are executable programs that perform specific robot tasks and operations. These are typically written in C++ or Python, but it's possible to write ROS Nodes using other programming languages too. We can see what nodes are active on our robot using ROS command-line tools.

Exercise 3: Visualising the ROS Network

  1. There shouldn't be anything running in TERMINAL 2 now, after you closed down the teleop node at the end of Exercise 2. Return to this terminal and use the following command to find out how many nodes are currently active on the robot:


    TERMINAL 3:

     rosnode list
    

    You should see a list of 7 items.

  2. We can visualise the connections between the active nodes by using a ROS node called rqt_graph. Launch this as follows:


    TERMINAL 3:

     rosrun rqt_graph rqt_graph
    

  3. In the window that opens, select "Nodes/Topics (active)" from the dropdown menu in the top left.

    What you should then see is a map of all the nodes in the list from earlier (as ovals), and arrows to illustrate the flow of information between all of these nodes. This is a visual representation of the ROS network!

    Items that have a rectangular border are ROS Topics. ROS Topics are essentially communication channels, and ROS nodes can read/write from/to these topics to pass information around the network and make things happen.

Post-lab Quiz: Did you notice how we used the rosrun command above, instead of roslaunch? We use rosrun if we only want to launch a single node (like the rqt_graph node) on the ROS network.

Post-lab Quiz: rosrun has the same two-part format as roslaunch. Why did we have to enter rqt_graph twice?

A ROS Robot might 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 the other nodes on the ROS Network.

Publishers and Subscribers: A ROS Communication Method

ROS Topics are key to making things happen on a robot. Nodes can publish and/or subscribe to ROS Topics in order to pass data around the ROS network. Data is published to topics using ROS Messages. We were actually publishing messages to a topic in Exercise 1 when we made the robot move with the teleop node.

Let's have a look at this in a bit more detail...

Exercise 4: Exploring ROS Topics and Messages

Much like the rosnode list command, we can use rostopic list to list all the topics that are currently available on our network.

  1. Close down the rqt_graph window if you haven't done so already. This will release TERMINAL 2 so that we can enter commands in it again. Return to this terminal window and enter the following:


    TERMINAL 2:

     rostopic list
    

    A much larger list of items should be printed to the terminal now. See if you can spot the following items in the list:

    1. /camera/color/image_raw
    2. /cmd_vel

    What do you think each of these is for? Let's have a look at the top item first...

  2. Enter the following rosrun command:


    TERMINAL 2:

     rosrun rqt_image_view rqt_image_view
    

  3. In the window that opens, select the "/camera/color/image_raw" topic from the dropdown menu in the top left. Maximise the window, if it isn't already, and you should see the live images coming from the camera on the front of the robot!

    This node subscribes to the /camera/color/image_raw topic, obtains the messages that are published to it and displays them for us to see.

    This topic is used to store image data from the camera, for any other node on the network to access, if required.

  4. Close down the rqt_image_view node.

  5. Let's have a look at the next item in the list now, but this time using some more command-line tools:

    First, let's find out more about the /cmd_vel topic by using the rostopic info command.


    TERMINAL 2:

     rostopic info /cmd_vel
    

    This should provide an output similar to the following:

     Type: geometry_msgs/Twist
    
     Publishers: None
    
     Subscribers:
      * /turtlebot3_core (http://dia-waffle[NUM]:#####/)
    

    This tells 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.

  6. We can use the rosmsg ROS command to provide further information about this message, or 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 next week.

  7. 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 5: Creating your own ROS Package

In a minute or two you 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 need to create a package in order to start creating our own ROS nodes.

ROS provides a tool to create a new ROS package and ensure that all the essential elements are present: catkin_create_pkg.

It is 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 already been created in the WSL-ROS environment: called catkin_ws.

  1. 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 week1_pubsub which will have std_msgs and rospy as dependencies:

     [TERMINAL 1] $ catkin_create_pkg week1_pubsub std_msgs rospy
    

    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. These items are highlighted with [*]:

     package_folder/    -- All packages must be self-contained within their own root folder [*]
     |-launch/          -- A folder for launch files (optional)
     |-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 a Catkin Package were created when we asked it to build the week1_pubsub package above.

  5. Before we do anything else, it's good practice to now run CMake on the package (using catkin build) to register it on our ROS system and make sure there are no errors with its definition so far:

     [TERMINAL 1] $ catkin build week1_pubsub
    

    Finally, "re-source" your environment using the following alias:

     [TERMINAL 1] $ src
    

    ... and we're good to go.

Exercise 6: Creating a publisher node

  1. Within the week1_pubsub package directory, navigate to the src folder using the cd command.

  2. touch is a Linux command that we can use to create an empty file. Use this to create an empty file called publisher.py, which we will add content to shortly:

     [TERMINAL 1] $ touch publisher.py
    
  3. Because we want to be able to run (or execute) this script, we will need to set the correct file permissions to allow us to do so. 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 have now granted permission for the file to be eXecuted too. Job done!

  4. We now need to open this file to edit it. As discussed on the Getting Started page, we will be using Visual Studio Code as our IDE for this work. It's important to launch this in a very specific way in order for it to work properly with the WSL-ROS environment, so follow the instructions here to get this up and running now!

  5. Make sure that the "Remote - WSL" VS Code extension is enabled within the WSL-ROS environment!!

  6. Using the VS Code File Explorer, navigate to your week1_pubsub package directory (~/catkin_ws/src/week1_pubsub/), locate the publisher.py file that you have just created in the /week1_pubsub/src/ folder and click on the file to open it.

  7. 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 make sure that you read the explainer!

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

     [TERMINAL 1] $ roscore
    
  9. 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:

     [INFO] [#####]: The 'simple_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:

  10. $ rosnode list: This will provide a list of all the nodes that are currently active on the system. Verify that the name of our publisher node is visible in this list.

  11. $ rostopic list: This will provide a list of the topics that are currently being used by nodes on the system. Verify that the name of the topic that our publisher is publishing messages to 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 7: Creating a subscriber node

You will now create another node to subscribe to the topic that our publisher node is broadcasting messages to, to access the information within the topic messages.

  1. In TERMINAL 3 use the filesystem commands that were introduced earlier (cd, ls and roscd) to navigate to the src folder of the week1_pubsub 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 VS Code, paste in the code provided here and save it. Once again, it's important that you understand how this code works, so make sure you read the explainer.

  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 you should see an output like this:

  5. As before, we can find out what nodes are running on our system by using the $ rosnode list command. Open a new terminal window (TERMINAL 4), run this 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.

Launch Files

At the beginning of this lab session we launched our Gazebo Simulation and the turtlebot3_teleop_keyboard node using launch files and the roslaunch command. This provides a means to launch multiple ROS nodes simultaneously, and we will demonstrate this by building a launch file for the publisher and subscriber nodes that we have just created.

Exercise 8: Creating a launch file

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

  2. Use the Linux mkdir command to make a new directory in the package root folder 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 pubsub.launch.

  4. Open this launch file in VS Code and enter the following text:

    <launch>
      <node pkg={BLANK} type={BLANK} name="pub_node" output="screen">
      </node>
    </launch>

    FILL IN THE {BLANK}(s)! Referring to what we learned about the format of launch files earlier, replace each {BLANK} above with the correct text to launch the publisher node that you created in Exercise 6.

  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 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 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 pubsub.launch file that you have now created.

  8. Launch this in TERMINAL 1 and then use $ rosnode list in TERMINAL 2 to check that it all works correctly.

Summary:

  • roslaunch can be used to launch multiple nodes on a robot from one single command.
  • It will also automatically launch the ROS Master (equivalent to running the roscore command manually) if it isn't already running. Did you notice that we didn't have to do this manually in Task 4, but we did when we launched our nodes individually using rosrun?
  • In the rospy.init(...) functions of our publisher.py and subscriber.py Python scripts, we defined a node name and set anonymous=True. As a result, when we launched our nodes manually using rosrun, the names we defined were honoured, but were appended with a unique combination of numbers.
  • When we launched our nodes using roslaunch however, the node names were set according to what we had defined in the name field of the <node> tag within the launch file, and anything specified within the rospy.init(...) function within our Python scripts was overwritten as a result.

Wrapping Up

In this session we've learnt about some key concepts in ROS, such as Packages; Launch files; Nodes and the Publisher-Subscriber Communication Method using Topics and Messages.

We have learnt how to use some key ROS commands:

  • roslaunch: to launch multiple ROS Nodes via launch files.
  • roscd: to navigate to installed ROS packages using a package name alone.
  • rosnode: to display information about active ROS Nodes.
  • rosrun: to run executables within a ROS package.
  • rostopic: to display information about active ROS topics.
  • rosmsg: to display information about all ROS messages that are available to use in a ROS application.
  • roscore: to launch the ROS Master: The baseline nodes and programs that are required for ROS to function.

In addition to this we also learnt how to use catkin_create_pkg, which is a helper script for creating ROS package templates.

We have also learnt how to work in the Linux Terminal and navigate a Linux filesystem using key commands such as:

  • pwd: prints the path of the current working directory to show you which directory you're currently located in.
  • ls: lists the files in the current directory.
  • cd: change directory to move around the file system.
  • mkdir: make a new directory (mkdir {new_folder}).
  • cat: show the contents of a file.
  • chmod: modify file permissions (i.e. to add execute permissions to a file for all users: chmod +x {file}).
  • touch: create a file without any content.

Finally, we have learnt how to create basic ROS nodes in Python to both publish and subscribe to ROS topics using standard ROS messages.

Saving your work

Remember, the work you have done in the WSL-ROS environment during this session will not be preserved for future sessions or across different University machines automatically! To save the work you have done here today you should now run the following script in any idle WSL-ROS Terminal Instance:

$ wsl_ros backup

This will export your home directory to your University U: Drive, allowing you to restore it at the start of the next session.

Navigating This Wiki:
← Getting Started [Previous] | [Next] Week 2: Odometry and Basic Navigation →