-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug] can we pub a ROS topic and receive it in zenoh subscriber? #131
Comments
I've figured this one out from the source code of this ros1-zenoh bridge: the zenoh topic name has some prefixes. I've written the following code in python to convert a ros topic name to the corresponding zenoh topic name, using the
with a script example that uses this function:
My example is for the pointcloud2 type of message, but it also works for other standard ROS message definitions. However, note the difference in naming, it is "sensor_msgs/msg/PointCloud2" and NOT "sensor_msgs/PointCloud2". You can now subscribe to the middle zenoh message with this generated topic name. |
Thanks a lot @edouard-fu for the Python snippet. - zenoh_topic = '/'.join([msg_type_encoded, md5, topic])
+ zenoh_topic = '/'.join([msg_type_encoded, md5, topic[1:]]) Using rosbags, I have added the deserialization to your example: import zenoh, time
from rosbags.typesys import Stores, get_typestore
TOPIC = '/topic'
TYPE = 'std_msgs/msg/String'
def get_zenoh_name_of_ros1_topic(ros1_store, topic: str, msg_type: str) -> str:
# Get md5 and encode msg_type to construct zenoh topic
msg_type_split = msg_type.split('/')
msg_type_encoded = '/'.join([msg_type_split[0],msg_type_split[2]]).encode('utf-8').hex()
md5 = ros1_store.generate_msgdef(msg_type)[1]
zenoh_topic = '/'.join([msg_type_encoded, md5, topic[1:]])
return zenoh_topic
def listener(sample):
msg = ros1_store.deserialize_ros1(sample.payload, TYPE)
print(f'ROS1 msg: {msg.data}')
if __name__ == "__main__":
session = zenoh.open(zenoh.Config())
ros1_store = get_typestore(Stores.ROS1_NOETIC)
zenoh_topic = get_zenoh_name_of_ros1_topic(ros1_store, topic=TOPIC, msg_type=TYPE)
print(f'ROS topic {TOPIC} is converted to Zenoh {zenoh_topic}')
sub = session.declare_subscriber(zenoh_topic, listener)
time.sleep(60) |
Just chiming in that this is still a usability problem, first day attempting to use Zenoh and this plugin and have been tripping over this for hours. The examples: https://github.com/eclipse-zenoh/zenoh-plugin-ros1/blob/main/zenoh-plugin-ros1/examples/ros1_sub.rs really make it look like this "should just work". Would dearly love a config option like "No Mangle Names" or "Proxy Topics Unmangled" that would allow for this to work directly. |
I ended up building a similar workaround in Rust to deal with this. The critical function is: /// Takes in a regular ros topic and type and returns a zenoh topic mangled in the way the zenoh-ros1-plugin does
fn mangle_topic(topic: &str, type_str: &str, md5sum: &str) -> String {
// Name mangling stuff!
// See: https://github.com/eclipse-zenoh/zenoh-plugin-ros1/issues/131
// Explicit implementation at: https://github.com/eclipse-zenoh/zenoh-plugin-ros1/blob/main/zenoh-plugin-ros1/src/ros_to_zenoh_bridge/topic_utilities.rs
// Note: the implementation inside of the bridge uses unstable zenoh, duplicating implementation here with stable zenoh instead.
// Remove leading and trailing slashes in the topic
let topic = topic.trim_start_matches('/').trim_end_matches("/");
// Encode the type as hex
let type_str = hex::encode(type_str.as_bytes());
format!("{type_str}/{md5sum}/{topic}")
} I built a wrapper crate that relies on roslibrust's type generation to get the md5 and type string here: |
hi @edouard-fu and @romainreignier, thanks for the examples! May I know what are the steps you did to get it working? I'm not sure if my setup is wrong or I am facing the same issue as @Carter12s mentioned in #208 where the examples are broken These are the steps I took so far, but the listener has not received any messages, # terminal 1
roscore
# terminal 2
rostopic pub my_topic -r 1 std_msgs/String "hello there"
# terminal 3, verifies that it is getting published on ros 1
rostopic echo /my_topic
# terminal 4, I see that /my_topic was registered
wget https://github.com/eclipse-zenoh/zenoh-plugin-ros1/releases/download/1.0.0-beta.2/zenoh-plugin-ros1-1.0.0-beta.2-x86_64-unknown-linux-gnu-standalone.zip
unzip zenoh-plugin-ros1-1.0.0-beta.2-x86_64-unknown-linux-gnu-standalone.zip
./zenoh-bridge-ros1
# terminal 5, changed topic to `/my_topic` and message type to `std_msgs/msg/String`
# however listener doesn't receive anything yet
pip3 install eclipse-zenoh==1.0.0b2 rosbags
python3 try_listen.py It produced the mangled topic at the output, but nothing else aaronchong@noetic:~$ python3 try_listen.py
ROS topic /my_topic is converted to Zenoh 7374645f6d7367732f6d73672f537472696e67/992ce8a1687cec8c8bd883ec73ca41d1/my_topic edit: just in case it's something to do with versions, it'd be nice to know what versions you all were running then. Thanks in advance! |
Not sure this is your issue? The bridge's default "mode" in zenoh is "client" you can see that here. I think to get the behavior your are looking for you'll want the bridge in "peer" mode so it automatically connects to your python code. This can be achieved by calling
More info about this on the zenoh deployment page I've also been testing with 1.0.0-beta-2, but I've been installing via I believe there is some discrepancy between my Rust implementation, and the python implementation above (possible related to versions of the bridge?). I'm not using I was able to determine the correct type str to use by running the bridge with default logging: You might also want to check out the "snoop_on_discovery" example here. The bridge is publishing some infomation here that announces what topics exist and has their key information. I used this when debugging to verify I was actually talking to the bridge with zenoh and again to double check the mangled topic names were mangled correctly. |
@Carter12s the default mode when using the standalone bridge should be
But overall I generally have a zenoh router running to help with discovery across multiple devices, or if I need to run clients, so I'm at least sure the mode is not the reason.
That's a great tip! Thanks, I'll look into it more starting from here to check the mangling of topic names, as well as |
Some updates, I struggled with ROS 1 publisher discovery by the bridge (not even the basic Then I created a fresh Ubuntu 20.04 VM, installed ROS 1 noetic natively, and things started to work 🤣 Just in case it is also stumping some folks, some background, I generally use Now that it's working for me, I found that the folks above are using - def listener(sample):
- msg = ros1_store.deserialize_ros1(sample.payload, TYPE)
+ def listener(sample: zenoh.Sample):
+ msg = ros1_store.deserialize_ros1(sample.payload.to_bytes(), TYPE)
print(f'ROS1 msg: {msg.data}') |
Describe the bug
When try the example:
I can not find a way create a zenoh subscriber to listen to the middle zenoh message (using "topic" key). Is there a way to do it? or can you give an example?
To reproduce
as mentioned above.
System info
Ubuntu 20.04
The text was updated successfully, but these errors were encountered: