ROS Python中如何在回调函数外获取/joy节点的按键输入以退出自动模式
ROS Python中如何在回调函数外获取/joy节点的按键输入以退出自动模式
看起来你遇到的核心问题是自动模式的while循环阻塞了ROS的回调处理,导致新的手柄按键消息没法被更新到循环里的data变量中。我来给你梳理下问题原因和解决办法:
问题根源
你原来的代码里,当进入automatic(data)函数后,while True是一个没有任何延迟的死循环,会一直占用CPU,导致ROS的回调线程没有机会处理新的/joy消息。而且就算回调能触发,循环里用到的data还是进入函数时的旧参数,不会自动同步最新的按键状态。
解决方案:用全局变量存储最新按键状态+ROS Rate控制循环
我们可以把手柄的按键状态存在全局变量里,让回调函数实时更新它,同时在自动模式的循环里用ROS的Rate来控制频率,给回调线程留出处理消息的时间。
步骤1:定义全局变量存储状态
先声明全局变量来保存最新的按键状态和当前模式:
import rospy from sensor_msgs.msg import Joy import cv2 # 根据你的手柄按键数量调整数组长度 latest_joy_buttons = [0] * 12 latest_joy_axes = [0] * 8 # 存储摇杆轴数据,供手动模式使用 automatic_mode = 0
步骤2:修改回调函数更新全局状态
让回调函数每次收到/joy消息时,就更新全局的按键和摇杆状态,同时处理模式切换:
def callback(data): global latest_joy_buttons, latest_joy_axes, automatic_mode rospy.loginfo(rospy.get_caller_id() + "motor variables: %s, %s, %s", data.axes[2], data.buttons[2], data.buttons[3]) # 实时更新全局的按键和摇杆状态 latest_joy_buttons = data.buttons.copy() latest_joy_axes = data.axes.copy() # 处理模式切换按钮 if latest_joy_buttons[2] == 1: automatic_mode = 1 if latest_joy_buttons[3] == 1: automatic_mode = 0
步骤3:重构自动模式函数
不要用死循环,改用ROS的Rate来控制循环频率,这样每次循环都会检查最新的全局按键状态,同时让ROS有时间处理回调:
def automatic(): # 设置循环频率(比如30Hz,可根据你的需求调整) rate = rospy.Rate(30) # 循环条件:ROS没关闭,且当前处于自动模式 while not rospy.is_shutdown() and automatic_mode == 1: # 这里放你的自动循线逻辑 # 比如读取摄像头帧、检测黑线、计算电机控制指令... # 检查退出按键(按钮3是否被按下) if latest_joy_buttons[3] == 1: automatic_mode = 0 rospy.loginfo("已退出自动模式") break # 必须调用这个,让ROS处理回调消息 rate.sleep()
步骤4:重构手动模式函数
手动模式也基于全局的最新摇杆状态来处理,确保控制逻辑实时响应手柄输入:
def manual(): # 获取最新的摇杆数据(比如你用到的axes[2]) current_axis_value = latest_joy_axes[2] # 这里放手动控制电机的逻辑 # 比如根据摇杆值调整左右电机转速...
步骤5:主线程循环处理模式切换
最后在主函数里,用一个循环来根据当前模式调用对应的函数,确保主线程不被阻塞:
def main(): rospy.init_node('robot_controller', anonymous=True) # 订阅/joy话题 rospy.Subscriber("/joy", Joy, callback) rate = rospy.Rate(30) while not rospy.is_shutdown(): if automatic_mode == 1: automatic() else: manual() rate.sleep() if __name__ == '__main__': try: main() except rospy.ROSInterruptException: pass
额外提示
- 默认情况下ROS的回调是在单线程里执行的,所以只要不同时在多个线程修改全局变量,就不会有线程安全问题。
- 你可以根据自己手柄的实际按键数量调整
latest_joy_buttons的数组长度,避免索引越界。
备注:内容来源于stack exchange,提问作者Cooler Mann
相关产品推荐
相关产品推荐

