======= Homework 01 =======
Your task will be to explore a {{ :courses:aro:tutorials:2019-02-20-11-00-56.zip | 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 plot the collected data. You can find a more detailed description of the individual sub-tasks below.
===== Reading messages from the bagfile =====
- Download the {{ :courses:aro:tutorials:2019-02-20-11-00-56.zip | 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
- Check the contents of the bagfile:
rosbag info
rqt_bag
- 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. {{http://wiki.ros.org/sensor_msgs|http://wiki.ros.org/sensor_msgs}}).
- Create a node that will listen for the messages from the laser scanner and process them in the following way:
- Filter out possibly erroneous data (i.e. outside of the normal value range – see the message documentation)
- Discard measurements taken at an angle greater than 30° or lower than -30° (i.e. abs(angle) < 30°)
- Compute the mean of the remaining values and store it into a buffer (you can use __Python list__ or __numpy array__)
- Store the message timestamp as well (you can store it as a single float using the __to_sec()__ function)
- If the number of stored values had reached the number specified in the __plot_length__ global parameter:
- Stop accumulating the data
- Plot the data
- on the X-axis: the timestamps minus the value in the global parameter __start_time__ – that is, each value should represent the number of seconds from the beginning of the bagfile.
- on the Y-axis: the computed means
- Run all the nodes and then play the bagfile (rosbag play).
===== Plotting =====
Plot the data using the __plot(x, y)__ function of the [[https://matplotlib.org/api/pyplot_api.html|pyplot module]] from the //matplotlib// package. You might also need to use the __show()__ function to show the plot.
===== Setting up the parameters =====
- Next, you will need to set a couple of parameters.
- First, set a global parameter with the name __plot_length__ specifying the number of values that shall be collected and plotted.
- Set a second global parameter called __start_time__ that will hold the starting timestamp of the ROS bag recording.
===== Hints =====
* 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.
* Check [[http://wiki.ros.org/rospy/Overview/Time|http://wiki.ros.org/rospy/Overview/Time]] if you need help with the timestamps.
* 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 should look like this:
#!/usr/bin/env python2
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
# 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, plot the data
if __name__ == '__main__':
sc = ScanCollector()
rospy.spin()
===== Example =====
Here is an example of the resulting plot (extracted from the bag with plot_length set to 500):
{{ :courses:aro:tutorials:figure_1_hw.png?nolink&800 |}}
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!)
===== Evaluation =====
Please, submit your solution to the [[https://cw.felk.cvut.cz/upload/|upload system]]. Upload only the folder of your package (e.g., "example_package", that contains a "src" folder, and the config files "CMakeList.txt", "package.xml"). Please, do not upload the entire workspace.
* The solution must work as described above.
* The submitted package must be "buildable" by catkin build in a ROS Melodic distro