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:
- How to install the IPC-bridge
- How to use the IPC-Bridge
- Run the example publisher
- Run the example subscriber
- List of Supported Messages
- Limitations of the IPC-Bridge
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 runmex -setup
at a terminal. Note: I've only compiled and testedipc_bridge_matlab
with gcc.
- 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
- Unzip it.
tar -xvf ipc-bridge-64bit-3.29.2011.zip
(or unzip ipc-bridge-64bit-3.29.2011.zip)
- 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.
- 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}
- 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
- Compile ipc_bridge_ros. Look at the output and make sure everything compiled without any errors.
rosmake ipc_bridge_ros
- 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 withreturns:* 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
- Launch the launch file that starts
central
and brings up an IPC subscriber.
roslaunch ipc_bridge_example matlab_publisher_example.launch
- Run matlab. Open
ipc_bridge_example/example_publisher.m
. Run it (PressF5
). Now we are publishing a twist message on a topic called/example_topic
.
- 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
- Launch the launch file that starts
central
and brings up an IPC publisher.
roslaunch ipc_bridge_example matlab_subscriber_example.launch
- 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}'
- Run matlab. Open
ipc_bridge_example/example_subscriber.m
. Run it (PressF5
). 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:
- Setup ipc folders.
roscd package_name
mkdir ipc && cd ipc
mkdir include mex ros xdr
- Setup ipc/ros/mex handlers.
- Define Foo.xdr in xdr from Foo.msg.
- Write the ros and mex handlers in ros/mex folders.
- 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
- Run
make
.The attached contains an example custom ipc message setup for one of my packages (msg/ipc directories). - 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