\(\def\dt{\Delta t}\)
\(\newcommand{\transpose}[0]{^\mathrm{T}}\)
\(\newcommand{\half}[0]{\tfrac{1}{2}}\)
\(\newcommand{\Half}[0]{\frac{1}{2}}\)
\(\newcommand{\norm}[1]{\left\lVert#1\right\rVert}\)
\(\newcommand\given[1][]{\:#1\vert\:}\)
UP | HOME

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.

  1. 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 rrbot model into this world. Save this world file and add it to your repository; be sure your README links to this world file.
  2. Write a launch file that starts Gazebo with your custom world from the previous problem, and inserts the default rrbot model from gazebo_ros_demos. You should use the spawn_model node from gazebo_ros to insert the rrbot model into the world. README should link to the launch file and include a screenshot of the rrbot in the custom world.
  3. Once Gazebo is running with your simulated rrbot you will use the image_view or rqt_image_view node 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?
  4. Write a launch file that starts rviz with a nice configuration to view the camera, the laser scanner, and the rrbot. For now, your launch file should also include the joint_state_publisher to 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 in rviz, you may be running into a driver issue. By default, the rrbot uses 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:

    1. Modify the appropriate xacro files to use a non-GPU laser scanner. The plugin is called gazebo_ros_laser.
    2. 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 is export 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_demos package; 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.

  1. In the last section, we needed the joint_state_publisher to create sensor_msgs/JointState information to tell rviz the pose of the rrbot. This is an artifact of the way the gazebo_ros_control package's plugins interact with Gazebo/ROS. By default, the gazebo_ros_control plugin does not provide joint state information to ROS. Rather, you must load a properly-configured joint_state_controller plugin with the spawner node from the controller_manager package. 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 that ros_control provides.

    Complete the following tasks:

    1. Write a YAML file that configures the joint_state_controller/JointStateController to convert model poses to joint_states information.
    2. Write a launch file that starts rviz, a spawner node, the robot_state_publisher, and loads the correct robot_description parameter. 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 the joint_state_publisher providing joint state information and Gazebo providing the joint state information. You may need to remap or 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).

  2. Write a ROS node in Python that uses the /gazebo/apply_joint_effort service to apply torques to the rrbot joints 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 the rrbot to 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).
  3. 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::OnUpdate function 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 the RRBotPosControl::OnUpdate function is called. This function simply sets the joint velocities and torques for both rrbot joints to be zero, and sets the joint angles to be the values specified by the private member variable refAngles.
    • For the second thread we call the RRBotPosControl::QueueThread function 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 variable subQueue which is of type ros::CallbackQueue. If there is a callback available, we handle it. This is really just a custom version of ros::spin(). We create a ROS subscriber that uses the subQueue variable for it's ros::CallbackQueue, and we set it to call RRBotPosControl::jointConfigCB() every time there is a new message on this topic. So every time a new message is published on the rrbot_joint_position_control/rrbot_ref_joint_config topic, the value of the latest message and the jointConfigCB are put at the top of the callback queue. The next time the RRBotPosControl::QueueThread function checks to see if there is something in the callback queue, it will see there is something there, and it will call jointConfigCB with the latest copy of the message as the argument. Then all the jointConfigCB function does is set the values of the refAngles variable; which is the variable used by the other thread to specify the joint angles of the rrbot.

    The first step is to make sure you compile this plugin with catkin_make. Next you need a version of the rrbot model that will use this custom plugin. Copy the correct files from the rrbot_description package into the urdf/ 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 the rrbot loaded. Your README should include the following:

    1. A description of the custom message that the plugin subscribes to.
    2. A link to the launch file that starts Gazebo with the custom plugin.
    3. A description of what you had to modify in the rrbot_description files 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 the CMakeLists.txt).
  4. Write a ROS node in Python that publishes the custom message on the correct topic to get the rrbot to follow a cyclic trajectory (hint: your node that provided /joint_states information 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 modified rrbot in 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.
Creative Commons License
ME 495: Embedded Systems in Robotics by Jarvis Schultz is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.