Week 2 - tom-howard/com2009 GitHub Wiki
You should be able to complete the exercises on this page within a two-hour lab session.
- Exercise 1: Exploring Odometry Data
- Exercise 2: Creating a Python node to process Odometry data
- Exercise 3: Moving a Robot with
rostopicin the Terminal - Exercise 4: Creating a Python node to make the robot move
This week you will learn how to control a ROS robot's position and velocity from both the command line and through ROS Nodes. You will also learn how to interpret data that allows us to monitor a robot's position in its physical environment. The things you will learn here form the basis for all robot navigation in ROS, from simple open-loop methods to more advanced closed-loop control (which you will learn more about next week).
By the end of this session you will be able to:
- Interpret the Odometry data published by a ROS Robot and identify the parts of these messages that are relevant to a 2-wheeled differential drive robot (such as the TurtleBot3).
- Develop Python nodes to obtain Odometry messages from an active ROS network and translate them to provide useful information about a robot's pose in a convenient, human-readable way.
- Implement open-loop velocity control of a robot using ROS command line tools.
- Develop Python nodes that use open-loop velocity control methods to make a robot follow a pre-defined motion path.
-
If you haven't done so already, launch your WSL-ROS environment by running the WSL-ROS shortcut in the Windows Start Menu. As you will now know, this may take a couple of minutes, but once it's ready this will open up the Windows Terminal and an Ubuntu terminal instance (which we'll refer to as TERMINAL 1).
-
It's also worth launching VS Code now, so that it's ready to go for when you need it later on. Follow the steps here to launch it correctly.
Remember that any work that you do within this WSL-ROS Environment will not be preserved between sessions or across different University computers. At the end of the previous practical session you should have run the wsl_ros tool to backup your home directory to your University U: Drive. Restore this now before you start on this Week 2 session by running the following command in TERMINAL 1:
[TERMINAL 1] $ wsl_ros restore
In the terminal 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
Remember: A
$symbol indicates a command that can be entered directly into the Linux Terminal. Enter (or copy and paste) all the text after the$into the terminal, excluding the$.
A Gazebo simulation window should open and within this you should see a TurtleBot3 Waffle in empty space:
You should already know from the Introducing the Robots Section of this Wiki that the TurtleBot3 Waffles that we are working with have the following sensors and actuators on-board to allow them to navigate:
- Two independently controlled wheel motors (a differential drive configuration).
- An Inertial Measurement Unit (IMU) to detect motion & orientation.
- A 360° laser displacement sensor (LiDAR) to detect its environment.
Two types of Velocity Command can be issued to any ROS Robot to make it move:
- Linear Velocity: The velocity at which the robot moves forwards or backwards in one of its axes.
- Angular Velocity: The velocity at which the robot rotates about one of its axes.
The TurtleBot3's principal axes are defined as follows:
Because the TurtleBot3 robot has a differential drive configuration, it can only move linearly in the x axis. In order to move to the left or right, it must first rotate to face the desired direction before moving forward. In addition to this, the robot can only rotate about its z (yaw) axis.
It's also worth noting that the TurtleBot3 Waffle robots have the following maximum velocity limits:
- A maximum linear velocity of 0.26 m/s,
- A maximum angular velocity of 1.82 rad/s.
In the previous session you learnt how to list all the topics that are currently active on a ROS system. Open up a new terminal instance (TERMINAL 2) and use what you learnt last week to list all of the topics that are active on the ROS network now, as a result of you launching the Gazebo simulation in the step above.
Which topic in the list do you think could be used to control the velocity of the robot? Use the rostopic info command on the topic to find out more about it.
The topic you have identified should use a message of the geometry_msgs/Twist type. You will have to send messages of this type to this topic in order to make the robot move. Use the rosmsg command (as you did last week) to find out more about the format of this message.
As we learnt above, the TurtleBot3 can only generate linear velocity in the x axis and angular velocity in the z axis. As a result, only velocity commands issued to the linear.x or angular.z sections of this message will have any effect.
Another topic that should have appeared when you ran the rostopic list command above is /odom. This topic contains Odometry data, which is also essential for robot navigation and is a basic feedback signal, allowing a robot to approximate its location.
-
In TERMINAL 2 use the
rostopic echocommand to display the odometry data currently being published by our simulated robot:[TERMINAL 2] $ rostopic echo -c /odomExpand the terminal window as necessary so that you can see the whole topic message (it starts with
headerand ends with---).What does the
-coption in the command above actually do? -
Now, you need to launch a new Windows Terminal instance so that you can view it side-by-side with TERMINAL 2. To do this, press the "New Tab" button whilst pressing the
Shiftkey. We'll call this one WT(B). Arrange both windows side-by-side so you can see what's happening in both, simultaneously. -
In WT(B) launch the
turtlebot3_teleop_keyboardnode as you did last week:[WT(B)] $ roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch -
In WT(B) enter
Aa couple of times to make the robot rotate on the spot. Observe how the odometry data changes in TERMINAL 2. Is there anything in thetwistpart of the/odommessage that corresponds to theangular velthat you are setting in WT(B)? -
Now press the
Skey to halt the robot, then pressWa couple of times to make the robot drive forwards. How does thetwistpart of the message now correspond to thelinear velsetting in WT(B)? -
Now press
Da couple of times and your robot should start to move in a circle. What linear and angular velocities are you requesting in WT(B) and how are these represented in thetwistpart of the/odommessage? What about theposepart of the message? How is this data changing as your robot moves in a circular path, what do you think this tells you? -
Press
Sin WT(B) to halt the robot (but leave the keyboard teleop node running). Then, pressCtrl+Cin TERMINAL 2 to shutdown therostopic echonode. -
Next, with the robot stationary, use
rosrunto run a Python node that we have created to help illustrate what odometry data actually represents in terms of the robot's potion and orientation in its environment:[TERMINAL 2] $ rosrun com2009_examples robot_odometry.py -
Now (using the keyboard teleop node in WT(B)), drive your robot around again, keeping an eye on the outputs that are being printed by the
robot_odometry.pynode in TERMINAL 2 as you do so.The output of the
robot_odometry.pynode shows you how the robot's odometry is changing in real-time as you move the robot around. The"initial"column tells us the robot's odometry (its position and orientation) when the node was first launched, and the"current"column show us what it currently is. The"delta"column then simply shows the difference between the two. Which odometry parameters haven't changed, and is this what you would expect (considering the robot's principal axes as illustrated above)? -
Press
Ctrl+Cin TERMINAL 2 and WT(B), to stop therobot_odometry.pyandturtlebot3_teleopnodes. Then, close down WT(B) so that only one Windows Terminal application remains open with 2 active tabs: TERMINAL 1 and TERMINAL 2.
We can learn more about Odometry data by using the rostopic info command:
$ rostopic info /odom
This provides information about the type of message used on this topic:
Type: nav_msgs/Odometry
We can find out more about this using the rosmsg info command:
rosmsg info nav_msgs/Odometry
Which tells us that the nav_msgs/Odometry message contains four base elements:
- header
- child_frame_id
- pose
- twist
pose tells us the position and orientation of the robot relative to an arbitrary reference point (typically where the robot was when it was turned on). The pose is determined from:
- Data from the Inertial Measurement Unit (IMU) onboard the OpenCR board,
- Data from both the left and right wheel encoders,
- An estimation of the distance travelled by the robot from its pre-defined reference point (using dead-reckoning).
Position data is important for determining the movement of our robot, and from this we can estimate its location in 3-dimensional space.
Orientation is expressed in units of Quaternions, and needs to be converted into angles (in degrees) about the principal axes. Fortunately, there are functions within the ROS tf library to do that for us, which we can use in any Python node as follows:
from tf.transformations import euler_from_quaternion
(roll, pitch, yaw) = euler_from_quaternion([orientation.x,
orientation.y, orientation.z, orientation.w],
'sxyz')Our TurtleBot3 robot can only move in a 2D plane and so, actually, its pose can be fully represented by (x,y,θz), where x and y are the 2D coordinates of the robot in the X-Y plane, and θz is the angle of the robot about the z (yaw) axis. You should have noticed this in the exercise above, where the linear_z, theta_x and theta_y values in the delta column should all have read 0.000 (or changed very little).
twist tells us the current linear and angular velocities of the robot, and this data comes directly from the wheel encoders.
All of this data is defined in terms of the principal axes, as illustrated in the figure above.
In the previous session you learnt how to create a package and build simple nodes in Python to publish and subscribe to messages on a topic.
-
Create a package in the same way as last week, this time called
week2_navigation, which depends on therospy,nav_msgsandgeometry_msgslibraries. Use thecatkin_create_pkgtool as you did last week. Remember to ensure that you are located in the~/catkin_ws/src/directory before you do this though:[TERMINAL 2] $ cd ~/catkin_ws/src/ [TERMINAL 2] $ catkin_create_pkg ... -
Run
catkin buildon this:[TERMINAL 2] $ catkin build week2_navigationand then re-source your environment by entering:
[TERMINAL 2] $ src -
Navigate to the
srcfolder within yourweek2_navigationpackage using the Linuxcdcommand. -
The
subscriber.pycode that you used last week can be used as a template for creating your odometry subscriber. First, create a new file in yourweek2_navigationpackagesrcfolder (~/catkin_ws/src/week2_navigation/src) calledodom_subscriber.py:[TERMINAL 2] $ touch odom_subscriber.py -
In the same way as last week, make this file executable using the Linux
chmodcommand. -
In the VS Code File Explorer navigate to the
~/catkin_ws/src/week2_navigation/srcfolder and open theodom_subscriber.pyfile that you have just created. Then, copy the subscriber code from last week. -
Now, edit the code to subscribe to and print out odometry data to the terminal:
-
You will need to make sure that you are importing the correct message type at the start of your code so that you can work with the Odometry data. In the Week 1 Subscriber we were working with a
Stringtype message from thestd_msgspackage, whereas this time we need to use anOdometrymessage from thenav_msgspackage instead. If you need help, have a look at this explainer. -
Your Python node should convert the raw odometry data to a
(x,y,θz)format using theeuler_from_quaternionfunction from thetf.transformationslibrary (remember thatθzis the same as Yaw). If you aren't sure how to do this, why not have a look at the source code for therobot_odometry.pynode from thecom2009_examplespackage that you used in the previous exercise. Remember that you can find out where this package is located by using theroscdcommand. -
You should aim for the output of your node to look something like this:
-
-
Launch your node using
rosrunand observe how the output (the formatted odometry data) changes whilst you move the robot around again using theturtlebot3_teleopnode in a new terminal instance (TERMINAL 3). -
Stop your
odom_subscriber.pynode in TERMINAL 2 and theturtlebot3_teleopnode in TERMINAL 3 by enteringCtrl+Cin each of the terminals.
Note: Make sure that you have stopped the
turtlebot3_teleopnode running in TERMINAL 3 (by enteringCtrl+C) before starting this exercise.
We can use the rostopic pub command to publish data to a topic from a terminal by using the command in the following way:
rostopic pub {topic_name} {message_type} {data}
As we discovered earlier, the /cmd_vel topic is expecting linear and angular data, each with an x, y and z component. We can get further help with formatting this message by using the autocomplete functionality within the terminal. Type the following into TERMINAL 3 (copying and pasting won't work):
[TERMINAL 3] rostopic pub /cmd_vel geometry_msgs/Twist[SPACE][TAB]
The full message should then be presented to us:
$ rostopic pub /cmd_vel geometry_msgs/Twist "linear:
x: 0.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.0"
- Scroll back through the message using the ← key on your keyboard and then edit the values of the various parameters, as appropriate. First, define some values that would make the robot rotate on the spot. Make a note of the command that you used.
- Enter
Ctrl+Cin TERMINAL 3 to stop the message from being published. - Next, enter a command in TERMINAL 3 to make the robot move in a circle. Again, make a note of the command that you used.
- Enter
Ctrl+Cin TERMINAL 3 to again stop the message from being published. - Finally, enter a command to stop the TurtleBot and make a note of this too.
- Enter
Ctrl+Cin TERMINAL 3 to stop this final message from being published.
You will now create another node to control the motion of your TurtleBot3 by publishing messages to the /cmd_vel topic. You created a publisher node in Week 1, and you can use this as a starting point.
-
In TERMINAL 2, ensure that you are still located within the
srcfolder of yourweek2_navigationpackage. You could usepwdto check your current working directory, where the output should look like this:/home/student/catkin_ws/src/week2_navigation/srcIf you aren't located here then navigate to this directory using
cd. -
Create a new file called
move_circle.py:[TERMINAL 2] $ touch move_circle.py... and make this file executable using the
chmodcommand. -
Open up this file in VS Code, then copy and paste the contents of the publisher node from last week into the new
move_circle.pyfile to get you started. Then edit the code to achieve the following:- Make your TurtleBot3 move in a circle with a path radius of approximately 0.5m.
- The Python node needs to publish
Twistmessages to the/cmd_veltopic in order to make the TurtleBot move. Have a look at this usage example. - Remember (as mentioned earlier) that for our robot, the maximum linear velocity (
linear.x) is 0.26 m/s, and the maximum angular velocity (angular.z) is 1.82 rad/s. - Make sure that you code your
shutdownhook()correctly so that the robot stops moving when the node is shutdown (viaCtrl+Cin the terminal that launched it).
Advanced features:
- Create a launch file to launch this and your
odom_subscriber.pynode simultaneously with a singleroslaunchcommand. Refer to the launch file that you created last week for a reminder on how to do this.
In this session you have learnt how to control the velocity and position of a robot from both the command-line (using ROS command-line tools) and from ROS Nodes by publishing correctly formatted messages to the /cmd_vel topic.
You have also learnt about Odometry, which is published by our robot to the /odom topic. The odometry data tells us the current linear and angular velocities of our robot in relation to its 3 principal axes. In addition to this though, it also tells us where in physical space our robot is located and oriented, which is determined based on dead-reckoning. You will learn a bit more about dead-reckoning in your lectures.
Consider the following:
- How is dead-reckoning implemented, and what information is needed to do this?
- What might the implications be for a robot that implements odometry-based navigation?
- Can a control method that uses this as a feedback signal be considered an implementation of closed-loop control?
We'll explore this a little more next week, but you might want to consider reading Chapter 11.1.3 ("Pose of Robot") in the ROS Robot Programming eBook that we mentioned here.
Remember, the work you have done in this WSL-ROS environment today 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
Navigating This Wiki:
← Week 1: ROS and Linux Basics [Previous] |
[Next] Week 3: Advanced Navigation and SLAM →