机器人执行动作之前的安全检查模块Check

机器人的检查员

一、它是谁?它在哪?它干嘛的?

机器人软件里有一个模块,专门负责在指令真正执行之前做安全检查。就像机场安检------你上飞机之前,安检员会检查你带没带违禁品、机票对不对。这个模块就是机器人的「安检员」。

它位于整个项目的这个地方:

复制代码
interaction/src/scheduler/checker/
├── checker.h          ← 安检员「模板」(爸爸,定义接口)
├── t1_checker.h       ← 一种机型的安检员(儿子,具体实现)
├── t1_checker.cpp
├── q1_checker.h       ← 另一种机型的安检员(另一个儿子)
└── q1_checker.cpp

二、继承关系------爸爸和儿子

先看爸爸(checker.h),定义了安检员必须会的 5 个技能:

cpp 复制代码
class Checker {
 public:
  // 检查动画能不能做(招手、比心、跳舞等)
  virtual int32_t CheckAnimation(int32_t animation_id) = 0;

  // 检查移动能不能做(前进、后退、转圈等)
  virtual bool CheckMove(int32_t direction) = 0;

  // 检查跟随能不能开启/关闭
  virtual bool CheckFollowTaskCtrl(bool trigger) = 0;

  // 检查编排任务(开箱流程等)
  virtual bool CheckArrangeTask(const std::string& task_id) = 0;

  // 检查触摸有没有效(有人拍你、摸你)
  virtual bool CheckTouch(int32_t type) = 0;
};

= 0 意思是「纯虚函数」------爸爸只写名字不写内容,具体怎么检查由儿子来实现。

儿子继承爸爸:

cpp 复制代码
class T1Checker : public Checker {       // 儿子继承了爸爸
 public:
  int32_t CheckAnimation(int32_t animation_id) override;   // 重写:我自己的安检规则
  bool CheckMove(int32_t direction) override;
  bool CheckFollowTaskCtrl(bool trigger) override;
  bool CheckArrangeTask(const std::string& task_id) override;
  bool CheckTouch(int32_t type) override;
};

为什么要这样设计? 不同机型安检规则不一样。T1 能变形(四足↔双足),Q1 是人形,各自的"能不能做"判断不同。用继承,调用方只需要调 Checker 的接口,不用关心具体是哪款。


三、5 个对外接口一览

接口 干什么 谁调它
CheckAnimation(id) 要跳舞/招手/比心,先过安检 遥控 / 语音对话 / 开箱流程
CheckMove(direction) 要前进/后退/转圈,先过安检 遥控 / 语音对话
CheckFollowTaskCtrl(trigger) 开启/关闭跟随模式,先过安检 遥控
CheckArrangeTask(task_id) 开箱流程等编排任务,先过安检 开箱流程
CheckTouch(type) 有人摸你(轻拍/滑动),先过安检 触摸传感器(硬件触发)

所有指令,不管来源是遥控、语音、触摸还是内部流程,真正执行前都要先过安检。


四、最核心的接口:CheckAnimation ------ 安检流水线

这是最重要的方法。任何让你跳舞/招手/比心的请求,都走这条流水线。它有 6 道关卡,源码如下:

cpp 复制代码
int32_t T1Checker::CheckAnimation(int32_t animation_id) {

  // ====== 第①关:机器人正在关机吗? ======
  // 如果正在关机中,什么动画都别想做,直接拒绝
  if (StateManager::GetInstance()->GetSysState().shutdown_state != ShutDownState::kIdle) {
    AIMRTE_WARN("System is in shutdown state, ignore animation request, animation_id: {}", animation_id);
    return static_cast<int32_t>(AniErrCode::kFormNotSupportCurrAnimation);   // 返回 -1
  }

  // 把 App 传来的数字(比如 7)转成程序能理解的枚举(kDance)
  auto animation = static_cast<T1Animation>(animation_id);

  // ====== 第②关:当前形态(四足/双足)支持这个动画吗? ======
  // 比如"比心"只有双足能做,四足没有手,不支持
  if (not CheckAnimationSupport(animation)) {
    return static_cast<int32_t>(AniErrCode::kFormNotSupportCurrAnimation);   // 返回 -1
  }

  // ====== 第③关:四足变形条件满足吗? ======
  // 四足变双足,必须站着才能变,躺着/趴着不能变形
  if (not CheckQuadrupedTransformateCondition(animation)) {
    return static_cast<int32_t>(AniErrCode::kTransformateConditionNotMet);   // 返回 -3
  }

  // ====== 第④关:双足模式下,当前 MC 档位对吗? ======
  // 双足的 PresetMotion(招手、比心等)必须在 WBC 等特定档位下才能播放
  if (not CheckBipedAction()) {
    return static_cast<int32_t>(AniErrCode::kBipedActionNotSupportAni);      // 返回 -2
  }

  // ====== 第⑤关:坐/趴/模式切换不受电量限制,直接放行 ======
  // 坐下和趴下是安全动作,不管电量多少都让做
  if (animation == T1Animation::kSitDown || animation == T1Animation::kLieDown) {
    return static_cast<int32_t>(AniErrCode::kSuccess);   // 返回 0,直接放行
  }

  // 模式切换(室内/户外/超能力/搬运)也不受电量限制
  if (animation == T1Animation::MODE_CARRY) {
    if (StateManager::GetInstance()->GetMotionState().curr_robot_form != RobotForm::kQuadruped) {
      AIMRTE_INFO("搬运模式仅四足形态支持,当前形态不满足");
      return static_cast<int32_t>(AniErrCode::kFormNotSupportCurrAnimation);
    }
    return static_cast<int32_t>(AniErrCode::kSuccess);
  }
  if (animation == T1Animation::MODE_INDOORS || animation == T1Animation::MODE_OUTDOORS
      || animation == T1Animation::MODE_SUPERPOWER || animation == T1Animation::MODE_CARRY) {
    return static_cast<int32_t>(AniErrCode::kSuccess);
  }

  // ====== 第⑥关:电量太低? ======
  auto& pmu_state    = StateManager::GetInstance()->GetPmuState();
  // last_battery_level_audio 含义:
  //   0 = 电量 >30%(正常)  1 = 15-30%(偏低)
  //   2 = 5-15%(很低)      3 = 1-5%(极低)   4 = 1%(快没了)
  bool is_easy_limit = (!robot_config_.IsIgnoreLowBatteryLimit()
                         && pmu_state.last_battery_level_audio >= 4)
                        || pmu_state.is_charging;
  if (is_easy_limit) {
    // 电量接近耗尽(等级 >= 4),所有动画全部禁止
    AIMRTE_INFO("当前电量状态过低,限制动画执行,动画id: {}, ...", animation_id);
    return static_cast<int32_t>(AniErrCode::kFormNotSupportCurrAnimation);
  }

  bool is_complex_limit = (!robot_config_.IsIgnoreLowBatteryLimit()
                            && pmu_state.last_battery_level_audio >= 4)
                           || pmu_state.is_charging;
  if (is_complex_limit && !IsEasyMotion(animation)) {
    // 电量低时,只允许简单动作(招手、比心等),复杂动作(跳舞)拒绝
    AIMRTE_INFO("当前电量状态过低,限制复杂动作执行,动画id: {}, ...", animation_id);
    return static_cast<int32_t>(AniErrCode::kFormNotSupportCurrAnimation);
  }

  // 全部通过!
  return static_cast<int32_t>(AniErrCode::kSuccess);   // 返回 0
}

错误码说明

返回值 含义 谁返回的
0 (kSuccess) 通过 ✅ ---
-1 (kFormNotSupportCurrAnimation) 形态不支持 / 关机中 / 电量耗尽 ①②⑥
-2 (kBipedActionNotSupportAni) 双足当前档位不合法
-3 (kTransformateConditionNotMet) 四足变形条件不满足

五、第②关详解:CheckAnimationSupport

"这个动画,当前形态(四足/双足)能做吗?"

cpp 复制代码
bool T1Checker::CheckAnimationSupport(const T1Animation& animation) {
  // ====== 四足形态能做的动画(白名单) ======
  std::vector<T1Animation> quadruped_support_animations = {
    T1Animation::kGreet,             // 打招呼
    T1Animation::kRightHandshake,    // 右手握手
    T1Animation::kLeftHandshake,     // 左手握手
    T1Animation::kSitDown,           // 坐下
    T1Animation::kLieDown,           // 趴下
    T1Animation::kStandUp,           // 站起
    T1Animation::kTransformateRotate,// 旋转变形
    T1Animation::kEasyTransformate,  // 简易变形
    T1Animation::kProud,             // 骄傲
    T1Animation::kJoy,               // 喜悦
    T1Animation::kStretch,           // 伸懒腰
    T1Animation::kDance,             // 跳舞
    // ... 还有很多
    T1Animation::MODE_INDOORS,       // 室内模式
    T1Animation::MODE_OUTDOORS,      // 户外模式
    T1Animation::MODE_SUPERPOWER,    // 超能力模式
    T1Animation::MODE_CARRY,         // 搬运模式
  };

  // ====== 双足形态能做的动画(白名单) ======
  std::vector<T1Animation> biped_support_animations = {
    T1Animation::kGreet,             // 打招呼
    T1Animation::kRightHandshake,    // 右手握手
    T1Animation::kLeftHandshake,     // 左手握手
    T1Animation::kBothHandsMakeHeart,// 双手比心 ← 只有双足能做!
    T1Animation::kDance,             // 跳舞
    T1Animation::kDance_C,           // 跳舞C
    T1Animation::kDance_D,           // 跳舞D
    // ... 还有很多
    T1Animation::MODE_INDOORS,
    T1Animation::MODE_OUTDOORS,
    T1Animation::MODE_SUPERPOWER,
    T1Animation::MODE_CARRY,
  };

  // 获取当前机器人形态(四足还是双足?)
  auto curr_form = StateManager::GetInstance()->GetMotionState().curr_robot_form;

  if (curr_form == RobotForm::kQuadruped) {
    // 当前是四足 → 在四足白名单里找,找到了就通过
    return std::find(quadruped_support_animations.begin(),
                     quadruped_support_animations.end(),
                     animation) != quadruped_support_animations.end();
  } else if (curr_form == RobotForm::kBiped) {
    // 当前是双足 → 在双足白名单里找
    return std::find(biped_support_animations.begin(),
                     biped_support_animations.end(),
                     animation) != biped_support_animations.end();
  } else {
    // 四足也不是,双足也不是 → 未知形态,不支持
    AIMRTE_WARN("不支持形态curr_robot_form: {}", curr_form);
    return false;
  }
}

举例:四足形态请求"双手比心"(kBothHandsMakeHeart) → 不在四足白名单 → 拒绝(四足没有手!)


六、第③关详解:CheckQuadrupedTransformateCondition

"四足变双足,必须站着才能变,不能躺着变形。"

cpp 复制代码
bool T1Checker::CheckQuadrupedTransformateCondition(const T1Animation& animation) {
  // 如果不是四足,或者不是变形动画(旋转变形、简易变形)→ 不关这关的事,直接过
  if (StateManager::GetInstance()->GetMotionState().curr_robot_form != RobotForm::kQuadruped
      || (animation != T1Animation::kTransformateRotate
          && animation != T1Animation::kEasyTransformate)) {
    return true;   // 双足发起的请求、或者不是变形动画,这关不管
  }

  // 走到这里的:一定是「四足形态」发起了「变形动画」
  // 检查当前四足的姿势是不是允许变形
  auto curr_action_id = StateManager::GetInstance()->GetMotionState().curr_action_id;
  if (curr_action_id != aimdk_msgs::msg::McAction::QUADRUPED_STAND_DEFAULT        // 101 站立
      && curr_action_id != aimdk_msgs::msg::McAction::QUADRUPED_LOCOMOTION_DEFAULT  // 102 行走
      && curr_action_id != aimdk_msgs::msg::McAction::QUADRUPED_LOCOMOTION_TERRAIN  // 103 越障
      && curr_action_id != aimdk_msgs::msg::McAction::QUADRUPED_LOCOMOTION_RUN      // 112 奔跑
      && curr_action_id != aimdk_msgs::msg::McAction::QUADRUPED_GET_DOWN_DEFAULT    // 110 趴下
      && curr_action_id != aimdk_msgs::msg::McAction::STORE_DEFAULT                 // 1001 收纳
      && curr_action_id != aimdk_msgs::msg::McAction::QUADRUPED_SIT_DOWN_DEFAULT) { // 111 坐下
    // 以上姿势都不满足 → 拒绝变形
    AIMRTE_ERROR("Invalid action id: {}", curr_action_id);
    return false;
  }

  return true;   // 姿势合法,允许变形
}

总结:四足变形只能在站立/行走/越障/奔跑/趴下/收纳/坐下这几种姿势下进行。躺着、悬空等状态拒绝变形。


七、第④关详解:CheckBipedAction

"双足模式下,当前 MC 的档位能不能接收 PresetMotion?"

先理解两个概念:

  • 档位(Action):MC(运动控制)的工作模式。比如走路模式、WBC 模式、趴下模式。不同档位能做不同的事,就像汽车的不同档位------P 档不能踩油门走,D 档才能。
  • PresetMotion:预设动作片段。在 WBC 模式下插入播放一段动画,比如招手、比心、碰拳。它不是切换档位,而是"在当前档位里插播一条广告"。
cpp 复制代码
bool T1Checker::CheckBipedAction() {
  /*
    当形态是双足,上肢动作要求是 WBC
    双足变形从 WBC 切到双足行走,再变形,这部分需要 MC 实现
    检查只检查 WBC
  */
  auto curr_action_id = StateManager::GetInstance()->GetMotionState().curr_action_id; // MC 当前档位
  auto curr_form      = StateManager::GetInstance()->GetMotionState().curr_robot_form; // 当前形态

  // 如果是双足,且当前档位不在白名单里 → 拦截
  if (curr_form == RobotForm::kBiped
      && (curr_action_id != aimdk_msgs::msg::McAction::QUADRUPED_TO_BIPED           // 10  四足变双足中
          && curr_action_id != aimdk_msgs::msg::McAction::QUADRUPED_TO_BIPED_ROTATE   // 11  旋转四变双中
          && curr_action_id != aimdk_msgs::msg::McAction::BIPED_LOCOMOTION_DEFAULT    // 202 双足走路
          && curr_action_id != aimdk_msgs::msg::McAction::BIPED_LOCOMOTION_TERRAIN    // 203 双足越障
          && curr_action_id != aimdk_msgs::msg::McAction::BIPED_LOCOMOTION_WBC        // 300 全身控制 ← 最常用
          && curr_action_id != aimdk_msgs::msg::McAction::BIPED_LOCOMOTION_ANIMATION  // 301 动画模式
          && curr_action_id != aimdk_msgs::msg::McAction::BIPED_LOCOMOTION_RUN)) {    // 207 双足跑步
    return false;   // 档位不在白名单,拦截!
  }

  return true;   // 通过
}

白名单(允许播放 PresetMotion 的档位):

Action 什么时候
QUADRUPED_TO_BIPED 10 正在四足变双足(过渡态)
QUADRUPED_TO_BIPED_ROTATE 11 正在旋转四变双(过渡态)
BIPED_LOCOMOTION_DEFAULT 202 双足走路模式
BIPED_LOCOMOTION_TERRAIN 203 双足越障模式
BIPED_LOCOMOTION_WBC 300 双足全身控制 ← 最常用
BIPED_LOCOMOTION_ANIMATION 301 双足动画模式
BIPED_LOCOMOTION_RUN 207 双足跑步模式

四足不查这一关 ------因为判断条件第一行就是 curr_form == RobotForm::kBiped,四足形态进来直接 false,跳过。


八、第⑥关详解:电池保护

cpp 复制代码
// IsEasyMotion:判断是不是"简单动作"。简单动作耗电少,低电量也能做
bool T1Checker::IsEasyMotion(const T1Animation& animation) {
  // 招手、握手、比心、拍照摆Pose、碰拳、举手、放下 → 都是简单动作
  if (animation == T1Animation::kGreet || animation == T1Animation::kRightHandshake
      || animation == T1Animation::kLeftHandshake || animation == T1Animation::kBothHandsMakeHeart
      || animation == T1Animation::kPhotoPose_1 || animation == T1Animation::kPhotoPose_2
      || animation == T1Animation::kPhotoPose_3 || animation == T1Animation::kPhotoPose_4
      || animation == T1Animation::kPhotoThreeShot || animation == T1Animation::kRightHandPunch
      || animation == T1Animation::kLeftHandPunch || animation == T1Animation::kBothHandsCelebrate
      || animation == T1Animation::kLeftHandUp || animation == T1Animation::kRightHandUp
      || animation == T1Animation::kBothHandsUp || animation == T1Animation::kLeftHandDown
      || animation == T1Animation::kRightHandDown || animation == T1Animation::kBothHandsDown) {
    return true;
  }
  return false;   // 跳舞、变形等 → 复杂动作,耗电大
}

焊在第⑥关的逻辑里(前面已贴过完整代码):

  • 电量等级 >= 4(电量只剩 1%)→ 所有动画全禁
  • 电量低但不是极低 → 只允许简单动作(IsEasyMotion 返回 true 的那些),跳舞等复杂动作拒绝

九、其余 4 个检查接口

CheckMove ------ 移动安检

cpp 复制代码
bool T1Checker::CheckMove(int32_t direction) {
  // 关机中不让动
  if (StateManager::GetInstance()->GetSysState().shutdown_state != ShutDownState::kIdle) {
    AIMRTE_WARN("System is in shutdown state, ignore move command, direction: {}", direction);
    return false;
  }
  // 极低电量不让移动
  auto& pmu_state = StateManager::GetInstance()->GetPmuState();
  if ((!robot_config_.IsIgnoreLowBatteryLimit() && pmu_state.last_battery_level_audio >= 4)
      || pmu_state.is_charging) {
    AIMRTE_WARN("Battery level is critically low, ignore move command, ...");
    return false;
  }
  return true;
}

CheckFollowTaskCtrl ------ 跟随安检

cpp 复制代码
bool T1Checker::CheckFollowTaskCtrl(bool trigger) {
  // 关机中不让跟随
  if (StateManager::GetInstance()->GetSysState().shutdown_state != ShutDownState::kIdle) {
    AIMRTE_WARN("System is in shutdown state, ignore follow task control");
    return false;
  }
  // 极低电量不让开启跟随
  auto& pmu_state = StateManager::GetInstance()->GetPmuState();
  if ((!robot_config_.IsIgnoreLowBatteryLimit() && pmu_state.last_battery_level_audio >= 4)
      || pmu_state.is_charging) {
    AIMRTE_WARN("Battery level is critically low, ignore follow task control, ...");
    return false;
  }
  return true;
}

CheckArrangeTask ------ 编排任务安检

cpp 复制代码
bool T1Checker::CheckArrangeTask(const std::string& task_id) {
  if (StateManager::GetInstance()->GetSysState().shutdown_state != ShutDownState::kIdle) {
    AIMRTE_WARN("System is in shutdown state, ignore arrange task, task_id: {}", task_id);
    return false;
  }
  auto& pmu_state = StateManager::GetInstance()->GetPmuState();
  if ((!robot_config_.IsIgnoreLowBatteryLimit() && pmu_state.last_battery_level_audio >= 4)
      || pmu_state.is_charging) {
    AIMRTE_WARN("Battery level is critically low, ignore arrange task, ...");
    return false;
  }
  return true;
}

CheckTouch ------ 触摸安检(多一道关)

cpp 复制代码
bool T1Checker::CheckTouch(int32_t type) {
  // 关机中摸它没用
  if (StateManager::GetInstance()->GetSysState().shutdown_state != ShutDownState::kIdle) {
    AIMRTE_WARN("System is in shutdown state, ignore touch trigger, type: {}", type);
    return false;
  }

  // 被动模式(没上电,躺着不动)或阻尼模式下,触摸无效
  auto curr_action_id = StateManager::GetInstance()->GetMotionState().curr_action_id;
  if (curr_action_id == aimdk_msgs::msg::McAction::DAMPING_DEFAULT       // 阻尼模式(没力)
      || curr_action_id == aimdk_msgs::msg::McAction::PASSIVE_DEFAULT) { // 被动模式(瘫着)
    AIMRTE_WARN("Current action is DAMPING_DEFAULT or PASSIVE_DEFAULT, "
                "ignore touch trigger, action_id: {}", curr_action_id);
    return false;   // 机器人躺着不省人事,摸它没反应
  }

  // 极低电量也拒绝触摸
  auto& pmu_state = StateManager::GetInstance()->GetPmuState();
  if ((!robot_config_.IsIgnoreLowBatteryLimit() && pmu_state.last_battery_level_audio >= 4)
      || pmu_state.is_charging) {
    AIMRTE_WARN("Battery level is critically low, ignore touch trigger, ...");
    return false;
  }
  return true;
}

十、完整调用链路

复制代码
来源:遥控 / 语音说"跳个舞" / 开箱流程
  │
  │  PlayAnimation(id=7)  RPC 请求
  ▼
Scheduler::PlayAnimationService              [scheduler.cpp:286]
  │ log("Received PlayAnimation request with animation_id:7")
  │
  ├─ checker_->CheckAnimation(7)            ← 坐安检流水线
  │    │
  │    ├─ ① 关机中?→ 否
  │    ├─ ② 形态支持?→ kDance 双足四足都支持 ✅
  │    ├─ ③ 变形条件?→ 不是变形动画,跳过 ✅
  │    ├─ ④ CheckBipedAction → curr_action=300(WBC) 在白名单 ✅
  │    ├─ ⑤ 坐/趴/模式?→ 否,继续
  │    └─ ⑥ 电量?→ 40%,通过!✅
  │    return 0(成功)
  │
  ├─ Post 到工作线程
  │    │
  │    ▼
  │  Dispatcher::DispatchAnimation(7)        [dispatcher.cpp:473]
  │    ├─ CreateTaskAnimation(7) → 生成技能清单(Action + Audio + Motion)
  │    └─ WorkerManager::ExecTask → 工人按清单执行
  │
  └─ res.success = true (回复调用方:收到!)

十一、在机器人行业中的作用

这种「安检员」模式,在机器人行业里叫 前置条件检查(Precondition Check)看门狗(Gatekeeper)。几乎所有真正跑在机器人上的系统都有类似设计。

为什么重要?

机器人不像手机 App------App 崩了大不了闪退,机器人崩了会物理伤害

  • 没电的时候跳舞 → 动作做一半趴下 → 可能摔坏关节
  • 四足形态做双足动作 → MC 收到不认识的指令 → 可能失控
  • 关机中发动画 → 电机突然上电又断电 → 损坏驱动器
  • 躺着变形 → 关节卡死 → 维修费几万块

安检员就是挡在这些灾难前面的一道墙。 任何指令,不管什么来源,必须先证明"此刻做这件事是安全的",才能发给底层执行。

行业同类设计

领域 类似机制 说明
自动驾驶 Safety Monitor 变道/加速前检查周围是否有障碍物
工业机械臂 Interlock 互锁 防护门未关好,机械臂不能启动
无人机 Pre-arm Check GPS 信号不够、电量不足,拒绝起飞
波士顿动力 Atlas State Machine Guard 每个动作只在特定状态下允许执行
ROS2 导航栈 Behavior Tree Condition 导航目标不可达,拒绝规划路径

三层安全架构

复制代码
高层决策(AI / Agent):
  "用户说了'跳个舞',那就跳吧"

        ↓  指令

安检员:                             ← 我们讲的就是这个
  "等等!你是四足还是双足?电量够不够?关机了吗?"
  → 不安全的直接拒绝,不会传到底层

        ↓ 通过安检

底层执行(MC / HAL):
  "收到合法指令,开始控制电机"

决策层只管"用户想做什么",安检员判断"现在能不能做",执行层只管"怎么做到"。三层各司其职,任何一层出问题都不会直接造成物理伤害。


十二、总结

核心思想很简单:别让机器人在错误的状态下做错误的事。

  • 关机了不让做动画 → 做了也没用,MC 都关了
  • 四足不让比心 → 四足没有手
  • 趴着不让双足招手 → 趴着的档位不认 PresetMotion
  • 快没电了不让跳舞 → 保护电池,省点电
  • 变形必须站着 → 躺着变形会摔
相关推荐
五羟基己醛3 小时前
【Robotics】半小时入门具身智能之Win11下IsaacSim环境搭建
机器人·robot·具身智能·isaacsim
视***间4 小时前
算力筑基,智领人形机器人新时代 —— 英伟达 × 宇树科技携手推进具身智能,视程空间基于 NVIDIA 全栈算力产品助力机器人产业落地
人工智能·机器人·nvidia·机器狗·gpt-oss·视程空间·宇树机器人
某林2127 小时前
ROS2 机器人底盘调试避坑指南:从 `/odom` 丢失到彻底跑通的硬核排障实录
stm32·机器人·人机交互
才兄说9 小时前
机器人二次开发机器狗巡检?低电量自主回充
机器人
啵啵鱼爱吃小猫咪9 小时前
示教学习强化学习用的标准数据集
机器人·强化学习·示教学习
硅谷秋水10 小时前
Qwen-VLA:跨任务、环境与机器人形态的视觉-语言-动作统一建模
人工智能·深度学习·算法·计算机视觉·语言模型·机器人
叶子Talk12 小时前
COMPTUEX炸场:OpenAI杀入机器人,英特尔288核CPU首秀
机器人
J_Xiong011713 小时前
【WAM篇】21:RIGVid——让机器人“照着 AI 生成的视频“干活,零演示、零训练
机器人·wam
ZPC821013 小时前
前馈补偿原理 + 分类 + 公式 + 工程实现(配合 PID 使用,从根源减轻闭环收敛压力)
人工智能·分布式·机器人