Issues with using codegen on handle objects with complex methods
Ältere Kommentare anzeigen
I'm running into a fundamental issue with using codegen in my project, and it is unclear if there is a reasonable workaround. I am using several custom handle objects within a ros2 node that are used as inputs to subscription callback functions. In order to have codegen convert all of the internal functions (ie, to fully excercise it), I need to send that node a rather long and complex series of ros2 messages that trigger these various callbacks. In order to generate these messages within the node function itself, I would have to bring in the entire large test script and go through codegen for the whole thing, even though it is irrelevant to the function of the node itself. I addition to this, many of the functions I would need to be able to do so are not supported by codegen, so I would need to rework that entire script to account for that.
What I have tried so far as a workaround is the following:
- Place the node generation function within the test script, and output the node and subscriber handles back into the script. This works as intended within normal matlab, but is not supported within codegen since it does not support handle outputs.
- If I do not output the node and subscription handle, they are deleted when the function completes. In this case the script runs but none of the callbacks I want to trigger ever get run with the data they need to be thoroughly exercised, since they are triggered by the test script but the handles to which they are associated have been deleted. I can run codegen on this version, but it ultimately runs into the following error after all other errors have been resolved: 'The library 'ROS 2 Node' is not supported by the current target, language or compiler.'
- If I add a loop within the function to stop it from completing, it blocks further evaluation of the test script, so the messages never get sent and the callbacks never trigger. I have not tried running codegen on this variation.
At a high level, the test script and node that works look like the following:
%%% Test Script that works but fails codegen %%%
% Set up test node
% Call the node that I am trying to run codegen on
[objectfindernode, objectfindersub]=objectFinderNode()
% Import test data
% Convert test data into msg1 format
% Send msg1 via test node publisher
% Check msg2 via test node subscriber callback
%%% End of test script %%%
%%% Node that works but fails codegen %%%
function [objectfindernode, objectfindersub]=objectFinderNode()
% Initialize handle objects ob1-obn and run needed methods
% build ros2 node 'objectfindernode'
% Add publisher 'pub' that publishes response 'msg2'
% Add subscriber 'objectfindersub' that subcribes to 'msg1' with callback
% callback1(ob1,...,obn,pub)
end
function callback1(msg,ob1,..,obn,pub)
% Do handle objects ob1-obn methods
% Populate and send msg2 via pub
end
%%% End of node that works but fails codegen %%%
If I change it to the following, the msg2 check never occurs, indicating that callback 1 never happened. Codegen runs on this version, but I still run into the error: 'The library 'ROS 2 Node' is not supported by the current target, language or compiler.' I also do not know which parts of the code are actually getting called.
%%% Test Script that does not work correctly and fails codegen differently %%%
% Set up test node
% Call the node that I am trying to run codegen on
[objectfindernode, objectfindersub]=objectFinderNode()
% Import test data
% Convert test data into msg1 format
% Send msg1 via test node publisher
% Check msg2 via test node subscriber callback
%%% End of test script %%%
%%% Node that can run in codegen until the listed error %%%
function objectFinderNode()
% Initialize handle objects ob1-obn and run needed methods
% build ros2 node 'objectfindernode'
% Add publisher 'pub' that publishes response 'msg2'
% Add subscriber 'objectfindersub' that subcribes to 'msg1' with callback
% callback1(ob1,...,obn,pub)
end
function callback1(msg,ob1,..,obn,pub)
% Do handle objects ob1-obn methods
% Populate and send msg2 via pub
end
%%% End of node %%%
At this point I am stuck. Unless there are more workarounds that I am not aware of this is questionably feasible project, due to the difficulty involved in generating test data for the node with only the codegen-viable set of functions. Also, I have already applied the workaround shown here for how to fix the ros2subscription callback issues within codegen: https://www.mathworks.com/matlabcentral/answers/1851568-ros2-subscriber-callback-function-arguments-for-code-generation
Separately, are there plans to support handle object generation within loops in the future within codegen? I use cell arrays of handle objects throughout my project, so having to initialize each one individually is very tedious and verbose if it is a large array.
5 Kommentare
Richard McCormack
am 18 Dez. 2023
Hi James,
I work on the MATLAB Coder team. I have sent your question to someone more familiar with ROS who can hopefully help out.
As for the last question on your post:
> Separately, are there plans to support handle object generation within loops in the future within codegen? I use cell arrays of handle objects throughout my project, so having to initialize each one individually is very tedious and verbose if it is a large array.
Yes, this is absolutely on our radar. Unfortunately, I can not promise any definite timeline on when this feature will be supported. In the meantime, I think you can get rid of a lot of the tedium by writing a loop to initialize the cell as normal and then using coder.unroll on the loop to unroll the loop into a set of statements at codegen time.
Hope that helps,
Richard
James Croughan
am 18 Dez. 2023
Josh Chen
am 18 Dez. 2023
Hi James,
I am still a bit confused about the workflow, could you provide more information to help me understand this issue?
- When you generate a ROS 2 Node from a MATLAB function, that function itself need to be considered as a standalone executable. If you are trying to generate code for objectFinderNode, you should put all your code inside this function (I image that's what you did for option 3). - Question, in this case, the objectFinderNode becomes a node that contains a publisher and subscriber, where you can either process new messages in subscriber calllback or using the 'receive' function. Why do you still need to keep a handle to the node and subscirber?
- If you process everything in subscriber callback, that callback itself is in another thread. Even if you place an infinte while-loop to keep the generated node running, you should be able to see subscriber callback get triggered.
- Regarding the error 'The library 'ROS 2 Node' is not supported by the current target, language or compiler.' - I hope you are not generating mex... ROS functions/classes does not support mex generation. You would need to generate an executable/binary with the help of setting configuration as a ROS/ROS 2 hardware. For example:
cfg = = coder.config('exe');
cfg.Hardware = coder.hardware('Robot Operating System 2 (ROS 2)');
cfg.Hardware.BuildAction = 'Build and load';
Looking forward to hearing back from you.
Josh
James Croughan
am 19 Dez. 2023
Hi James,
Sorry about my late response, not sure why there is no notification forwarded to my email.
Yes, when you mentioned the system has multiple nodes (n=1:N), and they should be able to interact with each other, first time came into my mind is you can use script-based codegen and just run the codegen commmand multiple times to build and run multiple nodes.
I might not fully understand the execution structures you want to check and convert, but it sounds like each node and callback has their own specific parameter/variable, and you want to test all of those combinations.
If we create one function for each node, then it allows you to:
- Include infinite loop to keep node alive until you manually kill the node
- Use meaningful name to distinguish between different nodes (e.g. first function is the first node, so inside first function, use ros2node('node_1');, in second function, use ros2node('node_2');, etc
- Each node run independently and are always visible to other nodes as long as they are in the same domain id.
Hope that helps.
Thanks,
Josh
Antworten (0)
Kategorien
Mehr zu Custom Message Support finden Sie in Hilfe-Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!