use ros_core_rs::core::MasterClient; use std::thread; use tokio::select; use url::Url; const ROS_MASTER_URI: &str = "http://0.0.0.0:11311"; const TOPIC_NAME: &str = "/chatter"; #[tokio::main] async fn main() -> anyhow::Result<()> { env_logger::init(); // Spawn a Tokio task to run the ROS master let core_cancel = tokio_util::sync::CancellationToken::new(); let t_core = tokio::spawn({ let core_cancel = core_cancel.clone(); async move { let uri = Url::parse(ROS_MASTER_URI).unwrap(); let socket_address = ros_core_rs::url_to_socket_addr(&uri)?; let master = ros_core_rs::core::Master::new(&socket_address); select! { serve = master.serve() => { serve }, _ = core_cancel.cancelled() => { Ok(()) } } } }); // Initialize the ROS node rosrust::loop_init("talker_listener", 1000); // Spawn a Tokio task to publish messages let t_talker = tokio::task::spawn_blocking(move || { // Create publisher let chatter_pub = rosrust::publish(TOPIC_NAME, 100).unwrap(); let mut count = 0; // Create object that maintains 10Hz between sleep requests let rate = rosrust::rate(10.0); // Breaks when a shutdown signal is sent while rosrust::is_ok() { // Create string message let mut msg = rosrust_msg::std_msgs::String::default(); msg.data = format!("hello world {}", count); log::info!("I wrote {}", msg.data); // Send string message to topic via publisher chatter_pub.send(msg).unwrap(); // Sleep to maintain 10Hz rate rate.sleep(); count += 1; } }); // Wait for the publisher to be available let master_url = Url::parse(ROS_MASTER_URI).expect("Failed to parse URL."); let master_client = MasterClient::new(&master_url); loop { let (_, _, published_topics) = master_client.get_published_topics("", "").await.unwrap(); if published_topics .iter() .any(|(topic_name, _)| topic_name == TOPIC_NAME) { break; } thread::sleep(std::time::Duration::from_millis(1000)); } // Spawn a Tokio task to subscribe to messages let t_listener = tokio::task::spawn_blocking(move || { // Create subscriber // The subscriber is stopped when the returned object is destroyed let mut _subscriber_info; loop { _subscriber_info = rosrust::subscribe(TOPIC_NAME, 2, |v: rosrust_msg::std_msgs::String| { // Callback for handling received messages log::info!("I heard {}", v.data); }); if _subscriber_info.is_ok() { break; } log::info!("publisher not found. Will retry until it becomes available..."); thread::sleep(std::time::Duration::from_millis(1000)); } log::info!("We successfully subscribes to the publisher"); // Block the thread until a shutdown signal is received rosrust::spin(); }); tokio::signal::ctrl_c().await?; // Wind down clients rosrust::shutdown(); let (_r1, _r2) = tokio::join!(t_talker, t_listener); // Wind down core core_cancel.cancel(); let _r3 = tokio::join!(t_core); Ok(()) }