让机器人锁定你,做你的原地小跟班
利用 vop 识别锁定一个对象,asr语音和tts互动,通过chassis_raw控制地盘转向实现原地跟随功能
【触发】 用户说"原地跟随""跟着我""跟着XX"时启动。 核心纪律:skill 未结束之前绝不让对话 finish——跟随全程由你持续驱动,任何一步做完的默认去向都是回到跟随循环;注意边走边播报!!!【只有用户喊停或按丢失规则放弃时才走【结束】。
【开始】
确认底盘空闲:若有导航任务在执行,播报"正在导航,无法跟随",不启动。
若 face_recognition 未在运行,调用其 start,input_topic 从 camera_head 卡片输出端口获取(形如 /<主机名>/camera/head)。
确定跟随目标(本 skill 只跟踪一个人):先取一两帧识别结果(格式见跟随循环第 1 步)。
用户点名了姓名(如"跟着小王")则按 name 字段锁定其 person_id。
未点名:取人脸框面积(bbox 的 w×h)最大者(通常离得最近)。陌生人 p-N 也可作为目标 id。
锁定后此 id 即唯一目标,全程不得更换。
播报(明确告知单人跟随语义):"开始原地跟随XX,我只跟着你一个人哦。"
进入跟随循环。
【跟随循环】(每轮依次执行)
取目标人脸位置:优先读卡片最近一条 FACES 事件(输出 topic 形如 /<主机名>/head/face),超过 1 秒无新事件再调 recognize_by_stream(window_s=1),两者数据同构。每条 FACES 实测格式: {"bbox":[x,y,w,h],"det_score":0.69,"person_id":"p-185","name":"","known":false,"score":0.60,"quality":"ok"}
有效性过滤:quality 不为 "ok" 或 det_score < 0.5 的帧丢弃,取最近有效帧(实测单帧延迟约 60ms,1 秒一轮足够)。
目标匹配:严格按锁定的 person_id 选脸。画面的其他人脸一概忽略(哪怕面积更大)——单人跟踪,锁定即不变。
归一化:center_x = bbox[0] + bbox[2] ÷ 2,norm_x = center_x ÷ 画面宽度。画面宽度从 camera_head 卡片 info 的分辨率获取(FACES 消息本身不含分辨率,严禁拿 bbox 像素值直接当 offset)。
计算偏差:offset = norm_x - 0.5。
死区判断:|offset| < 0.08(约±5°)→ 视为已居中,不发旋转,间隔约 1 秒后进入下一轮。
需要转向时:
方向:offset < 0(人在画面左侧)→ rotation="left";offset > 0 → rotation="right"。
角度:angle = |offset| × 2 × 70(70° 为镜头水平视场估计值),下限 5°、上限 45°,四舍五入取整度。
先用 tts 播报本次要转的角度(任何旋转动作都必须先说度数和方向):"xx别跑哦,让我左/右转XX度。"
调用 chassis_raw 的 rotate(只传 rotation 和 angle,不传 duration)。
等待本步转完:约 angle ÷ 90 秒(rotate 是立即返回、底盘闭环执行,不要连续发送未消化的旋转指令)。
回到第 1 步,闭环会自动修正残余误差和过冲。
【转向语义】 left + 正角度 = 逆时针(机器人的左侧);right + 正角度 = 顺时针;负角度 = 反向。只用 left/right + 正角度表达,不要用负数。
【丢失处理】
连续 2 轮识别不到目标(含画面完全无人的情况):不再转向,先用 tts 询问用户:"XX,你是不是跑开了?我识别不到你了。"
原地等待并继续每轮识别(这就是等待期间的心跳):目标重新出现 → 播报"找到你啦,继续跟随",恢复跟随循环。
询问后约 10 秒仍无目标:播报"目标丢失,跟随已停止",调用 chassis_raw 的 brake,走【结束】。
【安全红线】
全程只允许 chassis_raw 的 rotate 和 brake 两个动作,严禁调用 move(原地跟随不位移)。
单次旋转不超过 45°;急停/拍打/异常报错时立即 brake 并结束。
播报统一用 tts 卡片 action=speak;跟随期间播报要简短,避免长时间占用语音通道。每次旋转前必播角度,已居中或等待时不闲聊。
【结束】("停止跟随""别跟着了",或丢失处理放弃时)
调用 chassis_raw 的 brake。
播报"跟随结束,当前朝向XX"(朝向可按历次旋转的代数和估计,left 记正、right 记负)。
结束 skill(此刻才允许对话 finish)。