与ROS和四个订户同步问题

发布于 2025-01-21 06:46:24 字数 3427 浏览 2 评论 0原文

我正在python中编写一个ROS节点,该节点实现了一个特定应用程序,该应用程序作为处理4个不同图像的输入。在我的主线程中,我使用openCV的cv2.imshow()显示结果(我不能将其放在其他地方,因为它在主线程之外不起作用)。我有另一个没有由我写的节点出版的四张图片,它们以15Hz的速度出版,全部四个。

在主线程中,除了显示方法的图像之外,我还进行了一些冗长的图像处理。这可能比图像发布期(约66毫秒)花费或更少的时间,但通常需要的时间比这更多。事实是,对于处理,我需要最新的可用映像,并且全部来自同一时间窗口。我试图通过收到每个图像(或更好的数据消息)的LIFO队列来实现此功能。这是一个(大量减少的)示例:

import cv2
from cv_bridge import CvBridge
import numpy as np
from queue import LifoQueue
import rospy
from sensor_msgs.msg import Image

class ImageProc():
    def __init__(self):

        self.cv_bridge = CvBridge()

        # Placeholders
        self.image_1 = dummyImage()
        self.image_2 = dummyImage()
        self.image_3 = dummyImage()
        self.image_4 = dummyImage()

        self.image_1_queue = LifoQueue(QUEUE_SIZE)
        self.image_2_queue = LifoQueue(QUEUE_SIZE)
        self.image_3_queue = LifoQueue(QUEUE_SIZE)
        self.image_4_queue = LifoQueue(QUEUE_SIZE)

        rospy.init_node('image_proc', anonymous=True)

        # 15 Hz
        rospy.Subscriber('/subscribe/image_a',
                         Image, self.image_1_callback)
        # 15 Hz
        rospy.Subscriber('/subscribe/image_b',
                         Image, self.image_2_callback)
        # 15 Hz
        rospy.Subscriber('/subscribe/image_c',
                         Image, self.image_3_callback)
        # 15 Hz
        rospy.Subscriber('/subscribe/image_d',
                         Image, self.image_4_callback)

    def image_1_callback(self, data):
        if not self.image_1_queue.full():
            self.image_1_queue.put(data)

    def image_2_callback(self, data):
        if not self.image_2_queue.full():
            self.image_2_queue.put(data)

    def image_3_callback(self, data):
        if not self.image_3_queue.full():
            self.image_3_queue.put(data)

    def image_4_callback(self, data):
        if not self.image_4_queue.full():
            self.image_4_queue.put(data)


def main():

    instance = ImageProc()

    cv2.namedWindow('image_1', cv2.WINDOW_NORMAL)
    cv2.namedWindow('image_2', cv2.WINDOW_NORMAL)
    cv2.namedWindow('image_3', cv2.WINDOW_NORMAL)
    cv2.namedWindow('image_4', cv2.WINDOW_NORMAL)

    while True:

        image_1 = np.copy(instance.cv_bridge.imgmsg_to_cv2(
            instance.image_1_queue.get()))
        image_2 = np.copy(instance.cv_bridge.imgmsg_to_cv2(
            instance.image_2_queue.get()))
        image_3 = np.copy(instance.cv_bridge.imgmsg_to_cv2(
            instance.image_3_queue.get()))
        image_4 = np.copy(instance.cv_bridge.imgmsg_to_cv2(
            instance.image_4_queue.get()))

        ###
        # Lengthy image processing stuff
        ###

        cv2.imshow('image_1', image_1)
        cv2.imshow('image_2', image_2)
        cv2.imshow('image_3', image_3)
        cv2.imshow('image_4', image_4)

        k = cv2.waitKey(1) & 0xFF

        if k == ord('q'):
            cv2.destroyAllWindows()
            break



if __name__ == '__main__':
    try:
        main()
    except rospy.ROSInterruptException:
        pass

我遇到的问题是:我怎么知道两个图像消息是否来自同一时间邮票?通过header.stamp的信息,以及检查它们是否在一定时间内?或者也许是header.seq?我如何完美地同步,以使得(例如)在图像复制的中间(在之后),而在true之后),一个新的图像消息到达并将其写入其中之一LIFOS,我在处理过程中有来自不同时间段的图像?另外,我使用的是LIFO,因为如果我的处理需要大量时间,当周期再次开始时,我需要ROS主题中的最新数据,而不是存储在队列中的数据。在我的处理少于66毫秒的遥远场合中,我该如何防止这种小的小众案例?

任何帮助/洞察力都非常感谢!

I'm writing a ROS node in python that implements a specific application that takes as input for processing 4 different images. In my main thread I use OpenCV's cv2.imshow() to show results (I can't put it elsewhere since it doesn't work outside of the main thread). I have these four pictures published by another node not written by me, and they're published with a rate of 15Hz, all four together.

In the main thread, other than the image showing methods, I also do some lengthy image processing. This might take more or less time than the images publication period (approx. 66ms), but it usually takes more time than that. The fact is, for the processing I need the latest available images, and all from the same time window. I tried to implement this with a LIFO queue for each image (or better, data msg) recieved. Here is a (much reduced) example:

import cv2
from cv_bridge import CvBridge
import numpy as np
from queue import LifoQueue
import rospy
from sensor_msgs.msg import Image

class ImageProc():
    def __init__(self):

        self.cv_bridge = CvBridge()

        # Placeholders
        self.image_1 = dummyImage()
        self.image_2 = dummyImage()
        self.image_3 = dummyImage()
        self.image_4 = dummyImage()

        self.image_1_queue = LifoQueue(QUEUE_SIZE)
        self.image_2_queue = LifoQueue(QUEUE_SIZE)
        self.image_3_queue = LifoQueue(QUEUE_SIZE)
        self.image_4_queue = LifoQueue(QUEUE_SIZE)

        rospy.init_node('image_proc', anonymous=True)

        # 15 Hz
        rospy.Subscriber('/subscribe/image_a',
                         Image, self.image_1_callback)
        # 15 Hz
        rospy.Subscriber('/subscribe/image_b',
                         Image, self.image_2_callback)
        # 15 Hz
        rospy.Subscriber('/subscribe/image_c',
                         Image, self.image_3_callback)
        # 15 Hz
        rospy.Subscriber('/subscribe/image_d',
                         Image, self.image_4_callback)

    def image_1_callback(self, data):
        if not self.image_1_queue.full():
            self.image_1_queue.put(data)

    def image_2_callback(self, data):
        if not self.image_2_queue.full():
            self.image_2_queue.put(data)

    def image_3_callback(self, data):
        if not self.image_3_queue.full():
            self.image_3_queue.put(data)

    def image_4_callback(self, data):
        if not self.image_4_queue.full():
            self.image_4_queue.put(data)


def main():

    instance = ImageProc()

    cv2.namedWindow('image_1', cv2.WINDOW_NORMAL)
    cv2.namedWindow('image_2', cv2.WINDOW_NORMAL)
    cv2.namedWindow('image_3', cv2.WINDOW_NORMAL)
    cv2.namedWindow('image_4', cv2.WINDOW_NORMAL)

    while True:

        image_1 = np.copy(instance.cv_bridge.imgmsg_to_cv2(
            instance.image_1_queue.get()))
        image_2 = np.copy(instance.cv_bridge.imgmsg_to_cv2(
            instance.image_2_queue.get()))
        image_3 = np.copy(instance.cv_bridge.imgmsg_to_cv2(
            instance.image_3_queue.get()))
        image_4 = np.copy(instance.cv_bridge.imgmsg_to_cv2(
            instance.image_4_queue.get()))

        ###
        # Lengthy image processing stuff
        ###

        cv2.imshow('image_1', image_1)
        cv2.imshow('image_2', image_2)
        cv2.imshow('image_3', image_3)
        cv2.imshow('image_4', image_4)

        k = cv2.waitKey(1) & 0xFF

        if k == ord('q'):
            cv2.destroyAllWindows()
            break



if __name__ == '__main__':
    try:
        main()
    except rospy.ROSInterruptException:
        pass

The problems I encounter are: How do I know if two image messages are from the same time stamp? With the information from the header.stamp, and by checking if they're all within a certain time delta? Or maybe the header.seq? How do I synchronize this perfectly such that there is no occasion that (for example) in the middle of the image copying (just after the while True), a new image message arrives and gets written to one of the LIFOs, and I have images from different time periods during processing? Also, I'm using a LIFO because if my processing takes a lot of time, when the cycle starts again I need the latest data from the ROS topics, and not the data stored in a queue. And in the remote occasion that my processing takes less than 66ms, how do I prevent this small niche case?

Any help/insight is much appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文