Main Content

Generate a ROS Control Plugin from Simulink®

This example shows how to generate and build a ros_control plugin from a Simulink model. In this example, you first configure a model to generate C++ code for a ros_control package. You then deploy the plugin on a virtual machine running Gazebo® to control a Pioneer 3DX 2-wheeled differential drive robot.

Prerequisites

Overview

The ros_control framework provides a generic set of tools to create controllers for various types of robots.

This example focuses on auto-generating C++ code for a controller designed in Simulink® and packaging it and deploying that controller as a ros_control plugin as shown in the figure below. In this example, you generate code for a controller designed in Simulink, and deploy it as a ros_control plugin. The data flow of the controller is shown in the following diagram.

The Simulink model drivecontroller implements a simple closed-loop proportional controller. It receives the goal location from /command topic of type, geometry_msgs/Pose2D, and the current position of the robot from /p3dx/ground_truth/state topic of type, nav_msgs/Odometry. The controller sets the left and right wheel speed commands using VelocityJointInterface. This topology is shown in the diagram below.

Open Controller Simulink Model

After connecting to the ROS network, open the example controller model.

open_system('drivecontroller.slx');

The model implements a proportional controller. At each step, the algorithm orients the robot toward the desired location and drives it forward. Once the desired location is reached, the algorithm stops the robot.

Configure ROS Control Interfaces

The example controller model is configured for Robot Operating System (ROS). Use the ros_control Settings button to map the output ports of the model to correct resource type.

In SIMULATION tab, under PREPARE section, click on ROS Control Settings button from ROS Toolbox category.

In the Configure ROS Control dialog:

  1. Set the name of the Controller C++ class to ControllerHost

  2. In the Outports tab, set the Resource name of the output port 1, to base_right_wheel_joint and set the name of the output port 2, to base_right_wheel_joint.

  3. Set the Resource type for both output ports to VelocityJointInterface.

  4. Select Generate ros_control controller package checkbox.

  5. Click OK to save the settings and close the dialog.

The dialog settings are shown below for reference.

Configure Connection to the ROS Device

  1. Under the ROS tab, from the Deploy to drop-down, click Manage Remote Device.

  2. In the Connect to a ROS device dialog that opens, enter all the information that Simulink needs to deploy the ROS node.

  3. Specify IP address or host name of your ROS device, login credentials, and the Catkin workspace.

  4. Change Catkin workspace to ~/Documents/mw_catkin_ws. This workspace has a Pioneer 3DX Gazebo® world and related files to run a simulated differential drive robot.

Deploy the ROS Control Plugin

Generate C++ code for the proportional controller and create a ros_control plugin package, automatically transfer, and build it on the ROS device.

Start ROS Core and ROS Master

  • In MATLAB®, change the current folder to a temporary location where you have write permission.

  • Code generation process first prepares the model for simulation to ensure that all blocks are properly initialized. This preparation requires a valid connection to a ROS master.

  • Start the ROS core on the virtual machine using the rosdevice object

d = rosdevice;
runCore(d);
Another roscore / ROS master is already running on the ROS device. Use the 'stopCore' function to stop it.
  • Use rosinit to connect MATLAB to the ROS master running on the ROS device:

rosinit(d.DeviceAddress,11311)
Initializing global node /matlab_global_node_59727 with NodeURI http://192.168.93.1:57230/

Deploy the ROS Control Plugin

  • Configure Simulink to use the same ROS connection settings as MATLAB. Under the Simulation tab, in Prepare section, select ROS Network. Set the ROS Master (ROS 1) and Node Host network addresses to Default.

  • Under the ROS tab, click Deploy > Build & Load. If you get any errors about bus type mismatch, close the model, clear all variables from the base MATLAB workspace, and re-open the model.

  • Click on the View Diagnostics link at the bottom of the model toolbar to see the output of the build process.

  • Once the code generation completes, the ROS package is transferred to the Catkin workspace on the ROS device and built there.

Integrate Simulink ROS Control Plugin with Gazebo

Register Controller and Build Workspace

Modify the Pioneer 3DX controller configuration YAML file to register the generated controller, and build the workspace.

  • Replace the controller configuration YAML file using the rosdevice object. To use the controller plugin generated from the model, copy the pre-configured pioneer3dx.yaml file to the catkin workspace.

system(d,['cd ',d.CatkinWorkspace,' && cp src/pioneer_p3dx_model/p3dx_control/config/pioneer3dx.yaml src/pioneer_p3dx_model/p3dx_control/config/backup.pioneer3dx.yaml'])
ans =

  0×0 empty char array
putFile(d,fullfile(pwd,'pioneer3dx.yaml'),[d.CatkinWorkspace,'/src/pioneer_p3dx_model/p3dx_control/config/pioneer3dx.yaml'])
  • Build the workspace

system(d,['cd ',d.CatkinWorkspace,' && source ./devel/setup.bash && catkin_make'])
ans = 
    '[  0%] Built target _controller_manager_msgs_generate_messages_check_deps_HardwareInterfaceResources
     [  0%] Built target _controller_manager_msgs_generate_messages_check_deps_ListControllerTypes
     [  0%] Built target _controller_manager_msgs_generate_messages_check_deps_LoadController
     [  0%] Built target _controller_manager_msgs_generate_messages_check_deps_UnloadController
     [  0%] Built target _controller_manager_msgs_generate_messages_check_deps_ControllerStatistics
     [  0%] Built target _controller_manager_msgs_generate_messages_check_deps_SwitchController
     [  0%] Built target _controller_manager_msgs_generate_messages_check_deps_ControllerState
     [  0%] Built target std_msgs_generate_messages_nodejs
     [  0%] Built target _controller_manager_msgs_generate_messages_check_deps_ControllersStatistics
     [  0%] Built target _controller_manager_msgs_generate_messages_check_deps_ListControllers
     [  0%] Built target _controller_manager_msgs_generate_messages_check_deps_ReloadControllerLibraries
     [  0%] Built target std_msgs_generate_messages_py
     [  0%] Built target std_msgs_generate_messages_cpp
     [  0%] Built target std_msgs_generate_messages_eus
     [  0%] Built target std_msgs_generate_messages_lisp
     [  0%] Built target roscpp_generate_messages_cpp
     [  0%] Built target rosgraph_msgs_generate_messages_py
     [  0%] Built target rosgraph_msgs_generate_messages_lisp
     [  0%] Built target rosgraph_msgs_generate_messages_eus
     [  0%] Built target rosgraph_msgs_generate_messages_cpp
     [  0%] Built target roscpp_generate_messages_nodejs
     [  0%] Built target roscpp_generate_messages_py
     [  0%] Built target rosgraph_msgs_generate_messages_nodejs
     [  0%] Built target roscpp_generate_messages_eus
     [  0%] Built target roscpp_generate_messages_lisp
     [  0%] Built target iiwa_matlab_plugin
     [  1%] Built target gtest
     [  2%] Built target transmission_interface_parser
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_TurtlebotMoveFeedback
     [  2%] Built target geometry_msgs_generate_messages_py
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_TurtlebotMoveActionFeedback
     [  2%] Built target actionlib_msgs_generate_messages_py
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_FindFiducialAction
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_TurtlebotMoveActionGoal
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_TurtlebotMoveAction
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_FindFiducialActionGoal
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_FindFiducialActionResult
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_FindFiducialActionFeedback
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_FindFiducialGoal
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_FindFiducialResult
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_FindFiducialFeedback
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_TurtlebotMoveActionResult
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_TurtlebotMoveGoal
     [  2%] Built target _turtlebot_actions_generate_messages_check_deps_TurtlebotMoveResult
     [  2%] Built target geometry_msgs_generate_messages_nodejs
     [  2%] Built target actionlib_msgs_generate_messages_nodejs
     [  2%] Built target geometry_msgs_generate_messages_lisp
     [  2%] Built target actionlib_msgs_generate_messages_lisp
     [  2%] Built target actionlib_msgs_generate_messages_cpp
     [  2%] Built target geometry_msgs_generate_messages_cpp
     [  2%] Built target geometry_msgs_generate_messages_eus
     [  2%] Built target actionlib_msgs_generate_messages_eus
     [  8%] Built target controller_manager_msgs_generate_messages_nodejs
     [ 16%] Built target controller_manager_msgs_generate_messages_py
     [ 21%] Built target controller_manager_msgs_generate_messages_cpp
     [ 28%] Built target controller_manager_msgs_generate_messages_eus
     [ 33%] Built target controller_manager_msgs_generate_messages_lisp
     [ 35%] Built target combined_robot_hw
     [ 36%] Built target transmission_interface_loader
     [ 45%] Built target turtlebot_actions_generate_messages_py
     [ 54%] Built target turtlebot_actions_generate_messages_nodejs
     [ 62%] Built target turtlebot_actions_generate_messages_lisp
     [ 70%] Built target turtlebot_actions_generate_messages_cpp
     [ 78%] Built target turtlebot_actions_generate_messages_eus
     [ 78%] Built target controller_manager_msgs_generate_messages
     [ 79%] Built target controller_manager
     [ 86%] Built target transmission_interface_loader_plugins
     [ 86%] Built target turtlebot_actions_generate_messages
     [ 86%] Built target turtlebot_actions_gencpp
     [ 90%] Built target controller_manager_tests
     [ 91%] Built target cm_test
     [ 95%] Built target combined_robot_hw_tests
     [ 97%] Built target find_fiducial_pose
     [ 98%] Built target turtlebot_move_action_server
     [100%] Built target dummy_app
     Base path: /home/user/Documents/mw_catkin_ws
     Source space: /home/user/Documents/mw_catkin_ws/src
     Build space: /home/user/Documents/mw_catkin_ws/build
     Devel space: /home/user/Documents/mw_catkin_ws/devel
     Install space: /home/user/Documents/mw_catkin_ws/install
     ####
     #### Running command: "make cmake_check_build_system" in "/home/user/Documents/mw_catkin_ws/build"
     ####
     ####
     #### Running command: "make -j2 -l2" in "/home/user/Documents/mw_catkin_ws/build"
     ####
     '

Start Pioneer 3DX Gazebo World

  • In the Ubuntu VM, click on Gazebo Pioneer 3DX desktop icon to launch the Gazebo world. This also starts the rqt_controller_manager UI that allows you to start and load the controller.

  • In the rqt_controller_manager UI, right-click on the sl_drivecontroller and select Load and Start.

To change the display name of the controller, sl_drivecontroller, in rqt_controller_manager UI,

Send Commands to Move the Robot

To move the Pioneer 3DX robot, open the set_command model and click RUN from SIMULATE section in the SIMULATION tab. Observe the robot move in the Gazebo world.

Shutdown the global MATLAB node.

rosshutdown
Shutting down global node /matlab_global_node_59727 with NodeURI http://192.168.93.1:57230/

References

S. Chitta, E. Marder-Eppstein, W. Meeussen, V. Pradeep, A. Rodríguez Tsouroukdissian, J. Bohren, D. Coleman, B. Magyar, G. Raiola, M. Lüdtke and E. Fernandez Perdomo

  • "ros_control: A generic and simple control framework for ROS"

  • The Journal of Open Source Software, 2017. PDF