This page is located in archive. Go to the latest version of this course pages. Go the latest version of this page.

Homework 01

Your task will be to explore a bagfile containing data from a laser scanner (obtained from a real turtlebot). Once you have familiarized yourself with the contents of the bagfile, you should create a node that will collect and process the laser scanner data. After collecting the specified number of samples, the node will publish the collected data in batch using a ROS message. You can find a more detailed description of the individual sub-tasks below.

Reading messages from the bagfile

  1. Download the bagfile from the labs web page. Link should be next to the link to this document or:
    $ wget https://cw.fel.cvut.cz/b202/_media/courses/aro/tutorials/2019-02-20-11-00-56.zip
    $ unzip 2019-02-20-11-00-56.zip
  2. Check the contents of the bagfile with rosbag info:
    rosbag info <bag_name>
    and rqt_bag (the roscore has to be run first):
    rqt_bag <bag_name>
  3. Find topic name and message type corresponding to data from a laser scanner. This is a device that takes range measurements using laser ranging technique. The laser is incrementally (but very quickly) rotated and a measurement is taken after each increment. Thus, a single scan contains multiple range measurements taken at different angles. Based on the data (ROS message) type, try to find documentation for the laser scanner data (e.g., using rosmsg show <msg_type> command, or more detailed documentation at http://wiki.ros.org/sensor_msgs).
  4. Create a package named aro_scan containing python script scancollector.py and necessary ROS package configuration files “CMakeList.txt”, “package.xml”.
  5. Create a node in file scancollector.py that will listen for the messages from the laser scanner in the provided bag file and process them in the following way:
    1. Filter out possibly erroneous data (i.e. outside of the normal value range – see the message documentation)
    2. Discard measurements taken at an angle greater than 30° or lower than -30° (i.e. abs(angle) > 30°)
    3. Compute the mean of the remaining values and store it into a buffer (you can use Python list or numpy array)
    4. Store the message timestamp as well (you can store it as a single float using the to_sec() function)
    5. If the number of stored values had reached the number specified in the batch_length global parameter:
      1. Stop accumulating the data
      2. Publish the data to the scan_filtered topic as std_msgs/Float32MultiArray containing computed means in field data. The layout field does not have to be filled with any values.
  6. Run all the nodes and then play the bagfile (rosbag play).


You can plot the data to check it using the plot(x, y) function of the pyplot module from the matplotlib package. You might also need to use the show() function to show the plot.

Setting up the parameters

  1. Next, you will need to set a couple of parameters. Hint: use rospy.get_param().
  2. First, get a global parameter with the name batch_length specifying the number of values that shall be collected.
  3. Set a second global parameter called start_time that will hold the starting timestamp of the ROS bag recording.


  • You can find most of the necessary information within the presentations from Lab 01.
  • The rest could be found using the mentioned commands or by following the provided links.
  • If you have problem with plotting, search for matplotlib plot examples or documentation
  • When dealing with more complex nodes and persistent variables, it is useful to create a class that will handle all of the data processing. In the case of the listener node, the structure of your script scancollector.py should look like this:
    #!/usr/bin/env python3
    import rospy
    import numpy as np
    # TODO other imports
    class ScanCollector():
        def __init__(self):
            # Initialize the node here
            # retrieve the necessary parameters from the parameter server
            rospy.get_param( ... )
            # and store them into variables
            # create the listener object and assign a class method as the callback
            # possibly do some additional stuff
        def scan_callback(self, msg):
            # process the message
            # if enough data has been collected, publish the data
    if __name__ == '__main__':
        sc = ScanCollector()


Here is an example of a data plot (extracted from the bag with plot_length set to 500):

Your plot might differ a little, depending on the parameters. You also don't need to tune value ranges of the plot axis and the labels (but the plot will look nicer if you do!)


Please, submit your solution to the upload system. Upload the whole package aro_scan (as a folder with matching name, that contains the script and the config files “CMakeList.txt”, “package.xml”). Please, do not upload the entire workspace or just the files. 5 points will be awarded for valid submission.

  • The solution must work as described above.
  • The submitted package must be “buildable” by catkin build in a ROS Noetic distro.
  • The script scancollector.py must be “runnable” by calling rosrun after building and sourcing the workspace, and its parameters settable from rosparam server. Check if this is true before submission.
courses/aro/tutorials/homework01.txt · Last modified: 2023/03/01 13:29 by penicrob