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
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions