Skip to content
控制模式

控制模式#

P7 使用控制模式决定后续运动命令的处理方式。单次关节目标通常选择 Controller.planning_control;连续目标跟踪使用 Controller.servo_control;停止发送目标后应切回 Controller.idle。重力补偿通过专用方法进入,不属于 Controller 枚举。

如何选择#

SDK 入口 ServiceState.fsm_state 适用任务 move_joint() 的行为
Controller.idle IDLE 不再接受普通运动目标;运动前后的默认停留状态 返回 False
Controller.planning_control PLANNING_CONTROL PTP 或 OMPL 单次关节运动 先规划,再执行轨迹
Controller.servo_control SERVO_CONTROL 连续关节目标或单个 Servo 目标 非阻塞时发送一帧 Servo 目标;阻塞时等待目标到达判据
Controller.mit_control FORCE_CONTROL 专项调试的低层 MIT 指令 发送位置、速度、前馈力矩和增益,不支持阻塞完成判据
enter_gravity_compensation_mode() GRAVITY_COMPENSATION 人工拖动、示教前的重力补偿 返回 False;该状态不接受 move_joint()

MIT 模式需要专项参数和现场评审

mit_control 会把 JointMoveOptions.torquekpkd 直接用于低层命令,并把 SDK 当前保存的 关节速度数组作为目标速度。数组长度错误还可能触发静默回退。没有与当前负载、安装方式和整机 版本匹配的参数集时,不要进入该模式。

当前公开 Controller 只有 idleservo_controlplanning_controlmit_control。线协议中仍可 观察到 POSITION_CONTROL,但 SDK 已移除对应的直接位置/PVT 客户入口。应用不应根据该状态名构造 未公开的控制命令。

switch_controller()#

client.switch_controller(
    controller: Controller,
    timeout_ms: int = 1000,
) -> bool

gRPC 和 DDS 均支持此方法。调用前服务必须可用,客户端还必须持有控制租约。SDK 在没有本地租约时会 尝试按默认参数申请一次,但多客户端系统应先显式调用 acquire_control(),以便明确租期和协调结果。

参数 类型 单位 默认值 规则
controller Controller 只能使用当前公开的四个枚举成员
timeout_ms int ms 1000 应为正数;gRPC 小于 50 ms 时按 50 ms RPC deadline 处理

SDK 总是发送阻塞式模式切换请求。服务端确认目标 FSM 状态已经到达后,方法返回 True;请求被拒绝、 控制权失效或通信超时时返回 False。返回后仍应读取 get_service_state(),因为状态缓存可能稍有延迟, 也可能在切换完成后因故障或其他事件再次变化。controller_state 是底层 controller 名称,确认模式时应 检查 fsm_state

from arm_p7_sdk import Controller

if not client.switch_controller(Controller.planning_control, timeout_ms=5000):
    raise RuntimeError("无法进入 planning_control;检查 SDK 日志和服务状态")

state = client.get_service_state()
if state is None or state.fsm_state != "PLANNING_CONTROL":
    raise RuntimeError("状态缓存尚未确认 PLANNING_CONTROL")

后端等待差异#

  • gRPC 从 idle 切到活动模式后最多再等待 0.5 秒稳定时间,其他切换最多等待 0.2 秒。 timeout_ms 已耗尽时会缩短这段本地等待;服务端已经完成的切换不会因此改回失败。
  • DDS 在服务端确认后固定等待相同的 0.5 秒或 0.2 秒,不从 timeout_ms 中扣除,因此方法总耗时可能 超过传入值。
  • 正在执行规划轨迹时,切出 planning_control 会被拒绝。release_control() 也不会取消已经接受的 轨迹。

enter_gravity_compensation_mode()#

client.enter_gravity_compensation_mode(timeout_ms: int = 1000) -> bool

此方法需要可用服务和控制权,gRPC、DDS 均支持。timeout_ms 单位为 ms;gRPC 对小于 50 ms 的值使用 50 ms RPC deadline,DDS 把该值交给 route 调用。两种后端都发送阻塞式切换请求,并在成功后分别追加 从 idle 离开时 0.5 秒、其他切换 0.2 秒的本地等待。成功返回 True 后, ServiceState.fsm_state 应变为 GRAVITY_COMPENSATION

进入重力补偿可能让机械臂在外力作用下移动。确认工具和负载安装牢固、运动范围内无人和障碍物、 实体急停可立即操作后,再托住机械臂并进入该模式。退出时调用:

if not client.switch_controller(Controller.idle, timeout_ms=5000):
    raise RuntimeError("无法退出重力补偿;保持现场警戒并检查当前状态")

重力补偿成功后,SDK 的本地 controller 缓存记为 idle,因为该模式没有对应的 Controller 枚举值。 随后调用 move_joint() 会返回 False;若要运动,必须显式切入 planning、Servo 或 MIT 模式。

只读取并确认模式#

以下代码不申请控制权、不切换模式,也不发送运动目标。它适合在操作前确认服务当前处于哪个状态。

from arm_p7_sdk import AirbotClient

with AirbotClient(host="P7_IP_ADDRESS", port=50071, backend="grpc") as client:
    state = client.get_service_state()
    if state is None:
        raise RuntimeError("服务状态缓存尚未建立")
    if not state.valid or not state.service_state:
        raise RuntimeError("服务状态不可用或已经过期")

    print("FSM:", state.fsm_state)
    print("controller:", state.controller_state)

DDS 后端的 ServiceState.valid 可能在健康连接的两个轮询周期之间短暂为 False,处理方式见 状态读取参考。模式切换失败时先停止下发新目标,再按 状态参考确认当前状态,并按 异常恢复区分急停、碰撞和未知错误。同名模式命令及确认口令见 SDK 最小可执行用例