You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

node.rs 12 kB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. use std::ffi::CString;
  2. use std::sync::{Arc, Mutex, Weak};
  3. use std::time::Duration;
  4. use anyhow::{ensure, Context as _, Result};
  5. use rclrust_msg::_core::{FFIToRust, MessageT, ServiceT};
  6. use crate::clock::ClockType;
  7. use crate::context::{Context, RclContext};
  8. use crate::error::ToRclRustResult;
  9. use crate::internal::ffi::*;
  10. use crate::log::Logger;
  11. use crate::node_options::NodeOptions;
  12. use crate::publisher::Publisher;
  13. use crate::qos::QoSProfile;
  14. use crate::rclrust_error;
  15. use crate::service::{Service, ServiceBase};
  16. use crate::subscription::{Subscription, SubscriptionBase};
  17. use crate::timer::Timer;
  18. use crate::wait_set::RclWaitSet;
  19. #[derive(Debug)]
  20. pub(crate) struct RclNode(rcl_sys::rcl_node_t);
  21. unsafe impl Send for RclNode {}
  22. impl RclNode {
  23. fn new(
  24. context: &mut RclContext,
  25. name: &str,
  26. namespace: Option<&str>,
  27. options: &NodeOptions,
  28. ) -> Result<Self> {
  29. let mut node = unsafe { rcl_sys::rcl_get_zero_initialized_node() };
  30. let name_c_str = CString::new(name)?;
  31. let namespace_c_str = CString::new(namespace.unwrap_or_default())?;
  32. unsafe {
  33. rcl_sys::rcl_node_init(
  34. &mut node,
  35. name_c_str.as_ptr(),
  36. namespace_c_str.as_ptr(),
  37. context.raw_mut(),
  38. options.raw(),
  39. )
  40. .to_result()
  41. .with_context(|| "rcl_sys::rcl_node_init in RclNode::new")?;
  42. }
  43. Ok(Self(node))
  44. }
  45. pub(crate) const fn raw(&self) -> &rcl_sys::rcl_node_t {
  46. &self.0
  47. }
  48. pub(crate) unsafe fn raw_mut(&mut self) -> &mut rcl_sys::rcl_node_t {
  49. &mut self.0
  50. }
  51. fn is_valid(&self) -> bool {
  52. unsafe { rcl_sys::rcl_node_is_valid(&self.0) }
  53. }
  54. fn name(&self) -> String {
  55. unsafe {
  56. let name = rcl_sys::rcl_node_get_name(&self.0);
  57. String::from_c_char(name).unwrap()
  58. }
  59. }
  60. fn namespace(&self) -> String {
  61. unsafe {
  62. let namespace = rcl_sys::rcl_node_get_namespace(&self.0);
  63. String::from_c_char(namespace).unwrap()
  64. }
  65. }
  66. fn fully_qualified_name(&self) -> String {
  67. unsafe {
  68. let name = rcl_sys::rcl_node_get_fully_qualified_name(&self.0);
  69. String::from_c_char(name).unwrap()
  70. }
  71. }
  72. fn logger_name(&self) -> String {
  73. unsafe {
  74. let logger_name = rcl_sys::rcl_node_get_logger_name(&self.0);
  75. String::from_c_char(logger_name).unwrap()
  76. }
  77. }
  78. unsafe fn fini(&mut self, _ctx: &RclContext) -> Result<()> {
  79. rcl_sys::rcl_node_fini(&mut self.0)
  80. .to_result()
  81. .with_context(|| "rcl_sys::rcl_node_fini in RclNode::fini")
  82. }
  83. }
  84. pub struct Node<'ctx> {
  85. handle: Arc<Mutex<RclNode>>,
  86. context: &'ctx Context,
  87. pub(crate) subscriptions: Mutex<Vec<Weak<dyn SubscriptionBase>>>,
  88. pub(crate) timers: Mutex<Vec<Weak<Timer>>>,
  89. pub(crate) services: Mutex<Vec<Weak<dyn ServiceBase>>>,
  90. }
  91. impl<'ctx> Node<'ctx> {
  92. pub(crate) fn new(
  93. context: &'ctx Context,
  94. name: &str,
  95. namespace: Option<&str>,
  96. options: &NodeOptions,
  97. ) -> Result<Arc<Self>> {
  98. ensure!(context.is_valid(), "given Context is not valid");
  99. let handle = {
  100. RclNode::new(
  101. &mut context.handle().lock().unwrap(),
  102. name,
  103. namespace,
  104. options,
  105. )?
  106. };
  107. Ok(Arc::new(Self {
  108. handle: Arc::new(Mutex::new(handle)),
  109. context,
  110. subscriptions: Mutex::new(Vec::new()),
  111. timers: Mutex::new(Vec::new()),
  112. services: Mutex::new(Vec::new()),
  113. }))
  114. }
  115. pub(crate) fn clone_handle(&self) -> Arc<Mutex<RclNode>> {
  116. Arc::clone(&self.handle)
  117. }
  118. pub(crate) const fn context_ref(&self) -> &'ctx Context {
  119. self.context
  120. }
  121. /// # Examples
  122. ///
  123. /// ```
  124. /// let ctx = rclrust::init().unwrap();
  125. /// let node = ctx.create_node("node1").unwrap();
  126. /// assert!(node.is_valid())
  127. /// ```
  128. pub fn is_valid(&self) -> bool {
  129. self.handle.lock().unwrap().is_valid()
  130. }
  131. /// # Examples
  132. ///
  133. /// ```
  134. /// let ctx = rclrust::init().unwrap();
  135. /// let node = ctx.create_node("node1").unwrap();
  136. /// assert_eq!(&node.name(), "node1");
  137. /// ```
  138. pub fn name(&self) -> String {
  139. self.handle.lock().unwrap().name()
  140. }
  141. /// # Examples
  142. ///
  143. /// ```
  144. /// let ctx = rclrust::init().unwrap();
  145. /// let node = ctx.create_node_with_ns("node1", "ns").unwrap();
  146. /// assert_eq!(&node.namespace(), "/ns");
  147. ///
  148. /// let node = ctx.create_node("node1").unwrap();
  149. /// assert_eq!(&node.namespace(), "/");
  150. /// ```
  151. pub fn namespace(&self) -> String {
  152. self.handle.lock().unwrap().namespace()
  153. }
  154. /// # Examples
  155. ///
  156. /// ```
  157. /// let ctx = rclrust::init().unwrap();
  158. /// let node = ctx.create_node_with_ns("node1", "ns").unwrap();
  159. /// assert_eq!(&node.fully_qualified_name(), "/ns/node1");
  160. /// ```
  161. pub fn fully_qualified_name(&self) -> String {
  162. self.handle.lock().unwrap().fully_qualified_name()
  163. }
  164. /// # Examples
  165. ///
  166. /// ```
  167. /// let ctx = rclrust::init().unwrap();
  168. /// let node = ctx.create_node_with_ns("node1", "ns").unwrap();
  169. /// let logger = node.logger();
  170. /// ```
  171. pub fn logger(&self) -> Logger {
  172. Logger::new(&self.logger_name())
  173. }
  174. /// # Examples
  175. ///
  176. /// ```
  177. /// let ctx = rclrust::init().unwrap();
  178. /// let node = ctx.create_node_with_ns("node1", "ns").unwrap();
  179. /// assert_eq!(&node.logger_name(), "ns.node1");
  180. /// ```
  181. pub fn logger_name(&self) -> String {
  182. self.handle.lock().unwrap().logger_name()
  183. }
  184. pub fn create_publisher<T>(&self, topic_name: &str, qos: &QoSProfile) -> Result<Publisher<T>>
  185. where
  186. T: MessageT,
  187. {
  188. Publisher::new(self, topic_name, qos)
  189. }
  190. pub fn create_subscription<T, F>(
  191. &self,
  192. topic_name: &str,
  193. callback: F,
  194. qos: &QoSProfile,
  195. ) -> Result<Arc<Subscription<T>>>
  196. where
  197. T: MessageT + 'static,
  198. F: Fn(T) + 'static,
  199. {
  200. let sub = Subscription::new(
  201. self,
  202. topic_name,
  203. move |msg| callback(unsafe { T::from_raw(msg) }),
  204. qos,
  205. )?;
  206. let weak_sub = Arc::downgrade(&sub) as Weak<dyn SubscriptionBase>;
  207. self.subscriptions.lock().unwrap().push(weak_sub);
  208. Ok(sub)
  209. }
  210. pub fn create_raw_subscription<T, F>(
  211. &self,
  212. topic_name: &str,
  213. callback: F,
  214. qos: &QoSProfile,
  215. ) -> Result<Arc<Subscription<T>>>
  216. where
  217. T: MessageT + 'static,
  218. F: Fn(&T::Raw) + 'static,
  219. {
  220. let sub = Subscription::new(self, topic_name, callback, qos)?;
  221. let weak_sub = Arc::downgrade(&sub) as Weak<dyn SubscriptionBase>;
  222. self.subscriptions.lock().unwrap().push(weak_sub);
  223. Ok(sub)
  224. }
  225. pub fn create_timer<F>(
  226. &self,
  227. period: Duration,
  228. clock_type: ClockType,
  229. callback: F,
  230. ) -> Result<Arc<Timer>>
  231. where
  232. F: Fn() + 'static,
  233. {
  234. let timer = Timer::new(self, period, clock_type, callback)?;
  235. let weak_timer = Arc::downgrade(&timer);
  236. self.timers.lock().unwrap().push(weak_timer);
  237. Ok(timer)
  238. }
  239. pub fn create_wall_timer<F>(&self, period: Duration, callback: F) -> Result<Arc<Timer>>
  240. where
  241. F: Fn() + 'static,
  242. {
  243. self.create_timer(period, ClockType::SteadyTime, callback)
  244. }
  245. pub fn create_service<Srv, F>(
  246. &self,
  247. service_name: &str,
  248. callback: F,
  249. qos: &QoSProfile,
  250. ) -> Result<Arc<Service<Srv>>>
  251. where
  252. Srv: ServiceT + 'static,
  253. F: Fn(Srv::Request) -> Srv::Response + 'static,
  254. {
  255. let srv = Service::<Srv>::new(
  256. self,
  257. service_name,
  258. move |req_raw| (callback)(unsafe { req_raw.to_rust() }),
  259. qos,
  260. )?;
  261. let weak_srv = Arc::downgrade(&srv) as Weak<dyn ServiceBase>;
  262. self.services.lock().unwrap().push(weak_srv);
  263. Ok(srv)
  264. }
  265. pub fn create_raw_service<Srv, F>(
  266. &self,
  267. service_name: &str,
  268. callback: F,
  269. qos: &QoSProfile,
  270. ) -> Result<Arc<Service<Srv>>>
  271. where
  272. Srv: ServiceT + 'static,
  273. F: Fn(&<Srv::Request as MessageT>::Raw) -> Srv::Response + 'static,
  274. {
  275. let srv = Service::new(self, service_name, callback, qos)?;
  276. let weak_srv = Arc::downgrade(&srv) as Weak<dyn ServiceBase>;
  277. self.services.lock().unwrap().push(weak_srv);
  278. Ok(srv)
  279. }
  280. pub(crate) fn add_to_wait_set(&self, wait_set: &mut RclWaitSet) -> Result<()> {
  281. for subscription in self.subscriptions.lock().unwrap().iter() {
  282. if let Some(subscription) = subscription.upgrade() {
  283. wait_set.add_subscription(subscription.handle())?;
  284. }
  285. }
  286. for timer in self.timers.lock().unwrap().iter() {
  287. if let Some(timer) = timer.upgrade() {
  288. wait_set.add_timer(&timer.handle().lock().unwrap())?;
  289. }
  290. }
  291. for service in self.services.lock().unwrap().iter() {
  292. if let Some(service) = service.upgrade() {
  293. wait_set.add_service(service.handle())?;
  294. }
  295. }
  296. Ok(())
  297. }
  298. pub(crate) fn call_callbacks(&self) -> Result<()> {
  299. for subscription in self.subscriptions.lock().unwrap().iter() {
  300. if let Some(subscription) = subscription.upgrade() {
  301. subscription.call_callback()?;
  302. }
  303. }
  304. for timer in self.timers.lock().unwrap().iter() {
  305. if let Some(timer) = timer.upgrade() {
  306. timer.call_callback()?;
  307. }
  308. }
  309. for service in self.services.lock().unwrap().iter() {
  310. if let Some(service) = service.upgrade() {
  311. service.call_callback()?;
  312. }
  313. }
  314. Ok(())
  315. }
  316. }
  317. impl Drop for Node<'_> {
  318. fn drop(&mut self) {
  319. if let Err(e) = unsafe {
  320. self.handle
  321. .lock()
  322. .unwrap()
  323. .fini(&self.context.handle().lock().unwrap())
  324. } {
  325. rclrust_error!(
  326. Logger::new("rclrust"),
  327. "Failed to clean up rcl node handle: {}",
  328. e
  329. )
  330. }
  331. }
  332. }
  333. #[cfg(test)]
  334. mod test {
  335. use super::*;
  336. #[test]
  337. fn node_init() -> Result<()> {
  338. let ctx = crate::init()?;
  339. let node = ctx.create_node("test_node")?;
  340. assert!(node.is_valid());
  341. Ok(())
  342. }
  343. #[test]
  344. fn node_name_without_namespace() -> Result<()> {
  345. let ctx = crate::init()?;
  346. let node = ctx.create_node("test_node")?;
  347. assert_eq!(node.name(), "test_node");
  348. assert_eq!(node.namespace(), "/");
  349. assert_eq!(node.fully_qualified_name(), "/test_node");
  350. assert_eq!(node.logger_name(), "test_node");
  351. Ok(())
  352. }
  353. #[test]
  354. fn node_name_with_namespace() -> Result<()> {
  355. let ctx = crate::init()?;
  356. let node = ctx.create_node_with_ns("test_node", "ns1")?;
  357. assert_eq!(node.name(), "test_node");
  358. assert_eq!(node.namespace(), "/ns1");
  359. assert_eq!(node.fully_qualified_name(), "/ns1/test_node");
  360. assert_eq!(node.logger_name(), "ns1.test_node");
  361. Ok(())
  362. }
  363. #[test]
  364. fn node_logger() -> Result<()> {
  365. let ctx = crate::init()?;
  366. let node = ctx.create_node_with_ns("test_node", "ns1")?;
  367. crate::rclrust_debug!(node.logger(), "logging {}{}{}", 21, "abc", 20.);
  368. Ok(())
  369. }
  370. }

DORA (Dataflow-Oriented Robotic Architecture) is middleware designed to streamline and simplify the creation of AI-based robotic applications. It offers low latency, composable, and distributed datafl

Contributors (1)