Skip to content

Subscribers can't hear ros2_client publishers #39

@onkoe

Description

@onkoe

Hi again! I was making tests for our nodes and couldn't get ros2_client subscribers to hear ros2_client publishers. When listening on the topic using ros2 topic echo /topic_name, I was able to see output.

As an example, I made a test for ros2-client in a newly created tests/topic.rs:

//! Ensures that two `ros2_client` nodes can speak to each other.

use std::{pin::pin, time::Duration};
use futures::{future::select, StreamExt};

use ros2_client::{
  Context, MessageTypeName, Name, NodeName, NodeOptions, Publisher, Subscription,
  DEFAULT_PUBLISHER_QOS,
};

#[tokio::test]
async fn topic_communication() {
  select(pin!(make_publisher()), pin!(make_subscriber())).await;
}

async fn make_subscriber() {
  // make context
  let ctx = Context::new().unwrap();

  // node, topic, subscriber
  let mut node = ctx
    .new_node(
      NodeName::new("/", "topic_test_sub_node").unwrap(),
      NodeOptions::new(),
    )
    .unwrap();
  let topic = node
    .create_topic(
      &Name::new("/", "pub_sub_topic").unwrap(),
      MessageTypeName::new("std_msgs", "String"),
      &DEFAULT_PUBLISHER_QOS.clone(),
    )
    .unwrap();
  let subscriber: Subscription<String> = node.create_subscription(&topic, None).unwrap();

  // spin node in background
  tokio::task::spawn(node.spinner().unwrap().spin());

  // start listening.
  //
  // if we don't get a message within five seconds, fail the test.
  let (msg, _msg_info) = tokio::time::timeout(
    Duration::from_secs(5),
    Box::pin(subscriber.async_stream()).next(),
  )
  .await
  .expect("Test timed out - publisher never sent anything!")
  .expect("we should've got a message.")
  .expect("message should've sent correctly!");

  assert_eq!(msg, "hello subscriber!");
}

async fn make_publisher() {
  let ctx = Context::new().unwrap();

  let mut node = ctx
    .new_node(
      NodeName::new("/", "topic_test_pub_node").unwrap(),
      NodeOptions::new(),
    )
    .unwrap();

  let topic = node
    .create_topic(
      &Name::new("/", "pub_sub_topic").unwrap(),
      MessageTypeName::new("std_msgs", "String"),
      &DEFAULT_PUBLISHER_QOS.clone(),
    )
    .unwrap();

  let publisher: Publisher<String> = node.create_publisher(&topic, None).unwrap();

  tokio::task::spawn(node.spinner().unwrap().spin());

  // send messages every 0.25 seconds
  loop {
    publisher
      .async_publish("hello subscriber!".into())
      .await
      .unwrap();

    tokio::time::sleep(Duration::from_millis(250)).await;
  }
}

Output from the test:

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/topic.rs (target/debug/deps/topic-f3f388d49a16d225)

running 1 test
test topic_communication ... FAILED

failures:

---- topic_communication stdout ----
thread 'topic_communication' panicked at tests/topic.rs:47:4:
Test timed out - publisher never sent anything!: Elapsed(())
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    topic_communication

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 5.06s

error: test failed, to rerun pass `--test topic`

Output from ros2 topic echo /pub_sub_topic:

$ ros2 topic echo /pub_sub_topic
data: hello subscriber!
---
data: hello subscriber!
---
data: hello subscriber!
---
data: hello subscriber!
---
data: hello subscriber!
---
data: hello subscriber!
---
data: hello subscriber!
---

Please note that this test uses tokio (as mentioned in #26), though the same problem seems to appear when doing things synchronously, too.

In addition, you can force the test to pass by using ros2 topic pub:

$ ros2 topic pub /pub_sub_topic std_msgs/String {data: "hello subscriber!"}
publisher: beginning loop
publishing #1: std_msgs.msg.String(data='hello subscriber!')

publishing #2: std_msgs.msg.String(data='hello subscriber!')

publishing #3: std_msgs.msg.String(data='hello subscriber!')

publishing #4: std_msgs.msg.String(data='hello subscriber!')
Running tests/topic.rs (target/debug/deps/topic-f3f388d49a16d225)

running 1 test
test topic_communication ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 2.58s

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinginvalidThis doesn't seem right

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions