Skip to content

Commit

Permalink
actions: add example action client and server
Browse files Browse the repository at this point in the history
  • Loading branch information
hoffmann-stefan committed Jul 19, 2022
1 parent e6639a6 commit feb56f9
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 0 deletions.
18 changes: 18 additions & 0 deletions rcldotnet_examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ find_package(rcldotnet REQUIRED)

find_package(rcldotnet_common REQUIRED)

find_package(builtin_interfaces REQUIRED)
find_package(std_msgs REQUIRED)
find_package(std_srvs REQUIRED)
find_package(test_msgs REQUIRED)
find_package(rcldotnet REQUIRED)

find_package(dotnet_cmake_module REQUIRED)
Expand All @@ -19,8 +21,10 @@ find_package(DotNETExtra REQUIRED)
set(_assemblies_dep_dlls
${rcldotnet_common_ASSEMBLIES_DLL}
${rcldotnet_ASSEMBLIES_DLL}
${builtin_interfaces_ASSEMBLIES_DLL}
${std_msgs_ASSEMBLIES_DLL}
${std_srvs_ASSEMBLIES_DLL}
${test_msgs_ASSEMBLIES_DLL}
)

add_dotnet_executable(rcldotnet_talker
Expand All @@ -45,9 +49,23 @@ add_dotnet_executable(rcldotnet_example_client
${_assemblies_dep_dlls}
)

add_dotnet_executable(rcldotnet_example_action_server
RCLDotnetActionServer.cs
INCLUDE_DLLS
${_assemblies_dep_dlls}
)

add_dotnet_executable(rcldotnet_example_action_client
RCLDotnetActionClient.cs
INCLUDE_DLLS
${_assemblies_dep_dlls}
)

install_dotnet(rcldotnet_talker DESTINATION lib/${PROJECT_NAME}/dotnet)
install_dotnet(rcldotnet_listener DESTINATION lib/${PROJECT_NAME}/dotnet)
install_dotnet(rcldotnet_example_service DESTINATION lib/${PROJECT_NAME}/dotnet)
install_dotnet(rcldotnet_example_client DESTINATION lib/${PROJECT_NAME}/dotnet)
install_dotnet(rcldotnet_example_action_server DESTINATION lib/${PROJECT_NAME}/dotnet)
install_dotnet(rcldotnet_example_action_client DESTINATION lib/${PROJECT_NAME}/dotnet)

ament_package()
87 changes: 87 additions & 0 deletions rcldotnet_examples/RCLDotnetActionClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using ROS2;
using test_msgs.action;

namespace ConsoleApplication
{
public static class RCLDotnetService
{
public static void Main(string[] args)
{
RCLdotnet.Init();
var node = RCLdotnet.CreateNode("action_client");

var actionClient = node.CreateActionClient<Fibonacci, Fibonacci_Goal, Fibonacci_Result, Fibonacci_Feedback>("fibonacci");

var cts = new CancellationTokenSource();
var task = DoWorkAsync(actionClient, cts.Token);

while (RCLdotnet.Ok())
{
RCLdotnet.SpinOnce(node, 500);

if (task.IsCompletedSuccessfully)
{
break;
}
else if (task.IsFaulted)
{
Console.WriteLine($"Task faulted. Exception {task.Exception}");
break;
}
else if (task.IsCanceled)
{
Console.WriteLine("Task canceled.");
break;
}
}

cts.Cancel();
task.GetAwaiter().GetResult();
}

private static async Task DoWorkAsync(
ActionClient<Fibonacci, Fibonacci_Goal, Fibonacci_Result, Fibonacci_Feedback> actionClient,
CancellationToken cancellationToken)
{
while (!actionClient.ServerIsReady())
{
cancellationToken.ThrowIfCancellationRequested();

// NOTE: This causes the code to resume in an background worker Thread.
// Consider this when copying code from the example if additional synchronization is needed.
await Task.Delay(1000, cancellationToken);
}

var goal = new Fibonacci_Goal();
goal.Order = 10;

Console.WriteLine("SendGoal");

ActionClientGoalHandle<Fibonacci, Fibonacci_Goal, Fibonacci_Result, Fibonacci_Feedback> goalHandleForCallback = null;

var goalHandle = await actionClient.SendGoalAsync(goal, (Fibonacci_Feedback feedback) =>
{
Console.WriteLine($"Feedback: {string.Join(", ", feedback.Sequence)}");
Console.WriteLine($"Status after Feedback: {goalHandleForCallback.Status}");
});

goalHandleForCallback = goalHandle;

if (goalHandle.Accepted)
{
Console.WriteLine("Goal accepted.");

var result = await goalHandle.GetResultAsync();
Console.WriteLine($"Result: {string.Join(", ", result.Sequence)}");
Console.WriteLine($"Status: {goalHandle.Status}");
}
else
{
Console.WriteLine("Goal not accepted.");
}
}
}
}
70 changes: 70 additions & 0 deletions rcldotnet_examples/RCLDotnetActionServer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using ROS2;
using test_msgs.action;

namespace ConsoleApplication
{
public static class RCLDotnetService
{
public static void Main(string[] args)
{
RCLdotnet.Init();
var node = RCLdotnet.CreateNode("action_server");

var actionServer = node.CreateActionServer<Fibonacci, Fibonacci_Goal, Fibonacci_Result, Fibonacci_Feedback>("fibonacci", HandleAccepted, cancelCallback: HandleCancel);

RCLdotnet.Spin(node);
}

private static void HandleAccepted(ActionServerGoalHandle<Fibonacci, Fibonacci_Goal, Fibonacci_Result, Fibonacci_Feedback> goalHandle)
{
// Don't block in the callback.
// -> Don't wait for the returned Task.
_ = DoWorkWithGoal(goalHandle);
}

private static CancelResponse HandleCancel(ActionServerGoalHandle<Fibonacci, Fibonacci_Goal, Fibonacci_Result, Fibonacci_Feedback> goalHandle)
{
return CancelResponse.Accept;
}

private static async Task DoWorkWithGoal(ActionServerGoalHandle<Fibonacci, Fibonacci_Goal, Fibonacci_Result, Fibonacci_Feedback> goalHandle)
{
Console.WriteLine("Executing goal...");
var feedback = new Fibonacci_Feedback();

feedback.Sequence = new List<int> { 0, 1 };

for (int i = 1; i < goalHandle.Goal.Order; i++)
{
if (goalHandle.IsCanceling)
{
var cancelResult = new Fibonacci_Result();
cancelResult.Sequence = feedback.Sequence;

Console.WriteLine($"Canceled Result: {string.Join(", ", cancelResult.Sequence)}");
goalHandle.Canceled(cancelResult);
return;
}

feedback.Sequence.Add(feedback.Sequence[i] + feedback.Sequence[i - 1]);

Console.WriteLine($"Feedback: {string.Join(", ", feedback.Sequence)}");
goalHandle.PublishFeedback(feedback);

// NOTE: This causes the code to resume in an background worker Thread.
// Consider this when copying code from the example if additional synchronization is needed.
await Task.Delay(1000);
}

var result = new Fibonacci_Result();
result.Sequence = feedback.Sequence;

Console.WriteLine($"Result: {string.Join(", ", result.Sequence)}");
goalHandle.Succeed(result);
}
}
}
4 changes: 4 additions & 0 deletions rcldotnet_examples/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,22 @@
<buildtool_depend>rcldotnet_common</buildtool_depend>
<buildtool_export_depend>rosidl_cmake</buildtool_export_depend>

<build_depend>builtin_interfaces</build_depend>
<build_depend>example_interfaces</build_depend>
<build_depend>rcldotnet</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>std_srvs</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>test_msgs</build_depend>

<exec_depend>rcldotnet_common</exec_depend>
<exec_depend>builtin_interfaces</exec_depend>
<exec_depend>example_interfaces</exec_depend>
<exec_depend>rcldotnet</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>std_srvs</exec_depend>
<exec_depend>sensor_msgs</exec_depend>
<exec_depend>test_msgs</exec_depend>

<export>
<build_type>ament_cmake</build_type>
Expand Down

0 comments on commit feb56f9

Please sign in to comment.