Async api for waiting on services and action servers.
Implemented via polling in spin_once. Can be improved.
This commit is contained in:
parent
2babcaa5c6
commit
7853cb7161
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "r2r"
|
name = "r2r"
|
||||||
version = "0.3.0"
|
version = "0.3.5"
|
||||||
authors = ["Martin Dahl <martin.dahl@gmail.com>"]
|
authors = ["Martin Dahl <martin.dahl@gmail.com>"]
|
||||||
description = "Minimal ros2 bindings."
|
description = "Minimal ros2 bindings."
|
||||||
license = "Apache-2.0/MIT"
|
license = "Apache-2.0/MIT"
|
||||||
|
|
|
||||||
|
|
@ -10,27 +10,30 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let ctx = r2r::Context::create()?;
|
let ctx = r2r::Context::create()?;
|
||||||
let mut node = r2r::Node::create(ctx, "testnode", "")?;
|
let mut node = r2r::Node::create(ctx, "testnode", "")?;
|
||||||
let client = node.create_action_client::<Fibonacci::Action>("/fibonacci")?;
|
let client = node.create_action_client::<Fibonacci::Action>("/fibonacci")?;
|
||||||
|
let action_server_available = node.is_available(&client)?;
|
||||||
|
|
||||||
// signal that we are done
|
// signal that we are done
|
||||||
let done = Arc::new(Mutex::new(false));
|
let done = Arc::new(Mutex::new(false));
|
||||||
|
|
||||||
println!("waiting for action service...");
|
|
||||||
while !node.action_server_available(&client)? {
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
|
||||||
}
|
|
||||||
println!("action service available.");
|
|
||||||
|
|
||||||
let goal = Fibonacci::Goal { order: 5 };
|
|
||||||
println!("sending goal: {:?}", goal);
|
|
||||||
let goal_fut = client.send_goal_request(goal)?;
|
|
||||||
|
|
||||||
let mut pool = LocalPool::new();
|
let mut pool = LocalPool::new();
|
||||||
let spawner = pool.spawner();
|
let spawner = pool.spawner();
|
||||||
|
|
||||||
let task_spawner = spawner.clone();
|
let task_spawner = spawner.clone();
|
||||||
let task_done = done.clone();
|
let task_done = done.clone();
|
||||||
spawner.spawn_local(async move {
|
spawner.spawn_local(async move {
|
||||||
let (goal, result, feedback) = goal_fut.await.unwrap(); // assume success
|
println!("waiting for action service...");
|
||||||
|
action_server_available
|
||||||
|
.await
|
||||||
|
.expect("could not await action server");
|
||||||
|
println!("action service available.");
|
||||||
|
|
||||||
|
let goal = Fibonacci::Goal { order: 5 };
|
||||||
|
println!("sending goal: {:?}", goal);
|
||||||
|
let (goal, result, feedback) = client
|
||||||
|
.send_goal_request(goal)
|
||||||
|
.expect("could not send goal request")
|
||||||
|
.await
|
||||||
|
.expect("did not get goal");
|
||||||
|
|
||||||
println!("goal accepted: {}", goal.uuid);
|
println!("goal accepted: {}", goal.uuid);
|
||||||
// process feedback stream in its own task
|
// process feedback stream in its own task
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,19 @@
|
||||||
use futures::executor::LocalPool;
|
use futures::executor::LocalPool;
|
||||||
use futures::task::LocalSpawnExt;
|
use futures::task::LocalSpawnExt;
|
||||||
|
use futures::Future;
|
||||||
use r2r;
|
use r2r;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use r2r::example_interfaces::srv::AddTwoInts;
|
use r2r::example_interfaces::srv::AddTwoInts;
|
||||||
|
|
||||||
async fn requester_task(
|
async fn requester_task(
|
||||||
|
node_available: impl Future<Output = r2r::Result<()>>,
|
||||||
c: r2r::Client<AddTwoInts::Service>,
|
c: r2r::Client<AddTwoInts::Service>,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut x: i64 = 0;
|
let mut x: i64 = 0;
|
||||||
|
println!("waiting for service...");
|
||||||
|
node_available.await?;
|
||||||
|
println!("service available.");
|
||||||
loop {
|
loop {
|
||||||
let req = AddTwoInts::Request { a: 10 * x, b: x };
|
let req = AddTwoInts::Request { a: 10 * x, b: x };
|
||||||
print!("{} + {} = ", req.a, req.b);
|
print!("{} + {} = ", req.a, req.b);
|
||||||
|
|
@ -29,19 +34,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut node = r2r::Node::create(ctx, "testnode", "")?;
|
let mut node = r2r::Node::create(ctx, "testnode", "")?;
|
||||||
let client = node.create_client::<AddTwoInts::Service>("/add_two_ints")?;
|
let client = node.create_client::<AddTwoInts::Service>("/add_two_ints")?;
|
||||||
|
|
||||||
// wait for service to be available
|
let service_available = node.is_available(&client)?;
|
||||||
println!("waiting for service...");
|
|
||||||
while !node.service_available(&client)? {
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("service available.");
|
|
||||||
|
|
||||||
let mut pool = LocalPool::new();
|
let mut pool = LocalPool::new();
|
||||||
let spawner = pool.spawner();
|
let spawner = pool.spawner();
|
||||||
|
|
||||||
spawner.spawn_local(async move {
|
spawner.spawn_local(async move {
|
||||||
match requester_task(client).await {
|
match requester_task(service_available, client).await {
|
||||||
Ok(()) => println!("done."),
|
Ok(()) => println!("done."),
|
||||||
Err(e) => println!("error: {}", e),
|
Err(e) => println!("error: {}", e),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut timer = node.create_wall_timer(std::time::Duration::from_millis(250))?;
|
let mut timer = node.create_wall_timer(std::time::Duration::from_millis(250))?;
|
||||||
let mut timer2 = node.create_wall_timer(std::time::Duration::from_millis(2000))?;
|
let mut timer2 = node.create_wall_timer(std::time::Duration::from_millis(2000))?;
|
||||||
// wait for service to be available
|
// wait for service to be available
|
||||||
println!("waiting for service...");
|
let service_available = node.is_available(&client)?;
|
||||||
while !node.service_available(&client)? {
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
|
||||||
}
|
|
||||||
println!("service available.");
|
|
||||||
|
|
||||||
let mut pool = LocalPool::new();
|
let mut pool = LocalPool::new();
|
||||||
let spawner = pool.spawner();
|
let spawner = pool.spawner();
|
||||||
|
|
||||||
spawner.spawn_local(async move {
|
spawner.spawn_local(async move {
|
||||||
|
println!("waiting for delayed service...");
|
||||||
|
service_available.await.expect("could not await service");
|
||||||
|
println!("delayed service available.");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match service.next().await {
|
match service.next().await {
|
||||||
Some(req) => {
|
Some(req) => {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,16 @@
|
||||||
use futures::executor::LocalPool;
|
use futures::executor::LocalPool;
|
||||||
use futures::task::LocalSpawnExt;
|
use futures::task::LocalSpawnExt;
|
||||||
|
use futures::Future;
|
||||||
use r2r;
|
use r2r;
|
||||||
|
|
||||||
async fn requester_task(c: r2r::UntypedClient) -> Result<(), Box<dyn std::error::Error>> {
|
async fn requester_task(
|
||||||
|
node_available: impl Future<Output = r2r::Result<()>>,
|
||||||
|
c: r2r::UntypedClient,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut x: i64 = 0;
|
let mut x: i64 = 0;
|
||||||
|
println!("waiting for service...");
|
||||||
|
node_available.await?;
|
||||||
|
println!("service available.");
|
||||||
loop {
|
loop {
|
||||||
let json = format!("{{ \"a\": {}, \"b\": {} }}", 10 * x, x);
|
let json = format!("{{ \"a\": {}, \"b\": {} }}", 10 * x, x);
|
||||||
let req = serde_json::from_str(&json).unwrap();
|
let req = serde_json::from_str(&json).unwrap();
|
||||||
|
|
@ -24,19 +31,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let client =
|
let client =
|
||||||
node.create_client_untyped("/add_two_ints", "example_interfaces/srv/AddTwoInts")?;
|
node.create_client_untyped("/add_two_ints", "example_interfaces/srv/AddTwoInts")?;
|
||||||
|
|
||||||
// wait for service to be available
|
let service_available = node.is_available(&client)?;
|
||||||
println!("waiting for service...");
|
|
||||||
while !node.service_available_untyped(&client)? {
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("service available.");
|
|
||||||
|
|
||||||
let mut pool = LocalPool::new();
|
let mut pool = LocalPool::new();
|
||||||
let spawner = pool.spawner();
|
let spawner = pool.spawner();
|
||||||
|
|
||||||
spawner.spawn_local(async move {
|
spawner.spawn_local(async move {
|
||||||
match requester_task(client).await {
|
match requester_task(service_available, client).await {
|
||||||
Ok(()) => println!("done."),
|
Ok(()) => println!("done."),
|
||||||
Err(e) => println!("error: {}", e),
|
Err(e) => println!("error: {}", e),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -144,26 +144,6 @@ where
|
||||||
ActionClient { client }
|
ActionClient { client }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn action_server_available<T>(node: &rcl_node_t, client: &ActionClient<T>) -> Result<bool>
|
|
||||||
where
|
|
||||||
T: 'static + WrappedActionTypeSupport,
|
|
||||||
{
|
|
||||||
let client = client
|
|
||||||
.client
|
|
||||||
.upgrade()
|
|
||||||
.ok_or(Error::RCL_RET_CLIENT_INVALID)?;
|
|
||||||
let client = client.lock().unwrap();
|
|
||||||
let mut avail = false;
|
|
||||||
let result = unsafe { rcl_action_server_is_available(node, client.handle(), &mut avail) };
|
|
||||||
|
|
||||||
if result == RCL_RET_OK as i32 {
|
|
||||||
Ok(avail)
|
|
||||||
} else {
|
|
||||||
eprintln!("coult not send request {}", result);
|
|
||||||
Err(Error::from_rcl_error(result))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub enum GoalStatus {
|
pub enum GoalStatus {
|
||||||
Unknown,
|
Unknown,
|
||||||
|
|
@ -236,6 +216,8 @@ where
|
||||||
pub result_requests: Vec<(i64, uuid::Uuid)>,
|
pub result_requests: Vec<(i64, uuid::Uuid)>,
|
||||||
pub result_senders: Vec<(uuid::Uuid, oneshot::Sender<(GoalStatus, T::Result)>)>,
|
pub result_senders: Vec<(uuid::Uuid, oneshot::Sender<(GoalStatus, T::Result)>)>,
|
||||||
pub goal_status: HashMap<uuid::Uuid, GoalStatus>,
|
pub goal_status: HashMap<uuid::Uuid, GoalStatus>,
|
||||||
|
|
||||||
|
pub poll_available_channels: Vec<oneshot::Sender<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ActionClient_ {
|
pub trait ActionClient_ {
|
||||||
|
|
@ -249,6 +231,9 @@ pub trait ActionClient_ {
|
||||||
fn handle_result_response(&mut self) -> ();
|
fn handle_result_response(&mut self) -> ();
|
||||||
|
|
||||||
fn send_result_request(&mut self, uuid: uuid::Uuid) -> ();
|
fn send_result_request(&mut self, uuid: uuid::Uuid) -> ();
|
||||||
|
|
||||||
|
fn register_poll_available(&mut self, s: oneshot::Sender<()>) -> ();
|
||||||
|
fn poll_available(&mut self, node: &mut rcl_node_t) -> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
@ -515,6 +500,32 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn register_poll_available(&mut self, s: oneshot::Sender<()>) {
|
||||||
|
self.poll_available_channels.push(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_available(&mut self, node: &mut rcl_node_t) {
|
||||||
|
if self.poll_available_channels.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let available = action_server_available_helper(node, self.handle());
|
||||||
|
match available {
|
||||||
|
Ok(true) => {
|
||||||
|
// send ok and close channels
|
||||||
|
while let Some(sender) = self.poll_available_channels.pop() {
|
||||||
|
let _res = sender.send(()); // we ignore if receiver dropped.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(false) => {
|
||||||
|
// not available...
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
// error, close all channels
|
||||||
|
self.poll_available_channels.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn destroy(&mut self, node: &mut rcl_node_t) {
|
fn destroy(&mut self, node: &mut rcl_node_t) {
|
||||||
unsafe {
|
unsafe {
|
||||||
rcl_action_client_fini(&mut self.rcl_handle, node);
|
rcl_action_client_fini(&mut self.rcl_handle, node);
|
||||||
|
|
@ -572,3 +583,35 @@ pub fn action_client_get_num_waits(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use crate::nodes::IsAvailablePollable;
|
||||||
|
|
||||||
|
impl<T: 'static> IsAvailablePollable for ActionClient<T>
|
||||||
|
where
|
||||||
|
T: WrappedActionTypeSupport,
|
||||||
|
{
|
||||||
|
fn register_poll_available(&self, sender: oneshot::Sender<()>) -> Result<()> {
|
||||||
|
let client = self
|
||||||
|
.client
|
||||||
|
.upgrade()
|
||||||
|
.ok_or(Error::RCL_RET_ACTION_CLIENT_INVALID)?;
|
||||||
|
let mut client = client.lock().unwrap();
|
||||||
|
client.register_poll_available(sender);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn action_server_available_helper(
|
||||||
|
node: &rcl_node_t,
|
||||||
|
client: &rcl_action_client_t,
|
||||||
|
) -> Result<bool> {
|
||||||
|
let mut avail = false;
|
||||||
|
let result = unsafe { rcl_action_server_is_available(node, client, &mut avail) };
|
||||||
|
|
||||||
|
if result == RCL_RET_OK as i32 {
|
||||||
|
Ok(avail)
|
||||||
|
} else {
|
||||||
|
eprintln!("coult not check if action server is available {}", result);
|
||||||
|
Err(Error::from_rcl_error(result))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,8 @@ impl UntypedClient_ {
|
||||||
pub trait Client_ {
|
pub trait Client_ {
|
||||||
fn handle(&self) -> &rcl_client_t;
|
fn handle(&self) -> &rcl_client_t;
|
||||||
fn handle_response(&mut self) -> ();
|
fn handle_response(&mut self) -> ();
|
||||||
|
fn register_poll_available(&mut self, s: oneshot::Sender<()>) -> ();
|
||||||
|
fn poll_available(&mut self, node: &mut rcl_node_t) -> ();
|
||||||
fn destroy(&mut self, node: &mut rcl_node_t) -> ();
|
fn destroy(&mut self, node: &mut rcl_node_t) -> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,6 +120,7 @@ where
|
||||||
{
|
{
|
||||||
pub rcl_handle: rcl_client_t,
|
pub rcl_handle: rcl_client_t,
|
||||||
pub response_channels: Vec<(i64, oneshot::Sender<T::Response>)>,
|
pub response_channels: Vec<(i64, oneshot::Sender<T::Response>)>,
|
||||||
|
pub poll_available_channels: Vec<oneshot::Sender<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static> Client_ for TypedClient<T>
|
impl<T: 'static> Client_ for TypedClient<T>
|
||||||
|
|
@ -169,6 +172,32 @@ where
|
||||||
} // TODO handle failure.
|
} // TODO handle failure.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn register_poll_available(&mut self, s: oneshot::Sender<()>) {
|
||||||
|
self.poll_available_channels.push(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_available(&mut self, node: &mut rcl_node_t) {
|
||||||
|
if self.poll_available_channels.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let available = service_available_helper(node, self.handle());
|
||||||
|
match available {
|
||||||
|
Ok(true) => {
|
||||||
|
// send ok and close channels
|
||||||
|
while let Some(sender) = self.poll_available_channels.pop() {
|
||||||
|
let _res = sender.send(()); // we ignore if receiver dropped.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(false) => {
|
||||||
|
// not available...
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
// error, close all channels
|
||||||
|
self.poll_available_channels.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn destroy(&mut self, node: &mut rcl_node_t) {
|
fn destroy(&mut self, node: &mut rcl_node_t) {
|
||||||
unsafe {
|
unsafe {
|
||||||
rcl_client_fini(&mut self.rcl_handle, node);
|
rcl_client_fini(&mut self.rcl_handle, node);
|
||||||
|
|
@ -180,6 +209,7 @@ pub struct UntypedClient_ {
|
||||||
pub service_type: UntypedServiceSupport,
|
pub service_type: UntypedServiceSupport,
|
||||||
pub rcl_handle: rcl_client_t,
|
pub rcl_handle: rcl_client_t,
|
||||||
pub response_channels: Vec<(i64, oneshot::Sender<Result<serde_json::Value>>)>,
|
pub response_channels: Vec<(i64, oneshot::Sender<Result<serde_json::Value>>)>,
|
||||||
|
pub poll_available_channels: Vec<oneshot::Sender<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client_ for UntypedClient_ {
|
impl Client_ for UntypedClient_ {
|
||||||
|
|
@ -228,6 +258,32 @@ impl Client_ for UntypedClient_ {
|
||||||
} // TODO handle failure.
|
} // TODO handle failure.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn register_poll_available(&mut self, s: oneshot::Sender<()>) {
|
||||||
|
self.poll_available_channels.push(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_available(&mut self, node: &mut rcl_node_t) {
|
||||||
|
if self.poll_available_channels.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let available = service_available_helper(node, self.handle());
|
||||||
|
match available {
|
||||||
|
Ok(true) => {
|
||||||
|
// send ok and close channels
|
||||||
|
while let Some(sender) = self.poll_available_channels.pop() {
|
||||||
|
let _res = sender.send(()); // we ignore if receiver dropped.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(false) => {
|
||||||
|
// not available...
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
// error, close all channels
|
||||||
|
self.poll_available_channels.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn destroy(&mut self, node: &mut rcl_node_t) {
|
fn destroy(&mut self, node: &mut rcl_node_t) {
|
||||||
unsafe {
|
unsafe {
|
||||||
rcl_client_fini(&mut self.rcl_handle, node);
|
rcl_client_fini(&mut self.rcl_handle, node);
|
||||||
|
|
@ -272,23 +328,25 @@ pub fn service_available_helper(node: &mut rcl_node_t, client: &rcl_client_t) ->
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn service_available<T: 'static + WrappedServiceTypeSupport>(
|
use crate::nodes::IsAvailablePollable;
|
||||||
node: &mut rcl_node_t,
|
|
||||||
client: &Client<T>,
|
impl<T: 'static> IsAvailablePollable for Client<T>
|
||||||
) -> Result<bool> {
|
where
|
||||||
let client = client
|
T: WrappedServiceTypeSupport,
|
||||||
.client
|
{
|
||||||
.upgrade()
|
fn register_poll_available(&self, sender: oneshot::Sender<()>) -> Result<()> {
|
||||||
.ok_or(Error::RCL_RET_CLIENT_INVALID)?;
|
let client = self.client.upgrade().ok_or(Error::RCL_RET_CLIENT_INVALID)?;
|
||||||
let client = client.lock().unwrap();
|
let mut client = client.lock().unwrap();
|
||||||
service_available_helper(node, client.handle())
|
client.register_poll_available(sender);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn service_available_untyped(node: &mut rcl_node_t, client: &UntypedClient) -> Result<bool> {
|
impl IsAvailablePollable for UntypedClient {
|
||||||
let client = client
|
fn register_poll_available(&self, sender: oneshot::Sender<()>) -> Result<()> {
|
||||||
.client
|
let client = self.client.upgrade().ok_or(Error::RCL_RET_CLIENT_INVALID)?;
|
||||||
.upgrade()
|
let mut client = client.lock().unwrap();
|
||||||
.ok_or(Error::RCL_RET_CLIENT_INVALID)?;
|
client.register_poll_available(sender);
|
||||||
let client = client.lock().unwrap();
|
Ok(())
|
||||||
service_available_helper(node, client.handle())
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
src/nodes.rs
42
src/nodes.rs
|
|
@ -243,6 +243,7 @@ impl Node {
|
||||||
let ws = TypedClient::<T> {
|
let ws = TypedClient::<T> {
|
||||||
rcl_handle: client_handle,
|
rcl_handle: client_handle,
|
||||||
response_channels: Vec::new(),
|
response_channels: Vec::new(),
|
||||||
|
poll_available_channels: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let client_arc = Arc::new(Mutex::new(ws));
|
let client_arc = Arc::new(Mutex::new(ws));
|
||||||
|
|
@ -264,6 +265,7 @@ impl Node {
|
||||||
service_type,
|
service_type,
|
||||||
rcl_handle: client_handle,
|
rcl_handle: client_handle,
|
||||||
response_channels: Vec::new(),
|
response_channels: Vec::new(),
|
||||||
|
poll_available_channels: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let client_arc = Arc::new(Mutex::new(client));
|
let client_arc = Arc::new(Mutex::new(client));
|
||||||
|
|
@ -272,15 +274,13 @@ impl Node {
|
||||||
Ok(c)
|
Ok(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn service_available<T: 'static + WrappedServiceTypeSupport>(
|
pub fn is_available(
|
||||||
&mut self,
|
&mut self,
|
||||||
client: &Client<T>,
|
client: &dyn IsAvailablePollable,
|
||||||
) -> Result<bool> {
|
) -> Result<impl Future<Output = Result<()>>> {
|
||||||
service_available(self.node_handle.as_mut(), client)
|
let (sender, receiver) = oneshot::channel();
|
||||||
}
|
client.register_poll_available(sender)?;
|
||||||
|
Ok(receiver.map_err(|_| Error::RCL_RET_CLIENT_INVALID))
|
||||||
pub fn service_available_untyped(&mut self, client: &UntypedClient) -> Result<bool> {
|
|
||||||
service_available_untyped(self.node_handle.as_mut(), client)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_action_client<T: 'static>(&mut self, action_name: &str) -> Result<ActionClient<T>>
|
pub fn create_action_client<T: 'static>(&mut self, action_name: &str) -> Result<ActionClient<T>>
|
||||||
|
|
@ -297,6 +297,7 @@ impl Node {
|
||||||
result_senders: Vec::new(),
|
result_senders: Vec::new(),
|
||||||
result_requests: Vec::new(),
|
result_requests: Vec::new(),
|
||||||
goal_status: HashMap::new(),
|
goal_status: HashMap::new(),
|
||||||
|
poll_available_channels: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let client_arc = Arc::new(Mutex::new(client));
|
let client_arc = Arc::new(Mutex::new(client));
|
||||||
|
|
@ -305,13 +306,6 @@ impl Node {
|
||||||
Ok(c)
|
Ok(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn action_server_available<T: 'static + WrappedActionTypeSupport>(
|
|
||||||
&self,
|
|
||||||
client: &ActionClient<T>,
|
|
||||||
) -> Result<bool> {
|
|
||||||
action_server_available(self.node_handle.as_ref(), client)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_action_server<T: 'static>(
|
pub fn create_action_server<T: 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
action_name: &str,
|
action_name: &str,
|
||||||
|
|
@ -388,6 +382,15 @@ impl Node {
|
||||||
a.lock().unwrap().send_completed_cancel_requests();
|
a.lock().unwrap().send_completed_cancel_requests();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// as well as polling any services/action servers for availability
|
||||||
|
for c in &mut self.clients {
|
||||||
|
c.lock().unwrap().poll_available(self.node_handle.as_mut());
|
||||||
|
}
|
||||||
|
|
||||||
|
for c in &mut self.action_clients {
|
||||||
|
c.lock().unwrap().poll_available(self.node_handle.as_mut());
|
||||||
|
}
|
||||||
|
|
||||||
let timeout = timeout.as_nanos() as i64;
|
let timeout = timeout.as_nanos() as i64;
|
||||||
let mut ws = unsafe { rcl_get_zero_initialized_wait_set() };
|
let mut ws = unsafe { rcl_get_zero_initialized_wait_set() };
|
||||||
|
|
||||||
|
|
@ -815,10 +818,7 @@ impl Timer {
|
||||||
// wait until there are no other owners in the cleanup procedure. The
|
// wait until there are no other owners in the cleanup procedure. The
|
||||||
// next time a publisher wants to publish they will fail because the
|
// next time a publisher wants to publish they will fail because the
|
||||||
// value in the Arc has been dropped. Hacky but works.
|
// value in the Arc has been dropped. Hacky but works.
|
||||||
fn wait_until_unwrapped<T>(mut a: Arc<T>) -> T
|
fn wait_until_unwrapped<T>(mut a: Arc<T>) -> T {
|
||||||
where
|
|
||||||
T: std::fmt::Debug,
|
|
||||||
{
|
|
||||||
loop {
|
loop {
|
||||||
match Arc::try_unwrap(a) {
|
match Arc::try_unwrap(a) {
|
||||||
Ok(b) => return b,
|
Ok(b) => return b,
|
||||||
|
|
@ -860,3 +860,7 @@ impl Drop for Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait IsAvailablePollable {
|
||||||
|
fn register_poll_available(&self, sender: oneshot::Sender<()>) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue