Skip to content

Commit a8c5e50

Browse files
authored
ROS2 Action Support: Merge pull request #474 from memrecakal/master
ROS2 Action Support
2 parents 2d817a6 + 97fedb2 commit a8c5e50

File tree

1,277 files changed

+4490
-2029
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,277 files changed

+4490
-2029
lines changed

Libraries/MessageGeneration/ActionAutoGen.cs

Lines changed: 109 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ You may obtain a copy of the License at
1111
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
See the License for the specific language governing permissions and
1313
limitations under the License.
14+
15+
- Added ROS2 action support: Added new identifiers for ROS2 default constructor, parameterized constructor, and ROS message name.
16+
- Default constructor: goal -> args, result -> values, feedback -> values
17+
- Parameterized constructor: goal -> GoalInfo instead of GoalID, result -> sbyte status, bool result, string id instead of GoalStatus, feedback -> string id, string action instead of GoalStatus
18+
- ROS message name: rosPackageName/action/wrapperName
19+
- Namespace: RosSharp.RosBridgeClient.MessageTypes.Action instead of RosSharp.RosBridgeClient.MessageTypes.Actionlib
20+
© Siemens AG, 2025, Mehmet Emre Cakal, [email protected]/[email protected]
1421
*/
1522

1623
using System;
@@ -163,8 +170,28 @@ private string GenerateDefaultValueConstructor(string className)
163170

164171
foreach (string identifier in symbolTable.Keys)
165172
{
166-
constructor += TWO_TABS + ONE_TAB + "this." + identifier + " = ";
167173
string type = symbolTable[identifier];
174+
175+
string adjustedIdentifier = identifier;
176+
177+
if (ActionAutoGen.isRos2)
178+
{
179+
if (identifier.Equals("goal"))
180+
{
181+
adjustedIdentifier = "args";
182+
}
183+
else if (identifier.Equals("result") || identifier.Equals("feedback"))
184+
{
185+
adjustedIdentifier = "values";
186+
}
187+
else
188+
{
189+
adjustedIdentifier = identifier;
190+
Console.WriteLine("Warning: Unrecognized identifier: " + identifier);
191+
}
192+
}
193+
194+
constructor += TWO_TABS + ONE_TAB + "this." + adjustedIdentifier + " = ";
168195
constructor += "new " + type + "();\n";
169196
}
170197

@@ -181,21 +208,68 @@ private string GenerateParameterizedConstructor(string className, string msgType
181208
string paramsOut = "";
182209
string assignments = "";
183210

184-
if (msgType.Equals("Goal"))
211+
if (ActionAutoGen.isRos2)
185212
{
186-
paramsIn += "Header header, GoalID goal_id, ";
187-
paramsOut += "header, goal_id";
213+
if (msgType.Equals("Goal"))
214+
{
215+
paramsIn += "Header header, GoalInfo goalInfo, ";
216+
paramsOut += "header, goalInfo";
217+
}
218+
else if (msgType.Equals("Result"))
219+
{
220+
paramsIn += "Header header, string action, sbyte status, bool result, string id, ";
221+
paramsOut += "header, action, status, result, id";
222+
}
223+
else if (msgType.Equals("Feedback"))
224+
{
225+
paramsIn += "Header header, string id, string action, ";
226+
paramsOut += "header, id, action";
227+
}
228+
else
229+
{
230+
Console.WriteLine("Warning: Unrecognized message type: " + msgType);
231+
}
188232
}
189-
else if (msgType.Equals("Result") || msgType.Equals("Feedback")) {
190-
paramsIn += "Header header, GoalStatus status, ";
191-
paramsOut += "header, status";
233+
234+
else
235+
{
236+
if (msgType.Equals("Goal"))
237+
{
238+
paramsIn += "Header header, GoalID goal_id, ";
239+
paramsOut += "header, goal_id";
240+
}
241+
else if (msgType.Equals("Result") || msgType.Equals("Feedback"))
242+
{
243+
paramsIn += "Header header, GoalStatus status, ";
244+
paramsOut += "header, status";
245+
}
192246
}
193247

194248
foreach (string identifier in symbolTable.Keys)
195249
{
196250
string type = symbolTable[identifier];
197-
paramsIn += type + " " + identifier + ", ";
198-
assignments += TWO_TABS + ONE_TAB + "this." + identifier + " = " + identifier + ";\n";
251+
252+
string adjustedIdentifier = identifier;
253+
254+
if (ActionAutoGen.isRos2)
255+
{
256+
if (identifier.Equals("goal"))
257+
{
258+
adjustedIdentifier = "args";
259+
}
260+
else if (identifier.Equals("result") || identifier.Equals("feedback"))
261+
{
262+
adjustedIdentifier = "values";
263+
}
264+
else
265+
{
266+
adjustedIdentifier = identifier;
267+
Console.WriteLine("Warning: Unrecognized identifier: " + identifier);
268+
}
269+
}
270+
271+
paramsIn += type + " " + adjustedIdentifier + ", ";
272+
assignments += TWO_TABS + ONE_TAB + "this." + adjustedIdentifier + " = " + adjustedIdentifier + ";\n";
199273
}
200274

201275
if (!paramsIn.Equals(""))
@@ -218,9 +292,19 @@ public void WrapActionSections(string type)
218292

219293
string outPath = Path.Combine(this.outPath, wrapperName + ".cs");
220294

221-
string imports =
222-
"using RosSharp.RosBridgeClient.MessageTypes.Std;\n" +
223-
"using RosSharp.RosBridgeClient.MessageTypes.Actionlib;\n\n";
295+
string imports = "using RosSharp.RosBridgeClient.MessageTypes.Std;\n";
296+
297+
if (ActionAutoGen.isRos2)
298+
{
299+
if (type == "Goal")
300+
{
301+
imports += "using RosSharp.RosBridgeClient.MessageTypes.Action;\n\n";
302+
}
303+
}
304+
else
305+
{
306+
imports += "using RosSharp.RosBridgeClient.MessageTypes.Actionlib;\n\n";
307+
}
224308

225309
symbolTable = new Dictionary<string, string>();
226310

@@ -254,10 +338,19 @@ public void WrapActionSections(string type)
254338
ONE_TAB + "{\n"
255339
);
256340

257-
// Write ROS package name
258-
writer.Write(
259-
TWO_TABS + "public const string RosMessageName = \"" + rosPackageName + "/" + wrapperName + "\";\n"
260-
);
341+
if (ActionAutoGen.isRos2)
342+
{
343+
writer.Write(
344+
TWO_TABS + "public const string RosMessageName = \"" + rosPackageName + "/" + "action" + "/"
345+
+ wrapperName + "\";\n");
346+
}
347+
else
348+
{
349+
writer.Write(
350+
TWO_TABS + "public const string RosMessageName = \"" + rosPackageName + "/" + wrapperName + "\";\n"
351+
);
352+
}
353+
Console.WriteLine("RosMessageName: " + rosPackageName + "/" + wrapperName);
261354

262355
// Record goal/result/feedback declaration
263356
symbolTable.Add(MsgAutoGenUtilities.LowerFirstLetter(type), msgName);

Libraries/MessageGeneration/MessageGeneration.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
<Company>Siemens AG</Company>
1313
<Product>ROS#</Product>
1414
<Copyright>Copyright © 2024</Copyright>
15-
<AssemblyVersion>2.0.0.0</AssemblyVersion>
16-
<FileVersion>2.0.0.0</FileVersion>
17-
<Version>2.0.0</Version>
15+
<AssemblyVersion>2.1.0.0</AssemblyVersion>
16+
<FileVersion>2.1.0.0</FileVersion>
17+
<Version>2.1.0</Version>
1818
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
19-
<PackageId>RosSharpMessageGeneration</PackageId>
19+
<PackageId>Siemens.RosSharp.MessageGeneration</PackageId>
2020
<Title>MessageGeneration</Title>
2121
<Authors>ros-sharp</Authors>
2222
<EnablePackageValidation>true</EnablePackageValidation>

Libraries/MessageGenerationConsoleTool/MessageGenerationConsoleTool.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
<Company>Siemens AG</Company>
1414
<Product>ROS#</Product>
1515
<Copyright>Copyright © 2024</Copyright>
16-
<AssemblyVersion>1.7.0.0</AssemblyVersion>
17-
<FileVersion>1.7.0.0</FileVersion>
16+
<AssemblyVersion>2.1.0.0</AssemblyVersion>
17+
<FileVersion>2.1.0.0</FileVersion>
1818
</PropertyGroup>
1919
<ItemGroup>
2020
<ProjectReference Include="..\MessageGeneration\MessageGeneration.csproj" />

Libraries/RosBridgeClient/Actionlib/ActionClient.cs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,20 @@ You may obtain a copy of the License at
1111
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
See the License for the specific language governing permissions and
1313
limitations under the License.
14+
15+
- Added ROS2 action support:
16+
- The Initialize() and Terminate() methods are no longer needed.
17+
- The SetActionGoal() method has been added, which allows the user to set the action goal with additional parameters such as feedback, fragment size, and compression.
18+
- The SendGoal() method now uses the SendActionGoalRequest() method from the RosSocket class to send the action goal request.
19+
- The CancelGoal() method now uses the CancelActionGoalRequest() method from the RosSocket class to cancel the action goal request.
20+
- The StatusCallback(), FeedbackCallback(), and ResultCallback() methods have been modified to handle the new message types in ROS2.
21+
- The OnStatusUpdated(), OnFeedbackReceived(), and OnResultReceived() methods are still implemented by the user to handle the status, feedback, and result respectively.
22+
- The goalStatus, lastResultSuccess, and frameId variables have been added to store the goal status, last result success status, and frame ID respectively.
23+
24+
© Siemens AG 2025, Mehmet Emre Cakal, [email protected]/[email protected]
1425
*/
1526

27+
#if !ROS2
1628
using RosSharp.RosBridgeClient.MessageTypes.Actionlib;
1729

1830
namespace RosSharp.RosBridgeClient.Actionlib
@@ -99,3 +111,105 @@ private void ResultCallback(TActionResult actionResult)
99111
}
100112
}
101113
}
114+
115+
#else
116+
117+
using RosSharp.RosBridgeClient.MessageTypes.Action;
118+
using System;
119+
120+
namespace RosSharp.RosBridgeClient.Actionlib
121+
{
122+
public abstract class ActionClient<TAction, TActionGoal, TActionResult, TActionFeedback, TGoal, TResult, TFeedback>
123+
where TAction : Action<TActionGoal, TActionResult, TActionFeedback, TGoal, TResult, TFeedback>
124+
where TActionGoal : ActionGoal<TGoal>
125+
where TActionResult : ActionResult<TResult>
126+
where TActionFeedback : ActionFeedback<TFeedback>
127+
where TGoal : Message
128+
where TResult : Message
129+
where TFeedback : Message
130+
{
131+
public RosSocket rosSocket;
132+
133+
public TAction action;
134+
public string actionName;
135+
public string actionType;
136+
137+
public GoalStatus goalStatus;
138+
public bool lastResultSuccess;
139+
public string frameId;
140+
141+
142+
public void Initialize()
143+
{
144+
// Not needed anymore
145+
}
146+
147+
public void Terminate()
148+
{
149+
// Not needed anymore
150+
}
151+
152+
public abstract void SetActionGoal(TGoal goal, bool feedback, int fragmentSize, string compression);
153+
public abstract TActionGoal GetActionGoal();
154+
155+
public void SendGoal()
156+
{
157+
rosSocket.SendActionGoalRequest<TActionGoal, TGoal, TActionFeedback, TActionResult>(
158+
action.action_goal,
159+
ResultCallback,
160+
FeedbackCallback);
161+
162+
lastResultSuccess = false;
163+
}
164+
165+
public void CancelGoal(string frameId = null)
166+
{
167+
rosSocket.CancelActionGoalRequest<TActionResult>(
168+
frameId ?? this.frameId,
169+
actionName,
170+
ResultCallback);
171+
}
172+
173+
174+
175+
// Implement by user to handle status
176+
protected abstract void OnStatusUpdated();
177+
private void StatusCallback(GoalStatusArray actionGoalStatusArray)
178+
{
179+
if (actionGoalStatusArray.status_list.Length > 0)
180+
{
181+
goalStatus = actionGoalStatusArray.status_list[actionGoalStatusArray.status_list.Length - 1];
182+
}
183+
OnStatusUpdated();
184+
}
185+
186+
// Implement by user to handle feedback.
187+
protected abstract void OnFeedbackReceived();
188+
private void FeedbackCallback(TActionFeedback actionFeedbackValues)
189+
{
190+
action.action_feedback = actionFeedbackValues;
191+
frameId = actionFeedbackValues.id;
192+
OnFeedbackReceived();
193+
}
194+
195+
// Implement by user to handle result.
196+
protected abstract void OnResultReceived();
197+
private void ResultCallback(TActionResult actionResult)
198+
{
199+
if (actionResult.result == false)
200+
{
201+
Console.WriteLine("Request failed!");
202+
}
203+
else
204+
{
205+
action.action_result = actionResult;
206+
goalStatus.status = actionResult.status;
207+
lastResultSuccess = actionResult.result;
208+
frameId = actionResult.id;
209+
OnResultReceived();
210+
}
211+
212+
}
213+
}
214+
}
215+
#endif

0 commit comments

Comments
 (0)