Minitask 1 - RobotTeaching/COMP4034 GitHub Wiki

In this mini-task, you'll create your first ROS package and write your first program. Resources are provided at the bottom of the page, so feel free to refer to them as needed.

Task 1: Creating a ROS package

Open a terminal and navigate to your catkin_ws/src directory:

cd ~/catkin_ws/src

Use catkin_create_pkg command to create a new ROS package:

# catkin_create_pkg <package_name> [dependencies]
catkin_create_pkg minitask1 std_msgs geometry_msgs rospy

Catkin is a workspace manager and build tool that we will use to create, build, and manage our ROS packages. You can find out more about catkin and this command in Resource 1 at the bottom of the page.

Once you've created your package, return to the catkin_ws directory by typing cd ~/catkin_ws in your terminal.

Build your package by running catkin_make.

Once built, re-source your workspace by running . ~/catkin_ws/devel/setup.bash. This ensures that any new environment variables, paths, or package information set by catkin_make are applied to your current shell session. In other words, it sets up your environment with the paths and variables required for ROS to find and use your packages. If you don’t source it, your terminal won’t recognize the changes (like new packages or updates).

You will need to run catkin_make and re-source your workspace whenever you make a change to your package. You'll need to source your workspace like this in any fresh terminal unless you modified your .bashrc file to do it automatically for you.

Task 2: Exploring the /cmd_vel topic

From the lectures, remember that ROS uses a publisher/subscriber model where nodes communicate via topics, each with a specific message type. In this task, you'll explore the /cmd_vel topic.

In Minitask 0, you simulated a robot and drove it around while echoing the /odom topic. In this task, you'll follow similar steps, but this time you'll echo the /cmd_vel topic:

  1. In your terminal, run roslaunch turtlebot3_gazebo turtlebot3_world.launch
  2. In a new terminal tab, run roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch
  3. Open a new terminal and run rostopic echo /cmd_vel

The last terminal will show messages with components showing 0.0 - how does this change as you drive your TurtleBot? (Refocus the teleop window to drive the robot).

Upon closer inspection, you'll notice that /cmd_vel messages are of type Twist. Check Resource 2 to learn what a Twist message contains.

Task 3: Publishing messages using the command line

n Resource 2, you’ll see that a Twist message contains two Vector3 components. You can find more information about these components linked at the bottom of the resource page. This knowledge will be useful for the next step, where you'll publish commands to the robot using the command line.

First, stop the terminals running the teleop and rostopic echo. You can use one of these terminals or open a new one for the following steps (just remember to source your workspace if you do!).

Resource 3 has information on how to use rostopic pub to publish a message to a topic. Use this resource, along with your understanding of Twist messages, to publish a Twist command to /cmd_vel.

Task 4: Writing a publisher to move the robot

This link provides example code to create a basic ROS publisher. Inside the package you created earlier, move into the src folder and create a file called mover.py (in your terminal, touch mover.py) and make it executable by running chmod +x mover.py in your terminal. Study the code from the link and once you understand it, copy it into this file.

NOTE: If you get an error like 'python' no such file or directory check the top line of your code. It should be #!/usr/bin/env python3. You should always be using python3.

You can use Resource 4 to help you understand this code - and make sure you fully grasp it! Next, you'll modify this code to move your robot by publishing Twist messages. Here are some hints:

  1. Change all instances of talker to mover
  2. The line pub = rospy.Publisher... needs to be changed. rospy.Publisher takes in a topic, a message type, and a queue length (which you can leave as 10).
  3. Since you need to drive the robot, which topic should you publish to? Consider where the robot expects to receive movement commands.
  4. After identifying the correct topic, you'll need to create a Twist message to publish. A Twist contains linear (x, y, z) and angular (x, y, z) components, which control the robot's movements. You'll need to set these components as appropriate. These act like structs, so to change the linear x, you must change the linear.x property of your Twist() message.
  5. Your robot only has linear motion in the x-axis, and angular rotation on the z-axis. Why do you think that is?
  6. Don't forget to add an import for Twist from geometry_msgs.msg at the beginning of your file.

When you are ready to try running your code, remember that you need to return to the catkin_ws directory and execute catkin_make. Then, in your terminal, use rosrun minitask1 mover.py to run your code. rosrun takes in a package name and a script name.

Note: if, on your own install, you get an error about being unable to find Python, run the command sudo apt install python-is-python3 in your terminal and try again.

Task 5a: Driving around in a square (easy mode)

Now that you can publish Twist messages in your code, you will need to edit your code so your robot drives around in a square. You should publish two Twist messages, one after the other, until the program is terminated - one to move the robot forwards, and one to turn.

Your code is already in a loop while not rospy.is_shutdown() which repeats 10 times a second, so you can use the rospy.Time library to check how much time has passed in the loop. You'll need to start with rospy.Time.now().to_sec() to get the current time. You will need to figure out how long to drive your robot forwards for, and how long (and fast!) to turn for to get to 90 degrees.

Task 5b: Driving around in a square (hard mode)

Your robot should now drive around in a roughly square shape now. But simply timing your actions won’t give you an accurate square in the real world (think of the wheels slipping on sand!). A better approach is to adjust the robot’s actions based on how far it has actually moved. For that, the robot needs to know its position. The easiest way to get this info with the Turtlebot is by using odometry data, which estimates the robot's position and orientation by tracking wheel movement over time.

We’ll implement this by modifying your mover.py script. Start by opening it in your preferred editor. First, add an import statement for Pose from geometry_msgs.msg. Then, under where you created the publisher, define a subscriber to the /odom topic:

rospy.Subscriber("odom", Odometry, odom_callback)

The three parameters in this constructor are the topic name, the message type, and the name of the callback function. So, you need to implement a callback function. Define one called odom_callback with a parameter called msg, which will hold the Odometry data your subscriber listens to.

Hint: you'll need to import Odometry from nav_msgs.msg, and you'll need to import tf for the below code to work.

In this function, to extract the (x, y) position of the robot and its rotation (theta), we will need to convert the orientation in the Odometry message from a quaternion to Euler angles. You can use the code below to do so:

# Get (x, y, theta) specification from odometry topic
quaternion = [msg.pose.pose.orientation.x,msg.pose.pose.orientation.y, msg.pose.pose.orientation.z, msg.pose.pose.orientation.w]
(roll, pitch, yaw) = tf.transformations.euler_from_quaternion(quaternion)

self.pose.theta = yaw
self.pose.x = msg.pose.pose.position.x
self.pose.y = msg.pose.pose.position.y

You can find out more about quaternions using Resource 6, but for now you can just accept that they're a different way of representing space. Make sure you understand the above code snippet though.

Note: to use self in a Python class, you'll need an __init__ method. This is left as an exercise for you, to get you more familiar with Python.

Now, you can use the odometry data to implement the following steps, so that your robot attempts to move in a more robust square:

1. Initialise current `pose(x,y,theta)` of the robot and select a desired `pose(x*,y*,theta*)`. The `x*` and `y*` should be set as the first corner coordinates of the 1m-edge square you will traverse. `theta*` should be current `theta` plus 90 degrees
2. Move forward and accumulate the travelled distance. 
3. Stop if the total distance is greater than 1m. This is the end of your first edge.
4. Now set the desired orientation as `theta* = theta*+PI/2`
5. Rotate in place (remember the `Twist` message) until the accumulated orientation is greater than `PI/2`
6. Pause
7. Repeat until the square is complete.

Resources:

Resource 1 - Creating a catkin package

Resource 2 - Twist message

Resource 3 - rostopic pub

Resource 4 - ROS tutorial on writing a simple Publisher and Subscriber in Python

Resource 5 - Pose message

Resource 6 - Quaternions