Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Action support #410

Draft
wants to merge 61 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
f6ced1e
Added skeleton examples for action client and server
esteve Nov 28, 2022
f279041
Added action template
esteve Nov 28, 2022
483164a
Added action generation
esteve Nov 28, 2022
f555bbf
Added basic create_action_client function
esteve Nov 28, 2022
a89c196
Fix linter
esteve Nov 29, 2022
203b252
Split action client and server examples
esteve Jul 17, 2023
0b0bf4d
checkin
esteve Jul 17, 2023
1cc545e
checkin
esteve Jul 17, 2023
9fe3169
checkin
esteve Aug 10, 2023
e685f83
fix visibility
esteve Aug 10, 2023
1b5dd0c
Instantiate a new ActionClient
esteve Nov 8, 2023
eaa47f1
dded action generation
esteve Nov 28, 2022
3740a27
checkin
esteve Jul 17, 2023
3e4e718
checkin
esteve Jul 17, 2023
747f05d
checkin
esteve Nov 17, 2023
e1c837c
checkin
esteve Nov 17, 2023
af46ec4
checkin
esteve Nov 17, 2023
3e6fd1b
Fix missing exported pre_field_serde field
esteve Jan 17, 2024
55edf88
Removed extra code
esteve Jan 17, 2024
dccc667
Fix rclrs to compile after rebase
nwn Jun 6, 2024
573754d
Sketch out action server construction and destruction
nwn Jun 6, 2024
3733e5e
Sketch out action client as well
nwn Jun 6, 2024
ac4cc64
Pass rcl_clock_t from Node to ActionServer
nwn Jun 6, 2024
018ef66
Split action servers and clients into separate modules
nwn Jun 6, 2024
279bd8a
Move ServerGoalHandle to separate module
nwn Jun 6, 2024
8b76a0e
Begin implementing ActionServerGoalHandle functions
nwn Jun 6, 2024
a45b8ba
Make GoalUuid into a newtype
nwn Jun 8, 2024
03b9b74
Document the ServerGoalHandle struct
nwn Jun 8, 2024
045a66d
Add documentation and clean up
nwn Jun 8, 2024
38c5b95
Fix action typesupport function
nwn Jun 11, 2024
a323bd0
Take goal, cancel, and accepted callbacks in ActionServer
nwn Jun 11, 2024
0319419
Store action clients and servers in the Node
nwn Jul 6, 2024
b6c8b47
Add action client/server entities to wait set
nwn Jul 7, 2024
2fbd496
Handle action server/client readiness in WaitSet and executor
nwn Jul 7, 2024
d5fc2f3
Add rcl_action error codes
nwn Jul 13, 2024
e72d1c9
Add ActionImpl trait with internal messages and services
nwn Jul 13, 2024
02dcc7a
[WIP] Start defining server/client execute functions
nwn Jul 13, 2024
edebb76
Split srv.rs.em into idiomatic and rmw template files
nwn Jul 20, 2024
c9a28f7
Generate underlying service definitions for actions
nwn Jul 20, 2024
dc8781c
Add runtime trait to get the UUID from a goal request
nwn Jul 20, 2024
9d6a8b8
Use rcl-allocated goal handle pointer in ServerGoalHandle
nwn Jul 20, 2024
5425072
Split execute_goal_request() out into three functions
nwn Jul 20, 2024
9595b6e
Partial implementation of ActionServer::publish_status()
nwn Jul 25, 2024
5496b10
Add DropGuard convenience wrapper
nwn Aug 7, 2024
46e7093
Complete implementation of ActionServer::publish_status()
nwn Aug 7, 2024
b15c0c5
Move goal acceptance logic back into execute_goal_request()
nwn Aug 7, 2024
f8fedbc
Integrate RMW message methods into ActionImpl
nwn Aug 7, 2024
241f642
Add UUID->GoalHandle hash-map to action server
nwn Aug 7, 2024
1e75ce8
Add rosidl_runtime_rs::ActionImpl::create_feedback_message()
nwn Aug 9, 2024
ea04dcb
Add ActionServer::publish_feedback() method
nwn Aug 9, 2024
b06c14c
Implement goal expiration in action server
nwn Aug 9, 2024
249d5ec
Implement goal cancel requests
nwn Aug 10, 2024
213f891
Add GetResultService methods to ActionImpl
nwn Aug 16, 2024
a7c45fc
Implement action result requests in the action server
nwn Aug 16, 2024
a33ec48
Implement ActionImpl trait methods in generator
nwn Aug 16, 2024
e98882f
Fix formatting in example
nwn Aug 23, 2024
4ff9fd4
Hook up ServerGoalHandle callbacks into the ActionServer
nwn Aug 23, 2024
d8a0a1d
Replace set_result_response_status with create_result_response
nwn Aug 23, 2024
4d597c8
Switch to create_result_response() in rclrs
nwn Aug 23, 2024
be5b7e1
Hook up goal termination methods for goal handles
nwn Aug 23, 2024
75fd275
Implement client-side trait methods for action messages
nwn Sep 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions examples/minimal_action_client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "examples_rclrs_minimal_action_client"
version = "0.3.1"
# This project is not military-sponsored, Jacob's employment contract just requires him to use this email address
authors = ["Esteve Fernandez <[email protected]>", "Nikolai Morin <[email protected]>", "Jacob Hassold <[email protected]>"]
edition = "2021"

[[bin]]
name = "minimal_action_client"
path = "src/minimal_action_client.rs"

[dependencies]
anyhow = {version = "1", features = ["backtrace"]}

[dependencies.rclrs]
version = "0.4"

[dependencies.rosidl_runtime_rs]
version = "0.4"

[dependencies.example_interfaces]
version = "*"
26 changes: 26 additions & 0 deletions examples/minimal_action_client/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0"?>
<?xml-model
href="http://download.ros.org/schema/package_format3.xsd"
schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>examples_rclrs_minimal_action_client</name>
<version>0.3.1</version>
<description>Minimal action client examples for rclrs.</description>
<maintainer email="[email protected]">Esteve Fernandez</maintainer>
<maintainer email="[email protected]">Nikolai Morin</maintainer>
<!-- This project is not military-sponsored, Jacob's employment contract just requires him to use this email address -->
<maintainer email="[email protected]">Jacob Hassold</maintainer>
<license>Apache License 2.0</license>

<build_depend>rclrs</build_depend>
<build_depend>rosidl_runtime_rs</build_depend>
<build_depend>example_interfaces</build_depend>

<exec_depend>rclrs</exec_depend>
<exec_depend>rosidl_runtime_rs</exec_depend>
<exec_depend>example_interfaces</exec_depend>

<export>
<build_type>ament_cargo</build_type>
</export>
</package>
14 changes: 14 additions & 0 deletions examples/minimal_action_client/src/minimal_action_client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use std::env;

use anyhow::{Error, Result};

fn main() -> Result<(), Error> {
let context = rclrs::Context::new(env::args())?;

let node = rclrs::create_node(&context, "minimal_client")?;

let _client =
node.create_action_client::<example_interfaces::action::Fibonacci>("fibonacci")?;

Ok(())
}
22 changes: 22 additions & 0 deletions examples/minimal_action_server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "examples_rclrs_minimal_action_server"
version = "0.3.1"
# This project is not military-sponsored, Jacob's employment contract just requires him to use this email address
authors = ["Esteve Fernandez <[email protected]>", "Nikolai Morin <[email protected]>", "Jacob Hassold <[email protected]>"]
edition = "2021"

[[bin]]
name = "minimal_action_server"
path = "src/minimal_action_server.rs"

[dependencies]
anyhow = {version = "1", features = ["backtrace"]}

[dependencies.rclrs]
version = "0.4"

[dependencies.rosidl_runtime_rs]
version = "0.4"

[dependencies.example_interfaces]
version = "*"
26 changes: 26 additions & 0 deletions examples/minimal_action_server/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0"?>
<?xml-model
href="http://download.ros.org/schema/package_format3.xsd"
schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>examples_rclrs_minimal_action_server</name>
<version>0.3.1</version>
<description>Minimal action server examples for rclrs.</description>
<maintainer email="[email protected]">Esteve Fernandez</maintainer>
<maintainer email="[email protected]">Nikolai Morin</maintainer>
<!-- This project is not military-sponsored, Jacob's employment contract just requires him to use this email address -->
<maintainer email="[email protected]">Jacob Hassold</maintainer>
<license>Apache License 2.0</license>

<build_depend>rclrs</build_depend>
<build_depend>rosidl_runtime_rs</build_depend>
<build_depend>example_interfaces</build_depend>

<exec_depend>rclrs</exec_depend>
<exec_depend>rosidl_runtime_rs</exec_depend>
<exec_depend>example_interfaces</exec_depend>

<export>
<build_type>ament_cargo</build_type>
</export>
</package>
79 changes: 79 additions & 0 deletions examples/minimal_action_server/src/minimal_action_server.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use std::{env, sync::Arc, thread};

use anyhow::{Error, Result};

type Fibonacci = example_interfaces::action::Fibonacci;
type GoalHandleFibonacci = rclrs::ServerGoalHandle<Fibonacci>;

fn handle_goal(
_uuid: &rclrs::GoalUUID,
goal: Arc<example_interfaces::action::rmw::Fibonacci_Goal>,
) -> rclrs::GoalResponse {
println!("Received goal request with order {}", goal.order);
if goal.order > 9000 {
rclrs::GoalResponse::Reject
} else {
rclrs::GoalResponse::AcceptAndExecute
}
}

fn handle_cancel(_goal_handle: Arc<GoalHandleFibonacci>) -> rclrs::CancelResponse {
println!("Got request to cancel goal");
rclrs::CancelResponse::Accept
}

fn execute(goal_handle: Arc<GoalHandleFibonacci>) {
println!("Executing goal");
let feedback = example_interfaces::action::Fibonacci_Feedback {
sequence: [0, 1].to_vec(),
};

for i in 1..goal_handle.goal_request.order {
if goal_handle.is_canceling() {
let result = example_interfaces::action::Fibonacci_Result {
sequence: Vec::new(),
};

goal_handle.canceled(&result);
println!("Goal canceled");
return;
}

// Update sequence sequence
feedback
.sequence
.push(feedback.sequence[i as usize] + feedback.sequence[(i - 1) as usize]);
// Publish feedback
goal_handle.publish_feedback(&feedback);
println!("Publishing feedback");
thread::sleep(std::time::Duration::from_millis(100));
}

let result = example_interfaces::action::Fibonacci_Result {
sequence: Vec::new(),
};
result.sequence = feedback.sequence.clone();
goal_handle.succeed(&result);
println!("Goal succeeded");
}

fn handle_accepted(goal_handle: Arc<GoalHandleFibonacci>) {
thread::spawn(move || {
execute(goal_handle);
});
}

fn main() -> Result<(), Error> {
let context = rclrs::Context::new(env::args())?;

let mut node = rclrs::create_node(&context, "minimal_action_server")?;

let _action_server = node.create_action_server::<example_interfaces::action::Fibonacci>(
"fibonacci",
handle_goal,
handle_cancel,
handle_accepted,
);

rclrs::spin(node).map_err(|err| err.into())
}
3 changes: 2 additions & 1 deletion rclrs/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
<build_depend>libclang-dev</build_depend>
<build_depend>rosidl_runtime_rs</build_depend>
<depend>rcl</depend>
<depend>rcl_action</depend>
<depend>builtin_interfaces</depend>
<depend>rcl_interfaces</depend>
<depend>rosgraph_msgs</depend>

<test_depend>test_msgs</test_depend>

<export>
Expand Down
57 changes: 57 additions & 0 deletions rclrs/src/action.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
pub(crate) mod client;
pub(crate) mod server;
mod server_goal_handle;

use crate::rcl_bindings::RCL_ACTION_UUID_SIZE;
use std::fmt;

pub use client::{ActionClient, ActionClientBase};
pub use server::{ActionServer, ActionServerBase};
pub use server_goal_handle::ServerGoalHandle;

/// A unique identifier for a goal request.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GoalUuid(pub [u8; RCL_ACTION_UUID_SIZE]);

impl fmt::Display for GoalUuid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
self.0[0],
self.0[1],
self.0[2],
self.0[3],
self.0[4],
self.0[5],
self.0[6],
self.0[7],
self.0[8],
self.0[9],
self.0[10],
self.0[11],
self.0[12],
self.0[13],
self.0[14],
self.0[15],
)
}
}

/// The response returned by an [`ActionServer`]'s goal callback when a goal request is received.
#[derive(PartialEq, Eq)]
pub enum GoalResponse {
/// The goal is rejected and will not be executed.
Reject = 1,
/// The server accepts the goal and will begin executing it immediately.
AcceptAndExecute = 2,
/// The server accepts the goal and will begin executing it later.
AcceptAndDefer = 3,
}

/// The response returned by an [`ActionServer`]'s cancel callback when a goal is requested to be cancelled.
#[derive(PartialEq, Eq)]
pub enum CancelResponse {
/// The server will not try to cancel the goal.
Reject = 1,
/// The server will try to cancel the goal.
Accept = 2,
}
Loading
Loading