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.

main.rs 4.9 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. use dora_node_api::{
  2. self,
  3. dora_core::config::DataId,
  4. merged::{MergeExternal, MergedEvent},
  5. DoraNode, Event,
  6. };
  7. use dora_ros2_bridge::{
  8. messages::{
  9. geometry_msgs::msg::{Twist, Vector3},
  10. turtlesim::msg::Pose,
  11. },
  12. ros2_client::{self, ros2, NodeOptions},
  13. rustdds::{self, policy},
  14. };
  15. use eyre::{eyre, Context};
  16. fn main() -> eyre::Result<()> {
  17. let mut ros_node = init_ros_node()?;
  18. let turtle_vel_publisher = create_vel_publisher(&mut ros_node)?;
  19. let turtle_pose_reader = create_pose_reader(&mut ros_node)?;
  20. let output = DataId::from("pose".to_owned());
  21. let (mut node, dora_events) = DoraNode::init_from_env()?;
  22. let merged = dora_events.merge_external(Box::pin(turtle_pose_reader.async_stream()));
  23. let mut events = futures::executor::block_on_stream(merged);
  24. for i in 0..1000 {
  25. let event = match events.next() {
  26. Some(input) => input,
  27. None => break,
  28. };
  29. match event {
  30. MergedEvent::Dora(event) => match event {
  31. Event::Input {
  32. id,
  33. metadata: _,
  34. data: _,
  35. } => match id.as_str() {
  36. "tick" => {
  37. let direction = Twist {
  38. linear: Vector3 {
  39. x: rand::random::<f64>() + 1.0,
  40. ..Default::default()
  41. },
  42. angular: Vector3 {
  43. z: (rand::random::<f64>() - 0.5) * 5.0,
  44. ..Default::default()
  45. },
  46. };
  47. println!("tick {i}, sending {direction:?}");
  48. turtle_vel_publisher.publish(direction).unwrap();
  49. }
  50. other => eprintln!("Ignoring unexpected input `{other}`"),
  51. },
  52. Event::Stop => println!("Received manual stop"),
  53. other => eprintln!("Received unexpected input: {other:?}"),
  54. },
  55. MergedEvent::External(pose) => {
  56. println!("received pose event: {pose:?}");
  57. if let Ok((pose, _)) = pose {
  58. let serialized = serde_json::to_string(&pose)?;
  59. node.send_output_bytes(
  60. output.clone(),
  61. Default::default(),
  62. serialized.len(),
  63. serialized.as_bytes(),
  64. )?;
  65. }
  66. }
  67. }
  68. }
  69. Ok(())
  70. }
  71. fn init_ros_node() -> eyre::Result<ros2_client::Node> {
  72. let ros_context = ros2_client::Context::new().unwrap();
  73. ros_context
  74. .new_node(
  75. ros2_client::NodeName::new("/ros2_demo", "turtle_teleop")
  76. .map_err(|e| eyre!("failed to create ROS2 node name: {e}"))?,
  77. NodeOptions::new().enable_rosout(true),
  78. )
  79. .context("failed to create ros2 node")
  80. }
  81. fn create_vel_publisher(
  82. ros_node: &mut ros2_client::Node,
  83. ) -> eyre::Result<ros2_client::Publisher<Twist>> {
  84. let topic_qos: rustdds::QosPolicies = {
  85. rustdds::QosPolicyBuilder::new()
  86. .durability(policy::Durability::Volatile)
  87. .liveliness(policy::Liveliness::Automatic {
  88. lease_duration: ros2::Duration::INFINITE,
  89. })
  90. .reliability(policy::Reliability::Reliable {
  91. max_blocking_time: ros2::Duration::from_millis(100),
  92. })
  93. .history(policy::History::KeepLast { depth: 1 })
  94. .build()
  95. };
  96. let turtle_cmd_vel_topic = ros_node
  97. .create_topic(
  98. &ros2_client::Name::new("/turtle1", "cmd_vel")
  99. .map_err(|e| eyre!("failed to create ROS2 name: {e}"))?,
  100. ros2_client::MessageTypeName::new("geometry_msgs", "Twist"),
  101. &topic_qos,
  102. )
  103. .context("failed to create topic")?;
  104. // The point here is to publish Twist for the turtle
  105. let turtle_cmd_vel_writer = ros_node
  106. .create_publisher::<Twist>(&turtle_cmd_vel_topic, None)
  107. .context("failed to create publisher")?;
  108. Ok(turtle_cmd_vel_writer)
  109. }
  110. fn create_pose_reader(
  111. ros_node: &mut ros2_client::Node,
  112. ) -> eyre::Result<ros2_client::Subscription<Pose>> {
  113. let turtle_pose_topic = ros_node
  114. .create_topic(
  115. &ros2_client::Name::new("/turtle1", "pose")
  116. .map_err(|e| eyre!("failed to create ROS2 name: {e}"))?,
  117. ros2_client::MessageTypeName::new("turtlesim", "Pose"),
  118. &Default::default(),
  119. )
  120. .context("failed to create topic")?;
  121. let turtle_pose_reader = ros_node
  122. .create_subscription::<Pose>(&turtle_pose_topic, None)
  123. .context("failed to create subscription")?;
  124. Ok(turtle_pose_reader)
  125. }