Matlab & ROS

ROS does not officially support Matlab, however thanks to Nathan Michael, communication with ROS is possible from within Matlab through the ipc-bridge.

IPC is a software package for inter-process communication written by Professor Reid Simmons at CMU. It is used here to bridge communication between ROS and Matlab because ROS can't communicate directly with Matlab because of incompatible dependencies.

Jump To:



People:
Software was written by Nathan Michael
Software was packaged up and documented here by Ben Cohen

Repository:
The code can be downloaded here. It was developed on MacOS. Some changes were made to how it's organized and how it's built in the zip file of the code in the tutorial below so that it can be easily installed and used on Ubuntu.
https://github.com/nmichael/ipc-bridge


How to install the ipc-bridge stacks


Prerequisites:

  • You have ROS Diamondback installed.
  • You are have either one of the following computer configurations:
    • You are running 64-bit Ubuntu & 64-bit Matlab
    • You are running 32-bit Ubuntu & 32-bit Matlab
  • Your desired mex compiler has been chosen. If it hasn't then run mex -setup at a terminal. Note: I've only compiled and tested ipc_bridge_matlab with gcc.
  1. Download the ipc-bridge for either 64-bit or 32-bit.
    Note: There is no real difference between the zip files other than an executable that I decided to compile for you to make these directions as easy as possible
  2. Unzip it.
    tar -xvf ipc-bridge-64bit-3.29.2011.zip
    (or unzip ipc-bridge-64bit-3.29.2011.zip)
  3. Put the ipc_bridge_stack folder in your ROS_PACKAGE_PATH. Remember where you put it because we will need to know the location of the ipc-bridge folder to perform the next step.
  4. Add some libraries to your machine's LD_LIBRARY_PATH by putting the following line in your ~/.bashrc file after the line in which you set your ROS_PACKAGE_PATH.
    export LD_LIBRARY_PATH=`rospack find ipc`/lib:`rospack find roscpp`/lib:`rospack find roscpp_serialization`/lib:`rospack find xmlrpcpp`/lib:`rospack find rosconsole`/lib:`rospack find roslib`/lib:`rospack find rospack`/lib:`rospack find rostime`/lib:`rospack find cpp_common`/lib:${LD_LIBRARY_PATH}
  5. Source your .bashrc file to enable the changes you made. You can also just close and reopen your terminal for the same effect.
    source ~/.bashrc
  6. Compile ipc_bridge_ros. Look at the output and make sure everything compiled without any errors.
    rosmake ipc_bridge_ros
  7. Compile the messages folders in the correct order by running executing the following lines one at a time. If you download newer code from a git repository, change ipc_roslib to ipc_rosgraph_msgs.
    roscd ipc_roslib && make
    roscd ipc_std_msgs && make
    roscd ipc_geometry_msgs && make
    roscd ipc_nav_msgs && make
    roscd ipc_sensor_msgs && make

How to use the IPC-Bridge


Two things are needed for communication:

  • A Matlab publisher or subscriber. It communicates between Matlab <--> IPC.
  • A ROS node with the inverse subscriber or publisher. It communicates between IPC <--> ROS.

Matlab <--> IPC
For each type of ROS message supported, there is a unique mex file in ipc_bridge_matlab/bin. Calling the desired function from within matlab can do a couple of different things, depending on the arguments passed.

  • Connect a new Publisher/Subscriber
    inputs:
    * string: 'connect'
    * string: 'publisher' OR 'subscriber'
    * string: name of module (not important - can be garbage)
    * string: name of the IPC message to communicate with
    returns:
    * integer: process id of the publisher or subscriber (needed for pub/sub)
    ex.
    pid=geometry_msgs_Twist('connect','publisher','bla','twist')
  • Disconnect a Publisher/Subscriber
    inputs:
    * string: 'disconnect'
    * integer: process id
    ex.
    geometry_msgs_Twist('disconnect',pid)
  • Publish on a topic
    inputs:
    * string: 'send'
    * integer: process id
    * message: outgoing message (of correct type)
    ex.
    geometry_msgs_Twist('send',pid,my_twist_msg);
  • Read from a topic
    inputs:
    * string: 'read'
    * integer: process id
    * integer: timeout (seconds)
    returns:
    * message: received message
    ex.
    twist_msg = geometry_msgs_Twist('read',sid,1);
  • Instantiate an empty message
    inputs:
    * string: 'empty'
    returns:
    * message: an empty message object
    ex.
    empty_twist_msg=geometry_msgs_Twist('empty');



IPC <--> ROS
For each type of message supported, there is a binary executable in ipc_bridge_ros/bin that launches a ROS node. The node receives/sends a message through IPC. The node must be launched with the proper parameters to communicate properly with matlab.

To launch an ipc_bridge_ros node, you should create a launch file with the proper parameters set. Just like standard launch files, You can launch many ipc_bridge_ros nodes in the same launch file.

  • node:
    * pkg: name of package where binary is (will always be "ipc_bridge_ros")
    * name: name of node
    * type: name of executable corresponding to:
    {ROS package containing message}_{message type}_{subscriber/publisher}
    ex. geometry_msgs_Twist_subscriber
  • topic:
    * topic: the name of the ROS topic that IPC will publish/subscribe to
  • message:
    * message: the name of the IPC message that the matlab code will publish/subscribe to

ex.

<launch>
  <node pkg="ipc_bridge_ros"
    name="geometry_msgs_Twist_subscriberK"
    type="geometry_msgs_Twist_subscriber"
    output="screen">
    <remap from="~topic" to="/robot_twist_topic"/>
    <param name="message" value="twist"/>
  </node>
</launch>

Run the example matlab publisher


  1. Launch the launch file that starts central and brings up an IPC subscriber.
    roslaunch ipc_bridge_example matlab_publisher_example.launch
  2. Run matlab. Open ipc_bridge_example/example_publisher.m. Run it (Press F5). Now we are publishing a twist message on a topic called /example_topic.
  3. Now, let's check to see if we are publishing correctly. Open up a new terminal and run:
    rostopic echo /example_topic

You should see data spewing down the screen. In each message, the linear x,y,z velocities should be incrementing by 1.

Run the example matlab subscriber


  1. Launch the launch file that starts central and brings up an IPC publisher.
    roslaunch ipc_bridge_example matlab_subscriber_example.launch
  2. Publish on /my_test_publisher using the rostopic command:
    rostopic pub -r 10 /example_topic geometry_msgs/Twist '{x: 1.0, y: 2.0, z: 3.0}' '{x: 4.0, y: 5.0, z: 6.0}'
  3. Run matlab. Open ipc_bridge_example/example_subscriber.m. Run it (Press F5). Now we are receiving a twist message on a topic called /example_topic.

You should see data spewing down the matlab command window.

List of Supported Messages


geometry_msgs/Point32
geometry_msgs/Point
geometry_msgs/PointStamped
geometry_msgs/PoseArray
geometry_msgs/Pose
geometry_msgs/PoseStamped
geometry_msgs/PoseWithCovariance
geometry_msgs/PoseWithCovarianceStamped
geometry_msgs/Quaternion
geometry_msgs/Transform
geometry_msgs/TransformStamped
geometry_msgs/Twist
geometry_msgs/TwistStamped
geometry_msgs/TwistWithCovariance
geometry_msgs/Vector3
geometry_msgs/Wrench
nav_msgs/GridCells
nav_msgs/MapMetaData
nav_msgs/OccupancyGrid
nav_msgs/Odometry
nav_msgs/Path
roslib/Header
sensor_msgs/ChannelFloat32
sensor_msgs/Image
sensor_msgs/Imu
sensor_msgs/LaserScan
sensor_msgs/PointCloud
tf/tfMessage

How to Support New Messages


THESE ARE UNTESTED DIRECTIONS AND THIS TUTORIAL IS A WORK IN PROGRESS
How to create a custom IPC module:

  1. Setup ipc folders.
    roscd package_name
    mkdir ipc && cd ipc
    mkdir include mex ros xdr
  2. Setup ipc/ros/mex handlers.
    1. Define Foo.xdr in xdr from Foo.msg.
    2. Write the ros and mex handlers in ros/mex folders.
  3. Create a Makefile containing:
    PKG= package_name
    MEX_MSGS= Foo
    ROS_MSGS= Foo
    
    MEX_FILES := $(foreach msg, $(MEX_MSGS), $(PKG)_$(msg))
    ROS_FILES := $(foreach msg, $(ROS_MSGS), $(PKG)_$(msg)_publisher)
    ROS_FILES += $(foreach msg, $(ROS_MSGS), $(PKG)_$(msg)_subscriber)
    
    include $(shell rospack find ipc_roslib)/ipc_roslib.mk
    include $(shell rospack find ipc_geometry_msgs)/ipc_geometry_msgs.mk
    include $(shell rospack find ipc_bridge_local)/ipc_bridge_local.mk
    
    This line:
    include $(shell rospack find ipc_geometry_msgs)/ipc_geometry_msgs.mk
    points to dependencies, so if you need nav_msgs, add this line:
    include $(shell rospack find ipc_nav_msgs)/ipc_nav_msgs.mk
  4. Run make.
    The attached contains an example custom ipc message setup for one of my packages (msg/ipc directories).
  5. Add the following lines to your matlab code:
[a, p] = system('rospack find ipc_nav_msgs');
addpath(strcat(p, '/bin'));
[a, p] = system('rospack find so3_control');
addpath(strcat(p, '/ipc/bin'));
where in this case I need the nav_msgs and so3_control I/O.

Limitations of the IPC-Bridge


The IPC-Bridge works well for what it does but there is a bunch of functionality supported by ROS that can't be used primarily because of limitations in Matlab itself:

  • Services are not supported
  • Using the Param server is not supported
  • Need to create a new script to generate each type of ROS message