arci_ros2/
ros2_transform_resolver.rs1use std::time::Duration;
2
3use arci::{
4 nalgebra::{Quaternion, Translation3},
5 Isometry3, TransformResolver, UnitQuaternion,
6};
7use r2r::builtin_interfaces::msg as builtin_msg;
8use tf_r2r::{TfBuffer, TfListener};
9use tracing::{debug, warn};
10
11use crate::{utils::convert_system_time_to_ros2_time, Node};
12
13pub struct Ros2TransformResolver {
15 retry_rate: f64,
16 max_retry: usize,
17 tf_listener: TfListener,
18 _node: Node,
20}
21
22impl Ros2TransformResolver {
23 #[track_caller]
25 pub fn new(node: Node, cache_duration: Duration, retry_rate: f64, max_retry: usize) -> Self {
26 let duration = builtin_msg::Duration {
27 sec: cache_duration.as_secs() as i32,
28 nanosec: cache_duration.subsec_nanos(),
29 };
30
31 let tf_listener =
32 TfListener::new_with_buffer(&mut node.r2r(), TfBuffer::new_with_duration(duration));
33 Self {
34 retry_rate,
35 max_retry,
36 tf_listener,
37 _node: node,
38 }
39 }
40}
41
42impl TransformResolver for Ros2TransformResolver {
43 fn resolve_transformation(
44 &self,
45 from: &str,
46 to: &str,
47 time: std::time::SystemTime,
48 ) -> Result<Isometry3<f64>, arci::Error> {
49 const BILLION: u128 = 1_000_000_000;
50
51 let ros_time = convert_system_time_to_ros2_time(&time);
52 let wait_nanos = BILLION as u64 / self.retry_rate as u64;
53
54 let mut last_error = None;
55
56 for i in 0..=self.max_retry {
57 if i != 0 {
58 debug!("Retrying {from} -> {to} ({i} / {}) ...", self.max_retry);
59 }
60 let result = self
61 .tf_listener
62 .lookup_transform(from, to, ros_time.clone());
63 match result {
64 Ok(result) => {
65 let translation = result.transform.translation;
66 let rotation = result.transform.rotation;
67
68 return Ok(Isometry3::from_parts(
69 Translation3::new(translation.x, translation.y, translation.z),
70 UnitQuaternion::from_quaternion(Quaternion::new(
71 rotation.w, rotation.x, rotation.y, rotation.z,
72 )),
73 ));
74 }
75 Err(e) => {
76 debug!("Failed to lookup_transform ({e:?})");
77 last_error = Some(e)
78 }
79 }
80 std::thread::sleep(Duration::from_nanos(wait_nanos));
81 }
82 match last_error {
83 Some(e) => {
84 warn!("{e:?}");
85 Err(anyhow::anyhow!("{e:?}").into())
86 }
87 None => Err(anyhow::anyhow!("Broken Logic").into()),
88 }
89 }
90}