Homework: Gazebo and ROS Control
Table of Contents
1 Submission Instructions
Just like all other assignments so far, this will be submitted via Classroom for GitHub. See Canvas for the secret link for creating your private repository. Note that unlike other assignments, this assignment's repository will automatically start out with a copy of the rrbot_control_me495 package. You will be adding nodes, launch files, configuration files, and README answers to this package, and pushing your changes to the repo automatically created for you by GitHub Classroom.
All deliverables described below should be pushed to this repository, and a URL similar to https://github.com/ME495-EmbeddedSystems/homework-4-f2018-YOUR-USERNAME should be submitted via Canvas before the due date.
All answers should be in a README file located in the root of the package (a template has been created for you). Items that should specifically be addressed in the README and in the repo are highlighted like this. The README should have nice formatting, your repo should have evidence of proper Git usage (multiple commits, no extra files, etc.), and you should properly conform to the file hierarchy pre-specified by the package. If you have questions about anything, please post to Canvas.
2 rrbot and ROS interfacing
First you should complete the Using a URDF in Gazebo Tutorial and the Using Gazebo plugins with ROS Tutorial. It is up to you how carefully you follow the tutorials, but many hints and further explanations related to the tasks below are included in the tutorials. You will be writing new configuration files, launch files, and nodes that will be added to your copy of the rrbot_control_me495 package cloned from GitHub Classroom. These files will add new functionality to the gazebo_ros_demos demos package discussed in these two tutorials. Note, for both of the tutorials the kinetic-devel branch of gazebo_ros_demos should work fine on Melodic.
- In this problem, your first goal is to use the Gazebo GUI to create a
custom world. This world should have at least three built-in models
(dumpsters, cones, houses, etc.). Later you will be inserting an
rrbotmodel into this world. Save this world file and add it to your repository; be sure your README links to this world file. - Write a launch file that starts Gazebo with your custom world from the
previous problem, and inserts the default
rrbotmodel fromgazebo_ros_demos. You should use thespawn_modelnode fromgazebo_rosto insert therrbotmodel into the world. README should link to the launch file and include a screenshot of the rrbot in the custom world. - Once Gazebo is running with your simulated
rrbotyou will use theimage_vieworrqt_image_viewnode to display the simulated camera feed from Gazebo. README should include a screenshot of image and should address the following: (a) what command was used to start your image viewer? (b) what is the name of the plugin responsible for simulating the camera? (c) what topic is the simulated image published on and where was this topic name defined? Write a launch file that starts
rvizwith a nice configuration to view the camera, the laser scanner, and therrbot. For now, your launch file should also include thejoint_state_publisherto specify the joint values for ROS (we'll discuss why this is necessary in the next section). You can use the rrbot_rviz.launch file for inspiration. If you can't get the laser scans to show up inrviz, you may be running into a driver issue. By default, therrbotuses the gazebo_ros_gpu_laser plugin to simulate the laser scanner. This plugin is supposed to work by using your graphics card to compute the ray-tracing required to simulate the laser scanner, but in my experience, this doesn't work very well for many graphics card/driver combos. If the laser scanner isn't showing up, try one of the following:- Modify the appropriate xacro files to use a non-GPU laser scanner. The plugin is called gazebo_ros_laser.
- Set the LIBGL_ALWAYS_SOFTWARE environment variable to ensure that your
system uses the CPU instead of your GPU for rendering calculations.
Note that this may have a serious impact on the performance of your
system. It is not recommended to put this in your
.bashrc. The command to set this environment variable isexport LIBGL_ALWAYS_SOFTWARE=1.
Modify the noise settings for the simulated laser scanner and inspect how the scans change. Your README should include a link to the launch file, a link to your rviz configuration, screenshots of the simulated laser scanner in rviz with both noise settings, and a description of which files were edited to change the noise settings. If you ran into issues getting the laser scanner to show up, you should also describe how you fixed it. When you are done with this problem feel free to either revert or keep any edits you made regarding the noise models in the laser plugin in the
gazebo_ros_demospackage; for the next section it doesn't matter what the settings are.
3 ROS control, ROS communication, and custom plugins
Before completing this section, you should complete the following tutorials:
As before, it is up to you to decide how closely you want to follow the tutorials, but they do provide quite a lot of helpful information.
In the last section, we needed the
joint_state_publisherto createsensor_msgs/JointStateinformation to tellrvizthe pose of therrbot. This is an artifact of the way thegazebo_ros_controlpackage's plugins interact with Gazebo/ROS. By default, thegazebo_ros_controlplugin does not provide joint state information to ROS. Rather, you must load a properly-configured joint_state_controller plugin with thespawnernode from thecontroller_managerpackage. This plugin then interacts with the Gazebo simulation and automatically publishes joint state information. One could easily write a custom plugin to provide a less-complicated interface between ROS and Gazebo, but it would likely be less generic and not feature the same hardware abstractions thatros_controlprovides.Complete the following tasks:
- Write a YAML file that configures the
joint_state_controller/JointStateControllerto convert model poses tojoint_statesinformation. - Write a launch file that starts
rviz, aspawnernode, therobot_state_publisher, and loads the correctrobot_descriptionparameter. This can either be a new launch file, or you can modify one of your launch files from the previous section and add an argument to toggle between thejoint_state_publisherproviding joint state information and Gazebo providing the joint state information. You may need toremapor relay the joint state information to get the correct topic names. Just like in the tutorials, I'd recommend one launch file for starting Gazebo with your custom world, and a separate launch file for starting everything else.
Your README should include a link to the joint state controller configuration file, a link to the launch file, and instructions for running the launch file(s).
- Write a YAML file that configures the
- Write a ROS node in Python that uses the
/gazebo/apply_joint_effortservice to apply torques to therrbotjoints to get it to swing back in forth. If you are really fancy, you could even write a controller that subscribes to the joint state information and stabilizes therrbotto a reference configuration trajectory by setting the joint torques (this is not necessary!). Add a link to the node source code to your README, and describe how to run your node (could be one launch file, two launch files, or two launch files and a rosun command). The template package you cloned includes a custom ROS plugin. This plugin subscribes to a custom message that is specifically used for setting the joint configurations of the
rrbot. The structure of the plugin is very similar to that of a plugin you might find in the gazebo_ros_pkgs package, but all code has been merged into a single file to make it a bit easier to follow. In what follows, we will give a high-level overview of the plugin. You are welcome to study the code and ask if you have any questions, but the exact functionality of this code is not the primary purpose of this problem.The plugin has two threads:
- The
RRBotPosControl::OnUpdatefunction is set to be a callback to Gazebo's simulation update loop; this is done with boost::bind. So the first thread idles until Gazebo takes a simulation step, and then theRRBotPosControl::OnUpdatefunction is called. This function simply sets the joint velocities and torques for bothrrbotjoints to be zero, and sets the joint angles to be the values specified by the private member variablerefAngles. - For the second thread we call the
RRBotPosControl::QueueThreadfunction repeatedly in a loop with 0.01 second delays between calls. Each time we call this function, the function checks to see if there is a callback in our private member variablesubQueuewhich is of typeros::CallbackQueue. If there is a callback available, we handle it. This is really just a custom version ofros::spin(). We create a ROS subscriber that uses thesubQueuevariable for it'sros::CallbackQueue, and we set it to callRRBotPosControl::jointConfigCB()every time there is a new message on this topic. So every time a new message is published on therrbot_joint_position_control/rrbot_ref_joint_configtopic, the value of the latest message and thejointConfigCBare put at the top of the callback queue. The next time theRRBotPosControl::QueueThreadfunction checks to see if there is something in the callback queue, it will see there is something there, and it will calljointConfigCBwith the latest copy of the message as the argument. Then all thejointConfigCBfunction does is set the values of therefAnglesvariable; which is the variable used by the other thread to specify the joint angles of therrbot.
The first step is to make sure you compile this plugin with
catkin_make. Next you need a version of therrbotmodel that will use this custom plugin. Copy the correct files from therrbot_descriptionpackage into theurdf/directory of your package. Then edit these files to set the Gazebo simulation to use the custom plugin, and finally write a new launch file that starts Gazebo with the edited version of therrbotloaded. Your README should include the following:- A description of the custom message that the plugin subscribes to.
- A link to the launch file that starts Gazebo with the custom plugin.
- A description of what you had to modify in the
rrbot_descriptionfiles to get it to load your custom plugin. This should include the name of the plugin, and how you found this name (hint: look in theCMakeLists.txt).
- The
- Write a ROS node in Python that publishes the custom message on the correct
topic to get the
rrbotto follow a cyclic trajectory (hint: your node that provided/joint_statesinformation from homework 2 should need very little editing). When you add this node to your launch file from the previous section you should be able to, from a single launch file, start Gazebo with your modifiedrrbotin your custom world, and have a ROS node that is sending commands to move the simulation in a cyclic trajectory. Your README should include a link to the updated final launch file, instructions for launching, and a link to the node that was written to control the rrbot simulation.
