======= Homework 01 ======= /* The assignment has not been finalized yet. Please wait for the final version of the assignment to avoid any inconsistencies between your solution and automatic evaluation. */ 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 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 ===== - 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 with rosbag info: rosbag info and rqt_bag (the roscore has to be run first): 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., using ''rosmsg show '' command, or more detailed documentation at {{http://wiki.ros.org/sensor_msgs|http://wiki.ros.org/sensor_msgs}}). - Create a package named ''aro_scan'' containing python script ''scancollector.py'' and necessary ROS package configuration files "CMakeList.txt", "package.xml". - 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: - 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 __batch_length__ global parameter: - Stop accumulating the data - 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. - Run all the nodes and then play the bagfile (rosbag play). ===== Plotting ===== You can plot the data to check it 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. Hint: use ''rospy.get_param()''. - First, **get** a global parameter with the name __batch_length__ specifying the number of values that shall be collected. - **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 ''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() rospy.spin() ===== Example ===== Here is an example of a data 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 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.