ros2subscriber bug when using codegen

4 views (last 30 days)
James Croughan
James Croughan on 8 Jan 2024
Commented: Josh Chen on 11 Jan 2024
I am getting an error in ros2subscriber itself when trying to run codegen, and am unsure how to fix it. The error is created when I make several custom handle objects and pass those to a ros2subscriber callback. If I do not pass the handle objects to the callback, then the error does not occur. The code runs as expected in standard matlab, and only throws an error when using codegen. Note that these are all custom ros2message types. A simplified version of my code that works in codegen looks like the following:
function testNode()
% Mapper
mapper_node=ros2node("/mapper_node");
mapper_linker=rosShim2(mapper_node);
% Services as nodes
mapper_srvs=cell(1,4);
mapper_srvs{1} = ros2publisher(mapper_node,'/get_boxes_req','ros_msgs/GetBoxesReq');
mapper_srvs{2} = ros2publisher(mapper_node,'/get_depth_req','ros_msgs/GetDepthReq');
mapper_srvs{3} = ros2subscriber(mapper_node,'/get_boxes_resp','ros_msgs/GetBoxesResp');
mapper_srvs{4} = ros2subscriber(mapper_node,'/get_depth_resp','ros_msgs/GetDepthResp');
% Set up linker
mapper_linker_0.setSrvsMapper(mapper_srvs);
% Publications
mapper_pubs=cell(1,9);
mapper_pubs{1} = ros2publisher(mapper_node,'/mapper_local_est','ros_msgs/ExtendedVehicleState');
mapper_pubs{2} = ros2publisher(mapper_node,'/poi_summary','ros_msgs/POISummary');
mapper_pubs{3} = ros2publisher(mapper_node,'/coi_to_track','ros_msgs/COIToTrack');
mapper_pubs{4} = ros2publisher(mapper_node,'/coi_monitoring','ros_msgs/COIMonitoring');
mapper_pubs{5} = ros2publisher(mapper_node,'/depthcam0','ros_msgs/Depth');
mapper_pubs{6} = ros2publisher(mapper_node,'/depthcam1','ros_msgs/Depth');
mapper_pubs{7} = ros2publisher(mapper_node,'/depthcam2','ros_msgs/Depth');
mapper_pubs{8} = ros2publisher(mapper_node,'/gs_mapper_comms_to_gs','ros_msgs/GSComms');
mapper_pubs{9} = ros2publisher(mapper_node,'/target_observation','ros_msgs/TargetObservation');
% Subscriptions
mapper_subs=cell(1,11);
mapper_subs{1} = ros2subscriber(mapper_node,'/gpse_local_est','ros_msgs/ExtendedVehicleState');
mapper_subs{2} = ros2subscriber(mapper_node,'/cam0','sensor_msgs/Image');
mapper_subs{3} = ros2subscriber(mapper_node,'/cam1','sensor_msgs/Image');
mapper_subs{4} = ros2subscriber(mapper_node,'/cam2','sensor_msgs/Image');
mapper_subs{5} = ros2subscriber(mapper_node,'/cam3','sensor_msgs/Image');
mapper_subs{6} = ros2subscriber(mapper_node,'/cam4','sensor_msgs/Image');
mapper_subs{7} = ros2subscriber(mapper_node,'/cam5','sensor_msgs/Image');
mapper_subs{8} = ros2subscriber(mapper_node,'/observation_trigger','ros_msgs/ObservationTrigger');
mapper_subs{9} = ros2subscriber(mapper_node,'/offboard_comms','ros_msgs/OContMonitoring');
mapper_subs{10} = ros2subscriber(mapper_node,'/gs_comms_from_gs','ros_msgs/GSComms');
mapper_subs{11} = ros2subscriber(mapper_node,'/mapper_trigger','std_msgs/Header',@(src,msg) mapperCallback(src,msg,mapper_linker,mapper_pubs,mapper_srvs));
end
function mapperCallback(src,msg,linker,mapper_pubs,mapper_srvs)
linker.setPubsMapper(mapper_pubs,mapper_srvs);
obs_Pub_msg = ros2message('ros_msgs/TargetObservation');
coi_to_track_msg=ros2message('ros_msgs/COIToTrack');
mapper_state_msg=ros2message('ros_msgs/ExtendedVehicleState');
coi_msg=ros2message('ros_msgs/COIMonitoring');
poi_summary_msg=ros2message('ros_msgs/POISummary');
depth_msg=ros2message('ros_msgs/Depth');
gs_Pub_msg = ros2message('ros_msgs/GSComms');
% Change message contents here
send(linker.mapper_pub_target_observation,obs_Pub_msg);
% Send the rest of the messages here
end
In this code, I am able to pass ros2publishers as an input to a callback function, and then build the needed messages using either those publishers or the standalone message types, as you would expect. This runs in codegen totally fine.
However, when I add some additional custom handle objects to the callback and make the callback more complicated, I start getting very odd errors in the codegen error report. That code looks like:
function testNode()
% Mapper
mapper_node=ros2node("/mapper_node");
mapper_linker=rosShim2(mapper_node);
% Other handles
handle1=mycustomHandleclass1(args);
handle2=mycustomHandleclass2(args);
handleN=mycustomHandleclassN(args);
% Services as nodes
mapper_srvs=cell(1,4);
mapper_srvs{1} = ros2publisher(mapper_node,'/get_boxes_req','ros_msgs/GetBoxesReq');
mapper_srvs{2} = ros2publisher(mapper_node,'/get_depth_req','ros_msgs/GetDepthReq');
mapper_srvs{3} = ros2subscriber(mapper_node,'/get_boxes_resp','ros_msgs/GetBoxesResp');
mapper_srvs{4} = ros2subscriber(mapper_node,'/get_depth_resp','ros_msgs/GetDepthResp');
% Set up linker
mapper_linker_0.setSrvsMapper(mapper_srvs);
% Publications
mapper_pubs=cell(1,9);
mapper_pubs{1} = ros2publisher(mapper_node,'/mapper_local_est','ros_msgs/ExtendedVehicleState');
mapper_pubs{2} = ros2publisher(mapper_node,'/poi_summary','ros_msgs/POISummary');
mapper_pubs{3} = ros2publisher(mapper_node,'/coi_to_track','ros_msgs/COIToTrack');
mapper_pubs{4} = ros2publisher(mapper_node,'/coi_monitoring','ros_msgs/COIMonitoring');
mapper_pubs{5} = ros2publisher(mapper_node,'/depthcam0','ros_msgs/Depth');
mapper_pubs{6} = ros2publisher(mapper_node,'/depthcam1','ros_msgs/Depth');
mapper_pubs{7} = ros2publisher(mapper_node,'/depthcam2','ros_msgs/Depth');
mapper_pubs{8} = ros2publisher(mapper_node,'/gs_mapper_comms_to_gs','ros_msgs/GSComms');
mapper_pubs{9} = ros2publisher(mapper_node,'/target_observation','ros_msgs/TargetObservation');
% Subscriptions
mapper_subs=cell(1,11);
mapper_subs{1} = ros2subscriber(mapper_node,'/gpse_local_est','ros_msgs/ExtendedVehicleState');
mapper_subs{2} = ros2subscriber(mapper_node,'/cam0','sensor_msgs/Image');
mapper_subs{3} = ros2subscriber(mapper_node,'/cam1','sensor_msgs/Image');
mapper_subs{4} = ros2subscriber(mapper_node,'/cam2','sensor_msgs/Image');
mapper_subs{5} = ros2subscriber(mapper_node,'/cam3','sensor_msgs/Image');
mapper_subs{6} = ros2subscriber(mapper_node,'/cam4','sensor_msgs/Image');
mapper_subs{7} = ros2subscriber(mapper_node,'/cam5','sensor_msgs/Image');
mapper_subs{8} = ros2subscriber(mapper_node,'/observation_trigger','ros_msgs/ObservationTrigger');
mapper_subs{9} = ros2subscriber(mapper_node,'/offboard_comms','ros_msgs/OContMonitoring');
mapper_subs{10} = ros2subscriber(mapper_node,'/gs_comms_from_gs','ros_msgs/GSComms');
mapper_subs{11} = ros2subscriber(mapper_node,'/mapper_trigger','std_msgs/Header',@(src,msg) mapperCallback(src,msg,mapper_linker,mapper_pubs,mapper_srvs,handle1,handle2,handleN)); % ERROR 3 and ERROR 6
end
function mapperCallback(src,msg,linker,mapper_pubs,mapper_srvs,handle1,handle2,handleN)
linker.setPubsMapper(mapper_pubs,mapper_srvs);
obs_Pub_msg = ros2message('ros_msgs/TargetObservation');
coi_to_track_msg=ros2message('ros_msgs/COIToTrack'); % ERROR 1
mapper_state_msg=ros2message('ros_msgs/ExtendedVehicleState');
coi_msg=ros2message('ros_msgs/COIMonitoring'); % ERROR 2
poi_summary_msg=ros2message('ros_msgs/POISummary');
depth_msg=ros2message('ros_msgs/Depth');
gs_Pub_msg = ros2message('ros_msgs/GSComms');
% Change message contents here using functions from myhandleClass1-N
% placed within a logical structure with if and for loops
send(linker.mapper_pub_target_observation,obs_Pub_msg);
% Send the rest of the messages as they are filled in within the
% logical structure of this function
end
After adding these handles and calling their functions within mapperCallback, I initially got a bunch of codegen errors related to those functions, but I have worked through those. The remaining errors I get are as follows. I've labelled the lines they occur at in the code block above.
Error 1: Function: testNode/mapperCallback at the line indicated
This assignment writes a 'ros_msgs_COIToTrackStruct_T' value into a 'struct_T' type. Code generation does not support changing types through assignment. Check preceding assignments or input type specifications for type mismatches.
Error 2: Function: testNode/mapperCallback at the line indicated
This assignment writes a 'ros_msgs_COIMonitoringStruct_T' value into a 'struct_T' type. Code generation does not support changing types through assignment. Check preceding assignments or input type specifications for type mismatches.
Error 3: testNode/@(src,msg) mapperCallback(src,msg,mapper_linker,mapper_pubs,mapper_srvs,handle1,handle2,handleN) at the line indicated
Function call failed.
Error 4: Function: ros.internal.codegen.ros2subscriber>38/callback Line:288
Function call failed.
Error 5: ros.internal.codegen.ros2subscriber>37/ros2subscriber Line:277
Function call failed.
Error 6: testNode at the line indicated
Function call failed.
I am very confused as to why/how coi_to_track_msg was already defined as a 'struct_T' type, when the assignment to the ros2message type is where the variable gets declared and it is never reinitialized anywhere else within mapperCallback. It also had no problems using this same format when I didn't include the other handle objects as inputs or use their functions.
Errors 4 and 5 are occurring within the ros.internal.codegen.ros2subscriber class. Those bits of code are:
function callback(obj)
coder.inline('never') % This functions is called from MATLABROS2Subscriber and cannot be inlined
obj.MessageCount = obj.MessageCount + 1;
if ~isempty(obj.NewMessageFcn) && obj.IsInitialized
% Call user defined callback function
if isempty(obj.Args)
obj.NewMessageFcn(obj,obj.MsgStruct); % ERROR 4 occurs here
else
obj.NewMessageFcn(obj,obj.MsgStruct,obj.Args{:});
end
end
end
Error 5 is within the constructor when it calls callback.
I assume the actual problem has something to do with my handle objects or the structure within mapperCallback, since those are the difference between the code that runs and the one that doesn't. However, that is the entire list of errors that show up on the report when I run codegen, so I am at a loss as to what the problem is or how to fix it. Any suggestions would be appreciated. The full code is much longer than shown here and requires a supporting codebase and message set, but those can potentially be provided privately if necessary.
  2 Comments
Angelo Yeo
Angelo Yeo on 11 Jan 2024
Edited: Angelo Yeo on 11 Jan 2024
This type of question can be better helped with MathWorks Technical Support because
1) You believe that this should be a bug of ros2subscriber.
2) One needs additional codebase and messages to reproduce the issue but you don't want to share them in this public forum.
You can reach out to MathWorks Technical Support via the link below.
Josh Chen
Josh Chen on 11 Jan 2024
Hi James,
Thanks for the patience on clearly describe the issue. (Not easy as a big project)
When MATLAB Coder start generating code, it first parse all related files and see if it needs to create some struct that haven't been defined. For all ROS 2 messages, we have predefined structures. So the error message Error 1 and Error 2 usually means they might have been defined (not necessary by you, possibly by MATLAB Coder based on its understand of your code) somewhere else and the definition is not the same as the definition we used in publisher/subscriber. For example:
  1. Typo in field names
  2. Row versus Column-wise mismatch
  3. Extra or missing fields
For the rest of those errors, unfortunately we would have to look closer to the actual handle objects to see what's the culprit.
One thing that sound very interesting to me is that you said if you removed all those handles, you no longer see any error.
When reaching out to Techinical Support, could you please also provide the following information so that we can reproduce on our end:
  1. Which OS and Compiler are you using?
  2. Which version of MATLAB are you using?
  3. A simplified and (better not confidential) version of the code
  4. msg and srv folders for your custom messages and services.
Thanks,
Josh

Sign in to comment.

Answers (0)

Products


Release

R2022b

Community Treasure Hunt

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

Start Hunting!