You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nao机器人Python紧急开关优化咨询:终止抛异常、行走场景失效

NAO机器人紧急开关优化方案

原代码存在的问题

  1. 直接依赖全局app实例,作用域混乱,且sys.exit(1)强制终止进程会引发qi框架线程异常
  2. 仅处理了文本播报的停止逻辑,未针对行走场景添加ALMotion服务的停止操作
  3. 阻塞式调用tts.say(),导致事件循环未完全启动,触摸事件响应异常
  4. 采用Python2风格的异常捕获语法,兼容性差

优化后的实现代码

# -*- encoding: UTF-8 -*-
import qi
import sys

class EmergencySwitch(object):
    def __init__(self, app):
        super(EmergencySwitch, self).__init__()
        self.app = app  # 保存app实例到类属性,避免全局引用
        self.session = app.session
        self.app.start()
        
        # 初始化核心服务
        self.tts = self.session.service("ALTextToSpeech")
        self.motion = self.session.service("ALMotion")  # 新增行走服务支持
        self.memory = self.session.service("ALMemory")
        
        # 订阅头部触摸传感器事件
        self.touch_subscriber = self.memory.subscriber("FrontTactilTouched")
        self.touch_signal_id = self.touch_subscriber.signal.connect(self.trigger_emergency_stop)
        
        # 启动目标任务(播报/行走)
        self.start_task()

    def trigger_emergency_stop(self, touched):
        # 断开触摸事件订阅,防止重复触发
        if self.touch_signal_id:
            self.touch_subscriber.signal.disconnect(self.touch_signal_id)
            self.touch_signal_id = None
        
        # 优雅停止所有运行中任务
        try:
            self.tts.stopAll()  # 终止播报
            self.motion.stopMove()  # 终止行走(需强制终止可替换为killMove())
            self.app.stop()  # 优雅停止qi应用框架
        except RuntimeError as e:
            print(f"紧急停止出错: {str(e)}")
        finally:
            sys.exit(0)  # 正常退出进程,避免强制终止引发异常

    def start_task(self):
        # 示例1:异步播报任务(不阻塞事件循环)
        self.tts.setVolume(0.1)
        self.tts.say("Hallo sdiufhsfkasdkjasdnaskjfbnsdkfbskfjn", _async=True)
        
        # 示例2:异步行走任务(取消注释启用)
        # self.motion.moveInit()
        # self.motion.setWalkTargetVelocity(0.2, 0, 0, _async=True)

if __name__ == "__main__":
    try:
        app = qi.Application(["EmergencySwitch", "--qi-url=tcp://192.168.95.80:9559"])
    except RuntimeError:
        print("连接机器人失败")
        sys.exit(1)
    
    emergency_switch = EmergencySwitch(app)
    app.run()

关键优化说明

  • 消除全局依赖:将app实例保存为类属性,确保操作的是正确实例,避免作用域冲突
  • 优雅终止流程:先通过app.stop()停止qi框架服务,再正常退出进程,彻底解决异常抛出问题
  • 适配行走场景:新增ALMotion服务调用,紧急停止时主动终止行走动作
  • 异步任务执行:所有任务调用添加_async=True参数,避免阻塞事件循环,确保触摸事件能被及时响应
  • 防止重复触发:断开触摸订阅后将信号ID置空,避免重复操作引发错误

内容的提问来源于stack exchange,提问作者Mathews

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 12:59:14