Received just one message when I used receive(sub, timeout) for rossubscriber

5 views (last 30 days)
Xin Xing
Xin Xing on 13 Oct 2021
Commented: Xin Xing on 14 Oct 2021
Hello all,
i used rossubscriber without callback function for receiving feedback data from the action server in ROS (Ubuntu).
sub = rossubscriber('action_server/feedback', message_type);
pause(1);
msg = receive(sub,10);
showdetails(msg);
Generally, the command will display the content of msg for 10 seconds. But I only received one message when I run the program.
But when I used echo to display topic messages, the content of feedback would always be displayed.
rostopic echo action_server/feedback
I used MATLAB R2021b and Ubuntu 16.04.

Accepted Answer

Cam Salzberger
Cam Salzberger on 13 Oct 2021
The receive function will only ever receive a single message, and returns immediately upon receiving that message. It is not a replacement for echo. The "10" in your example is the timeout - if a message is not received within 10 seconds it will error.
Generally, I recommend only using receive once, when you need to ensure that the subscriber has gotten a message before you enter into your main control loop if you are going to be working on the LatestMessage property of the subscriber. This design pattern would look like this:
sub = rossubscriber(topic, type);
receive(sub, 10); % Ensure that messages are flowing
while (condition)
msg = sub.LatestMessage;
% ... take action based on message ...
end
That design pattern is useful if you need to execute on a regular cadence with the most up-to-date data (like a camera image), but don't necessarily need to process all messages sent to the subscriber. This pattern is frequently used in conjunction with rosrate to set the cadence.
The other main design pattern is to process every message in the subscriber callback. This is useful if every message needs to be processed or else data will be lost. The design pattern typically looks like this:
cb = @(src, msg) myCallback(src, msg, additional, parameters);
sub = rossubscriber(topic, type, 'NewMessageFcn', cb);
function myCallback(src, msg, additional, parameters)
% Process the newly-received message
% Take action using additional parameters as necessary
end
You might even see a combination of these patterns, where one slow subscriber sets the cadence, and then the most recent information from other subscribers is used at that time. That might look something like this (for a more application-focused example):
% Set up subscribers for most sensors and location publisher
gpsSub = rossubscriber("/gps", "sensor_msgs/NavSatFix");
imuSub = rossubscriber("/imu", "sensor_msgs/Imu");
posePub = rospublisher("/estimated_position", "geometry_msgs/PoseStamped");
% Ensure data is flowing
receive(gpsSub);
receive(imuSub);
% Set up camera subscriber to control localization of the robot
cameraCallback = @(src, msg) cameraUpdateEKF(msg, gpsSub, imuSub, posePub);
cameraSub = rossubscriber("/camera", "sensor_msgs/Image", "NewMessageFcn", cameraCallback);
function cameraUpdateEKF(imageMsg, gpsSub, imuSub, posePub)
gpsMsg = gpsSub.LatestMessage;
imuMsg = imuSub.LatestMessage;
poseMsg = updateEKF(imageMsg, gpsMsg, imuMsg);
send(posePub, poseMsg)
end
I would suggest thinking about what your application requires and looking into one of these design patterns for use.
-Cam
  1 Comment
Xin Xing
Xin Xing on 14 Oct 2021
Hi Cam, thank you very much for introducing the design patterns in detail. That‘s so helpful for me.

Sign in to comment.

More Answers (0)

Products


Release

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!