lambdaprime / jros2client

Java module to interact with ROS2 (Robot Operating System)
5 stars 3 forks source link

subscribe to id.jros2messages.sensor_msgs.ImageMessage #5

Closed wldfwefwefqe closed 11 months ago

wldfwefwefqe commented 1 year ago

Dear author:

I was trying to use the package to subscribe to ImageMessage published by ros2 humble publisher. However, it does not work.

Here is the code:

public class SubscriberApp {

public static void main(String[] args) throws Exception {

    var client = new JRos2ClientFactory().createClient();
    var topicName = "/image_topic";
    // register a new Subscriber

    client.subscribe(new TopicSubscriber<>(ImageMessage.class, topicName) {

        @Override
        public void onNext(ImageMessage item) {
            System.out.println(item.header.frame_id);
            // request next message
            getSubscription().get().request(1);
        }
    });

}

}

And here is the error message:

WARNING: dataFrag with number 2 already present, ignoring it... Oct 24, 2023 10:35:00 PM pinorobotics.rtpstalk.impl.behavior.reader.DataFragmentJoiner#1496724653-00000104 WARNING: dataFrag with number 78 already present, ignoring it... Oct 24, 2023 10:35:00 PM pinorobotics.rtpstalk.impl.behavior.reader.DataFragmentJoiner#1496724653-00000104 WARNING: dataFrag with number 79 already present, ignoring it... Oct 24, 2023 10:35:00 PM pinorobotics.rtpstalk.impl.behavior.reader.DataFragmentJoiner#1496724653-00000104 WARNING: DataFrag 106 length mismatch, expected 65,384 received 46,780, ignoring message Oct 24, 2023 10:35:00 PM pinorobotics.rtpstalk.impl.behavior.reader.DataFragmentJoiner#1496724653-00000104 WARNING: dataFrag with number 1 already present, ignoring it...

How to solve this?

Thank you very much in advance.

wldfwefwefqe commented 1 year ago

The Publisher is ros2, which publishes .png files(Image from sensor_msgs.msg). Subscriber is java as shown above. Java subscriber is receiving the warning, meaning at least the data has been received by subscriber. However, it is just not receiving ImageMessage properly. How to set up Java subscriber, so it could receive ImageMessage properly?

lambdaprime commented 1 year ago

Hi @wldfwefwefqe ,

Thanks for trying jrosclient

The subscriber code looks correct.

Have you received warnings like:

Oct 26, 2023 3:00:04 AM pinorobotics.rtpstalk.impl.spec.transport.DataChannelFactory
WARNING: Could not set size of receive buffer, current size 212992, expected 26214400. This may cause message loss.

If running Linux try to set receive buffer manually:
sudo sysctl -w net.core.rmem_max=26214400
sudo sysctl -w net.core.rmem_default=26214400
sudo sysctl -w net.ipv4.udp_mem=26214400

Could you please apply them just to be sure that buffer is large enough.

If this does not help could you please:

wldfwefwefqe commented 1 year ago

Dear Author,

Thank you very much for you response.

I have updated setting for net.core.rmem_max , etc. Then the warning for buffer size disappeared when I run the Java subscriber.

However, the same warning is still there. Oct 26, 2023 10:23:57 PM pinorobotics.rtpstalk.impl.behavior.reader.DataFragmentJoiner#458209687-00000104 WARNING: dataFrag with number 86 already present, ignoring it... Oct 26, 2023 10:23:57 PM pinorobotics.rtpstalk.impl.behavior.reader.DataFragmentJoiner#458209687-00000104 WARNING: dataFrag with number 87 already present, ignoring it...

Here is my ros2 publisher code:

import os import rclpy from rclpy.node import Node from sensor_msgs.msg import Image from cv_bridge import CvBridge import cv2

class ImagePublisher(Node): def init(self): super().init('image_publisher')

     # Log the RMW implementation in use
    rmw_implementation = rclpy.get_rmw_implementation_identifier()
    self.get_logger().info(f'Using RMW: {rmw_implementation}')

    # 10 is the length of queue, if full, the first element in queue will be deleted
    self.publisher_ = self.create_publisher(Image, 'image_topic', 10)
    self.bridge = CvBridge()
    timer_period = 0.02  # seconds
    self.timer = self.create_timer(timer_period, self.publish_image)
    self.i = 0

def get_image_paths(self, folder_path):
    image_paths = []
    for root, _, files in os.walk(folder_path):
        for file in files:
            if file.lower().endswith('.png') or file.lower().endswith('.jpg'):
                image_paths.append(os.path.join(root, file))
    sorted_image_paths = sorted(image_paths)
    return sorted_image_paths

def publish_image(self):
    folder_path = '/home/wls/ws/src/resource/A9/a9_dataset_r00_s01/_images'#/s110_camera_basler_south2_8mm-20231024T090545Z-001' #Path to be updated
    image_paths = self.get_image_paths(folder_path)
    if self.i < len(image_paths):
        img = cv2.imread(image_paths[self.i])
        img_msg = self.bridge.cv2_to_imgmsg(img) #, encoding='bgr8' 

        # Extract filename from the path and add it to the message header
        filename = os.path.basename(image_paths[self.i])
        img_msg.header.frame_id = filename

        self.publisher_.publish(img_msg)
        self.get_logger().info(f'Image "{filename}" published')
        self.i += 1
    else:
        self.get_logger().info('All images published.')
        self.destroy_timer(self.timer)

def main(args=None): rclpy.init(args=args) image_publisher = ImagePublisher() rclpy.spin(image_publisher) image_publisher.destroy_node() rclpy.shutdown()

if name == 'main': main()

Code finished

This python ros2 publisher is looping through a folder and publish all picture files under topic 'image_topic'. Of course, Java subscriber listens to this topic also.

I am using FastDDS (rmw_fastrtps_cpp). I have tried 2 sets of images: big set has all pictures with size over 3 MB and small set with all pictures with around 200KB. Please find the small set of pictures here: 161148.zip

wldfwefwefqe commented 11 months ago

Dear Author, Is there any foreseeable update on this issue? Many thanks in advance.

lambdaprime commented 11 months ago

Hi @wldfwefwefqe

Thanks for the images and test code. We could reproduce the problem and are working on it. We will update you in 2 weeks period.

lambdaprime commented 11 months ago

Hi @wldfwefwefqe

The fix is ready and will be included in v4 we plan to release end of the year. Until then you can use prerelease version You will need to install it manually

Our test results using your example:

jros2client v3: 96 messages received out of 128 jros2client v4 snapshot: 127 messages received out of 128

wldfwefwefqe commented 11 months ago

Dear @lambdaprime ,

Thank you very much for the previous fix. However, could you please update the underlying library with the changes from these two commits: af1a3b0 and 736ce30? Currently, I am unable to use version 4 because the underlying library is not updated. I attempted a manual installation, but it was unsuccessful. The Maven installation of Jros2client is working well for me, but it depends on an outdated version of the underlying library.

Could you push the latest commits to the repository? Alternatively, is it possible to release ros2client version 4, perhaps a month early, like in November? This is urgent for my thesis and its deadline. Your support is greatly appreciated.

Thank you very much in advance.

lambdaprime commented 11 months ago

Hi @wldfwefwefqe,

could you please update the underlying library with the changes from these two commits: af1a3b0 and 736ce30?

All the necessary changes including these two commits you can find inside prerelease version

I attempted a manual installation, but it was unsuccessful.

Could you please show the logs

wldfwefwefqe commented 11 months ago

Dear @lambdaprime ,

Thank you for your quick response.

when I download the prerelease version source code and running in my Intellij, it shows the following error: image The reason is the gradle dependency, which is essential to run programm is not available in gradle/maven repository: image As you can see in the repository screenshot as below: image 4.0-SNAPSHOT does not exist there

lambdaprime commented 11 months ago

Hi @wldfwefwefqe

What you are showing is not what documentation for manual installation talks about. See: "To use jros2client the entire libs folder needs to be added to the classpath/module-path of the application."

Could you please show your classpath/module-path you are using? Make sure you use jros2client-v4.0-SNAPSHOT.zip and not sources archive

wldfwefwefqe commented 11 months ago

Dear @lambdaprime ,

Thank you very much for your hint. I have used the manual installation as you suggested as now I can start the java program directly.

However, the new library does not work on communication between different devices. I have ros2 running on RasPi and Java running on laptop. Now the listener on Java from laptop does have any reaction. In addition, for my task, I have to test on big picture, over 2 Mb each and it has to be highly reliable and fast. The files I sent to you were small pictures, only 200 KB each. And your test result still has package loss (127 messages received out of 128).

I would need to find another way to solve the issue, so I can solve the task/problem I am facing.

But thank you very very much for your contribution for the ros2 community. And also great thanks for your fast response for all the question and response.

lambdaprime commented 11 months ago

Hi @wldfwefwefqe

Nice to hear that it works, and thanks for reporting initial issue.

And your test result still has package loss (127 messages received out of 128).

FYI Package loss happens not in jrosclient but on the Publisher side which you provided:

>    # 10 is the length of queue, if full, the first element in queue will be deleted
>    self.publisher_ = self.create_publisher(Image, 'image_topic', 10)