arci_ros/
ros_robot_client.rs
1use std::sync::{Arc, Mutex};
2
3use arci::*;
4
5use crate::msg;
6
7#[derive(Clone)]
8pub struct RosRobotClient(Arc<RosRobotClientInner>);
9
10struct RosRobotClientInner {
11 joint_names: Vec<String>,
12 trajectory_publisher: Option<rosrust::Publisher<msg::trajectory_msgs::JointTrajectory>>,
13 _joint_state_subscriber: rosrust::Subscriber,
14 joint_state_message: Arc<Mutex<msg::sensor_msgs::JointState>>,
15 complete_condition: Mutex<Arc<dyn CompleteCondition>>,
16}
17
18impl From<TrajectoryPoint> for msg::trajectory_msgs::JointTrajectoryPoint {
19 fn from(tp: TrajectoryPoint) -> Self {
20 let mut message = msg::trajectory_msgs::JointTrajectoryPoint {
21 positions: tp.positions,
22 ..Default::default()
23 };
24 message.time_from_start.sec = tp.time_from_start.as_secs() as i32;
25 message.time_from_start.nsec = tp.time_from_start.subsec_nanos() as i32;
26 message
27 }
28}
29
30impl RosRobotClient {
31 pub fn new(
32 joint_names: Vec<String>,
33 joint_state_topic_name: &str,
34 trajectory_topic_name: &str,
35 ) -> Self {
36 let joint_state_message = Arc::new(Mutex::new(msg::sensor_msgs::JointState::default()));
37 let joint_state_message_for_sub = joint_state_message.clone();
38 let _joint_state_subscriber = rosrust::subscribe(
39 joint_state_topic_name,
40 1,
41 move |joint_state: msg::sensor_msgs::JointState| {
42 let mut aaa = joint_state_message_for_sub.lock().unwrap();
43 *aaa = joint_state;
44 },
45 )
46 .unwrap();
47 while joint_state_message.lock().unwrap().name.is_empty() {
48 rosrust::ros_info!("waiting joint state publisher");
49 std::thread::sleep(std::time::Duration::from_millis(100));
50 }
51
52 let trajectory_publisher = if trajectory_topic_name.is_empty() {
53 None
54 } else {
55 let publisher = rosrust::publish(trajectory_topic_name, 1).unwrap();
56
57 let rate = rosrust::rate(10.0);
58 while rosrust::is_ok() && publisher.subscriber_count() == 0 {
59 rosrust::ros_info!("waiting trajectory subscriber");
60 rate.sleep();
61 }
62 Some(publisher)
63 };
64
65 Self(Arc::new(RosRobotClientInner {
66 joint_names,
67 trajectory_publisher,
68 _joint_state_subscriber,
69 joint_state_message,
70 complete_condition: Mutex::new(Arc::new(TotalJointDiffCondition::default())),
71 }))
72 }
73}
74
75impl JointTrajectoryClient for RosRobotClient {
76 fn joint_names(&self) -> Vec<String> {
77 self.0.joint_names.clone()
78 }
79
80 fn current_joint_positions(&self) -> Result<Vec<f64>, Error> {
81 let message = self.0.joint_state_message.lock().unwrap();
82 Ok(message.position.clone())
83 }
84
85 fn send_joint_positions(
86 &self,
87 positions: Vec<f64>,
88 duration: std::time::Duration,
89 ) -> Result<WaitFuture, Error> {
90 if let Some(ref publisher) = self.0.trajectory_publisher {
91 if self.0.joint_names.len() != positions.len() {
92 return Err(arci::Error::LengthMismatch {
93 model: self.0.joint_names.len(),
94 input: positions.len(),
95 });
96 }
97 let point = msg::trajectory_msgs::JointTrajectoryPoint {
98 positions: positions.to_vec(),
99 time_from_start: rosrust::Duration::from_nanos(duration.as_nanos() as i64),
100 ..Default::default()
101 };
102 let traj = msg::trajectory_msgs::JointTrajectory {
103 joint_names: self.0.joint_names.clone(),
104 points: vec![point],
105 ..Default::default()
106 };
107 publisher.send(traj).unwrap();
108 let this = self.clone();
109 Ok(WaitFuture::new(async move {
110 let complete_condition = this.0.complete_condition.lock().unwrap().clone();
112 complete_condition
113 .wait(&this, &positions, duration.as_secs_f64())
114 .await
115 }))
116 } else {
117 Ok(WaitFuture::ready())
118 }
119 }
120
121 fn send_joint_trajectory(&self, trajectory: Vec<TrajectoryPoint>) -> Result<WaitFuture, Error> {
122 if let Some(ref publisher) = self.0.trajectory_publisher {
123 let traj = msg::trajectory_msgs::JointTrajectory {
124 joint_names: self.0.joint_names.clone(),
125 points: trajectory.iter().map(|t| (*t).clone().into()).collect(),
126 ..Default::default()
127 };
128 publisher.send(traj).unwrap();
129 let this = self.clone();
130 Ok(WaitFuture::new(async move {
131 let complete_condition = this.0.complete_condition.lock().unwrap().clone();
133 complete_condition
134 .wait(
135 &this,
136 &trajectory.last().unwrap().positions,
137 trajectory.last().unwrap().time_from_start.as_secs_f64(),
138 )
139 .await
140 }))
141 } else {
142 Ok(WaitFuture::ready())
143 }
144 }
145}
146
147impl SetCompleteCondition for RosRobotClient {
148 fn set_complete_condition(&mut self, condition: Box<dyn CompleteCondition>) {
149 *self.0.complete_condition.lock().unwrap() = condition.into();
150 }
151}