简体   繁体   English

如何在执行子进程回调时保持 ROS 发布者发布?

[英]How to keep ROS publisher publishing while executing a subprocess callback?

How can I keep the ROS Publisher publishing the messages while calling a sub-process:如何让 ROS Publisher 在调用子流程时发布消息:

import subprocess
import rospy

class Pub():
    def __init__(self):
        pass

    def updateState(self, msg):
     cmd = ['python3', planner_path, "--alias", search_options, "--plan-file", plan_path, domain_path, problem_path]

    subprocess.run(cmd, shell=False, stdout=subprocess.PIPE)
    self.plan_pub.publish(msg)

    def myPub(self):
        rospy.init_node('problem_formulator', anonymous=True)
        self.plan_pub = rospy.Publisher("plan", String, queue_size=10)
        rate = rospy.Rate(10) # 10hz
        rospy.Subscriber('model', String, updateState)
        rospy.sleep(1)
        rospy.spin()

if __name__ == "__main__":
    p_ = Pub()
    p_.myPub()

Since subprocess.call is a blocking call your subscription callback may take a long time.由于subprocess.call是阻塞调用,您的订阅回调可能需要很长时间。

Run the command described by args.运行 args 描述的命令。 Wait for command to complete, then return the returncode attribute.等待命令完成,然后返回 returncode 属性。

ROS itself will not call the callback again while it is executed already. ROS 本身不会在已经执行的情况下再次调用回调。 This means you are blocking this and potentially also other callbacks to be called in time.这意味着您正在阻止此回调,并且可能还会及时调用其他回调。

The most simple solution would be to replace subprocess.call by subprocess.Popen which简单的解决方案是用subprocess.Popen替换subprocess.call

Execute a child program in a new process在新进程中执行子程序

nonblocking.非阻塞。

But keep in mind that this potentially starts the process multiple times quite fast.但请记住,这可能会非常快地多次启动该过程。

Think about starting the process only conditionally if not already running.如果尚未运行,请考虑仅有条件地启动该过程 This can be achieved by checking the process to be finished in another thread.这可以通过检查要在另一个线程中完成的过程来实现。 Simple but effective, use boolean flag.简单但有效,使用 boolean 标志。 Here is a small prototype:这是一个小原型:

def updateState(self, msg):
    #Start the process if not already running
    if not self._process_running:
        p = subprocess.Popen(...)
        self._process_running = True
        def wait_process():
            while p.poll() is None:
                time.sleep(0.1)
            self._process_running = False
        threading.Thread(target=wait_process).start()
    #Other callback code
    self.plan_pub.publish(msg)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM