Controlling a robot using software is difficult. ROS gives us to a way structure, build and develop robotic software while making tedious tasks like setting up communication links between different software modules easy. This provides the developer with more time to focus on difficult tasks like robot control. In this lab, we will build, run, and inspect some simple ROS code to control an overly-simplified rocket simulation. The simulation in this lab has been over-simplified so that we can focus on learning the basics of ROS. However, in general, simulation is a great way to test if the code is working correctly before running it on an actual robot. The first half of this semester we will be using a Crazyflie simulator to fly and control a drone. Many other simulators have been built around robots that use ROS. Thus once you are done with this course, there are a bunch of other really advanced open-source simulators you can use to keep developing robotic code. Below are some of the simulators you will be able to download and use once you are done with this course.
This lab aims to teach you:
Let's assume we have been given the software used to fly a rocket to the moon. The rocket's software is written using ROS. Our job is to use the ROS tools to compile, launch, and then monitor this rocket on its journey to the moon.
To start the lab, download the lab code. You can do that by opening a terminal and running:
# Change to home directory
$ cd ~
# Clone the code
$ git clone https://github.com/hildebrandt-carl/RSECS4501-Spring2020-Lab1.git
# Get the labs workspace
$ mv RSECS4501-Spring2020-Lab1/lab1_ws ~/lab1_ws
# Do some cleanup
$ rm -rf RSECS4501-Spring2020-Lab1
To start, we first need to compile the rocket's ROS code. ROS code is organized into workspaces. A ROS workspace is a folder where you modify, build, and install ROS code. Let's compile the workspace now. Open a terminal in your virtual machine and run the following command:
# Change the directory to the ROS workspace
$ cd ~/lab1_ws/
# Compile the ROS code
$ catkin_make
If you get no errors, you have successfully compiled your rockets ROS code. Remember: In general, when you change your code and want to run it, you should compile it first.
Before you run any ROS code, you need to launch a roscore
. Robots, in general, are many different software modules working together to make the robot work. We call many different software modules working together a distributed system. One of the things roscore
does is creates a ROS master. The ROS master controls the distributed system and allows all the software modules to communicate with each other. In general, roscore
is a collection of programs that are pre-requisites of a ROS-based system, and roscore needs to be run before you start any ROS code. Open a terminal in your virtual machine and start a roscore
using the following command:
$ roscore
Next, let's run our rocket's software. The rockets software consists of three software components. Therefore to run our rockets software, we are going to need to open three new terminals. In each of the terminals run the following:
Terminal 1:
# Update your environment variables so that ROS knows where your workspace is
$ source ~/lab1_ws/devel/setup.bash
# Run the rocket-ship source code
$ rosrun rocketship rocket_engine.py
Hit enter, the rocket_engine
software is now running. You will see no further messages printed in this terminal.
Terminal 2:
# Update your environment variables so that ROS knows where your workspace is
$ source ~/lab1_ws/devel/setup.bash
# Run the rocket-ship source code
$ rosrun rocketship main_controller
Hit enter, the main_controller is now running. The main controller should respond with the following message:
>>> [ INFO] [...]: Rocket Ready for Countdown
Now let's get ready to launch the rocket! Start the countdown using terminal 3.
Terminal 3:
# Update your environment variables so that ROS knows where your workspace is
$ source ~/lab1_ws/devel/setup.bash
# Run the rocket-ship source code
$ rosrun rocketship countdown
If everything went correctly in terminal 2, you should see a countdown (after 5 seconds) and subsequent velocity commands as shown below:
>>> [ INFO] [...]: Countdown: 10s
>>> [ INFO] [...]: Countdown: 9s
>>> ...
>>> [ INFO] [...]: Requested Velocity: 0.076450m/s
>>> [ INFO] [...]: Requested Velocity: 0.077994m/s
>>> ...
That's awesome. We just launched the rocketship using ROS code! But let's dive deeper so that we start to understand what is going on behind the scenes. To launch this rocket, we needed four terminals. That is because we launched four separate pieces of software. We had to launch the roscore
, the rocket_engine
software, the main_controller
software, and the countdown
software. Using this information, we can start to fill in our understanding of the rocket's software, as shown below in the figure:
Having to run many different software components is not an uncommon problem in robotics. If we had to open a new terminal for each software component, robotics would not scale. ROS makes it easy to run multiple software components at the same time. ROS uses launch files to run many software components simultaneously. Remember, ROS is a distributed system, and launch files are a way to manage the complexity that comes with this distributed system. Another benefit of a ROS launch file is that it automatically checks if a roscore is running, and if not, starts one. Let's create a launch file to run all the software components of our rocket. First, open the base rocket.launch
file provided to you. You can do that using:
$ code ~/lab1_ws/src
And then navigate to the launch folder. It should be under rocketship/launch/rocket.launch
. You will find an empty launch file with xml code as shown below:
<?xml version="1.0"?>
<launch>
<!-- Add your code here -->
</launch>
Let's add each of the different software components into the launch file. ROS calls each software component a node. Add the following lines between <launch>
and </launch>
.
<node pkg="rocketship" type="rocket_engine.py" name="RocketEngineNode"></node>
<node pkg="rocketship" type="main_controller" name="MainControllerNode" output="screen"></node>
<node pkg="rocketship" type="countdown" name="CountDownNode"></node>
Take a second to try and understand what is inside the launch file. You are launching three software modules (nodes) rocket_engine, main_controller, and countdown. Each of the software components belongs to the rocketship package (pkg). We want the main_controller to output to screen. Save the file and go back to your terminal. Let's try and relaunch the rocket. Close all terminals and open a new one. To launch the rocket we need to run:
# Update your environment variables so that ROS knows where your workspace is
$ source ~/lab1_ws/devel/setup.bash
# Run the countdown code
$ roslaunch rocketship rocket.launch
This time you should see the rocket state that it is ready for launch. The countdown should automatically begin, and the rocket should launch!
Next, let's use some of the built-in ROS tools to get a better understanding of how our rocketship works. Let's start by finding what kind of communication is occurring between software modules in this rocketship. We can easily list all the communication in ROS at any given time using the following command. Leave the rocketship running and open another terminal. In that terminal, run the command. (Note we will discuss ROS nodes and topics in more detail in the next lecture)
# List all the communication channels (ROS topics)
$ rostopic list
You will see the following output:
>>> /cmd_vel
>>> /countdown
>>> /launch_abort
>>> ...
This shows us the names of all the created communication channels (topics). The next thing we might want to do is to display the data (ROS messages) being sent on any one of these communication channels. Lets, for instance, display the rockets commanded velocity /cmd_vel
. We can, at any time, view the data on any ROS communication channel using:
# Display the data on the ROS communication channel (ROS messages)
$ rostopic echo /cmd_vel
>>> data: 1684.0
>>> ---
>>> data: 1684.0
>>> ...
Notice how these numbers match the numbers being printed by the rocketship software:
>>> [ INFO] [...]: Requested Velocity: 1684.000000m/s›
>>> [ INFO] [...]: Requested Velocity: 1684.000000m/s
Our rocketship code is reasonably simple, and keeping track of what going on in our heads is manageable. However, when you get larger systems, it sometimes helps to visualize the software modules and the communication between software modules altogether. One way to do that is to use rqt_graph
. rqt_graph
provides a GUI plugin for visualizing the ROS computation graph. Open another terminal and while your rocketship is running run the following command:
$ rosrun rqt_graph rqt_graph
Change the first dropdown to Nodes/Topics (all) and uncheck the hide deadsinks and hide leaf topics as shown in the figure below:
This gives us a much clearer picture of the software we are running. Software modules in ROS are called nodes, and communication channels are called topics. Use this information to answer the first activity.
Take a screenshot of the ROS communication graph.
1) How many software modules (nodes) are there?
2) How many communication channels (topics) are there?
Previously we displayed data on the terminal using rostopic echo
. Displaying data on the terminal is not always the most effective way of understanding a system. Generally, if the data is continuous, it would be better to plot the data. rqt_plot
is a GUI used to visualize numeric values in ROS. Leave the rocket running and launch rqt_plot
by running the following in a new terminal:
$ rosrun rqt_plot rqt_plot
You will see output similar to the figure on the left. In the topic edit-box, type in /cmd_vel
and hit the green + button. You will see a blue line, as shown in the right-hand figure. Use the magnifying glass to set the scale correctly. Left-click and drag to zoom in. Right-click and drag to zoom out. (Note: The mapping between your primary OS and your virtual OS is different for each machine, and thus you might have to use shift to right-click for some machines.)
After running the rqt_plot
command, a GUI similar to this will appear on your screen.
Enter the cmd_vel
topic and hit the green + button. You can use the magnifying glass to zoom in and out (right-click and drag to zoom out).
You now have all you need to launch the rocket and plot the communicated data. Try and plot both the command velocity (/cmd_vel
) and the velocity sensor data (/sensor_vel
) using rqt_plot
. Relaunch the rocket's software so that you can see the velocity from the count down until it reaches maximum velocity.
The graph is continually updated and should look move as the rocket launches. This is what you should see.
Take a screenshot, including the entire GUI. The graph should look similar to this. This is what your screenshot should look like.
Answer the following question using the graph:
1) Why does the sensor readings (red line) not match the command velocity (blue line) exactly?
The final tool we will inspect in this lab is rqt_publisher
. rqt_publisher
provides a GUI plugin for sending arbitrary ROS messages. We will use this tool to control the abort function of our rocketship. You would have noticed that one of the communication channels (topics) the rocketship accept is called /launch_abort
. Let's use rqt_publisher
to abort one of our launches. While your rocketship is running open a new terminal and type:
$ rosrun rqt_publisher rqt_publisher
You will see a GUI appear, similar to the one below:
Remember, we were interested in the communication channel (topic) /launch_abort
. We are going to send (publish) messages on that communication channel (topic) and try and see if we can abort the rocketship. To do that, do the following:
First: Select /launch_abort
from the dropdown. Then change the frequency to 5. Then click the green + button.
Second: Open the message using the side arrows. Then select the checkmark. Selecting the checkmark sends messages.
You will notice that nothing happens. Let's investigate why. Open a new terminal and display the content (ROS messages) of the communication channel (topic) using the following code.
$ rostopic echo /launch_abort
>>> data: False
>>> ---
>>> data: False
>>> ...
This explains why it did nothing! We were sending /launch_abort
message set to false. So we are telling the robot not to abort! To send true abort messages, check the checkbox next to the word false. Once you have done that, you should see the following appear on your rocketship terminal:
>>> [ INFO] [...]: Abort Failed
>>> [ INFO] [...]: Requested Velocity: 1684.000000m/s
>>> [ INFO] [...]: Requested Velocity: 1684.000000m/s
>>> [ INFO] [...]: Abort Failed
>>> [ INFO] [...]: Requested Velocity: 1684.000000m/s
The abort fails because the rocketship is already flying and so you can abort the launch.
Rerun the abort test, but try and abort before the rocket takes off.
1)What does the rocket print to the terminal when you abort before launch?
2) After the successful abort, try and echo the command velocity (/cmd_vel
). What message do you receive, and does this make sense?
At the end of this lab, you should have the following:
/cmd_vel
? Does this make sense?