订阅者仅在 input() 命令后收到消息

Message received by subscriber only after input() command

我的凉亭模型可以移动到给定的目标目的地。 到目前为止,目标是由用户输入的:

goal_pose.x = float(input("Set your x goal: "))
goal_pose.y = float(input("Set your y goal: "))

我想通过节点而不是通过用户输入发送目标目的地。所以我创建了另一个发布一些随机目标目的地的节点。

问题是当我尝试订阅那个节点时,它只会在我使用 input() 命令后订阅。

无效的代码:

        print("self.goal , is:") 
        print(self.goal_pose.x, self.goal_pose.y)
        print("self.goal , is:")
        print(self.goal_pose.x, self.goal_pose.y)

输出:

self.goal , is:
(0.0, 0.0)
self.goal , is:
(0.0, 0.0)

有效的代码:

        print("self.goal , is:")
        print(self.goal_pose.x, self.goal_pose.y)
        input("type something and press enter: ")
        print("self.goal , is:")
        print(self.goal_pose.x, self.goal_pose.y)

输出:

self.goal , is:
(0.0, 0.0)
type something and press enter: 22
self.goal , is:
(5.0, 6.0)

我想知道这种行为的原因是什么以及如何解决?

附上部分代码要点:

class oferbot_controller:

    def __init__(self):
        rospy.init_node(const.MOVE_NODE_NAME, anonymous=True)
        self.velocity_publisher = rospy.Publisher(const.CMD_VEL_TOPIC, Twist, queue_size=10)
        self.odom_subscriber = rospy.Subscriber(const.ODOMETRY_TOPIC,Odometry, self.update_odom)
        self.goal_subscriber = rospy.Subscriber(const.GOAL_POSE_TOPIC,Pose,self.update_goal)
        self.odom = Odometry()
        self.goal_pose = Pose()
        self.vel_msg = Twist()
        self.teta = float()
        self.rate = rospy.Rate(10)
        
        


    def update_goal(self,data): 
        self.goal_pose = data
        self.goal_pose.x = round(self.goal_pose.x, 4)
        self.goal_pose.y = round(self.goal_pose.y, 4)

    
    
    def move2goal(self):
        
        
        print("self.goal , is:")
        print(self.goal_pose.x, self.goal_pose.y)
        input("type something and press enter: ")
        print("self.goal , is:")
        print(self.goal_pose.x, self.goal_pose.y)


        while calc.euclidean_distance(self.odom,self.goal_pose) >= const.DISTANCE_TOLERANCE:
            ## Make the robot move accordingly ##

        # Stopping our robot after the movement is over.
        self.stop_the_bot()
        rospy.spin()

if __name__ == '__main__':
    try:
        x = oferbot_controller()
        x.move2goal()
    except rospy.ROSInterruptException:
        pass

发布者节点在不同的终端中运行。出版商代码:

rospy.init_node('point_goal_publisher')

point_goal_pub = rospy.Publisher(const.GOAL_POSE_TOPIC, Pose, queue_size=10)
point_goal = Pose()
point_goal.x = const.POINT_X
point_goal.y = const.POINT_Y
rate = rospy.Rate(10)
print("Publishing point goal:")
print("x goal = ", point_goal.x ,"y goal = ", point_goal.y)
while not rospy.is_shutdown():
    point_goal_pub.publish(point_goal)
    rate.sleep()

您可以尝试在update_goal()函数中直接调用self.move2goal(),确保在执行前收到数据。

您在实际创建可能仅以 <50Hz 的频率进入的订阅者后不久就呼叫 print()。这意味着当您查询 msg 变量时,订阅者很有可能还没有收到任何数据。 input 调用给了它足够的时间来实际接收消息;这并没有特别强迫它接收任何东西。你应该做的是让它等待这样一个有效的目标:

class oferbot_controller:

    def __init__(self):
        rospy.init_node(const.MOVE_NODE_NAME, anonymous=True)
        self.velocity_publisher = rospy.Publisher(const.CMD_VEL_TOPIC, Twist, queue_size=10)
        self.odom_subscriber = rospy.Subscriber(const.ODOMETRY_TOPIC,Odometry, self.update_odom)
        self.goal_subscriber = rospy.Subscriber(const.GOAL_POSE_TOPIC,Pose,self.update_goal)
        self.odom = Odometry()
        self.goal_pose = None
        self.vel_msg = Twist()
        self.teta = float()
        self.rate = rospy.Rate(10)
        
        


    def update_goal(self,data): 
        self.goal_pose = data
        self.goal_pose.x = round(self.goal_pose.x, 4)
        self.goal_pose.y = round(self.goal_pose.y, 4)

    
    
    def move2goal(self):
        
        while self.goal_pose == None:
            self.rate.sleep()
        
        print("self.goal , is:")
        print(self.goal_pose.x, self.goal_pose.y)


        while calc.euclidean_distance(self.odom,self.goal_pose) >= const.DISTANCE_TOLERANCE:
            ## Make the robot move accordingly ##

        # Stopping our robot after the movement is over.
        self.stop_the_bot()
        rospy.spin()

if __name__ == '__main__':
    try:
        x = oferbot_controller()
        x.move2goal()
    except rospy.ROSInterruptException:
        pass