You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MoveIt Task Constructor:Connect与MoveRelative碰撞设置冲突致规划失败

问题描述

我正在用MoveIt Task Constructor(MTC)实现装配任务的取放流水线,卡在放置阶段——部件即将接触主装配体的时候。我需要给两个连续阶段设置不同的碰撞规则:

  • Connect阶段:不允许碰撞
  • MoveRelative(接近)阶段:允许碰撞(预期会产生接触)

我用ModifyPlanningScene修改碰撞矩阵,但规划完整轨迹时IK求解器找不到解。我猜测问题出在Connect会双向传播约束,导致它和MoveRelative阶段的碰撞约束冲突,进而引发规划失败。

日志信息如下:

[mtc_node-1]     -  0 →   0 →   -  0 / lift object
[mtc_node-1]     -  0 →   0 ←   0  - / move to predeliver
[mtc_node-1]     0  - ←   0 ←   0  - / allow collision PRS - piece
[mtc_node-1]     0  - ←   0 ←   0  - / approach dest
[mtc_node-1]     0  - ←   0 →   -  0 / dest pose IK
[mtc_node-1]       0  - ←   0 →   -  0 / generate place pose
[mtc_node-1] Failing stage(s):
[mtc_node-1] grasp pose IK (0/1):  no IK found

以下是定义ConnectModifyPlanningSceneMoveRelative和IK阶段的代码片段,有没有其他组件排列方式能让IK求解成功?

// ---- *               Move to Predeliver               * ----
auto stage_move_to_predeliver = std::make_unique<mtc::stages::Connect>(
    "move to predeliver",
    mtc::stages::Connect::GroupPlannerVector{{arm_group_name, sampling_planner},
                                             {hand_group_name, interpolation_planner}});
stage_move_to_predeliver->setTimeout(15.0);
stage_move_to_predeliver->properties().configureInitFrom(mtc::Stage::PARENT);
task.add(std::move(stage_move_to_predeliver));

// ---- *               Allow Collision Stage (PRS - Piece)              * ----

auto stage_allow_piece_PRS = std::make_unique<mtc::stages::ModifyPlanningScene>("allow collision PRS - piece");
stage_allow_piece_PRS->properties().configureInitFrom(mtc::Stage::INTERFACE);
stage_allow_piece_PRS->allowCollisions(object, "PRS001", true);
stage_place_ptr = stage_allow_piece_PRS.get();
task.add(std::move(stage_allow_piece_PRS));

// ---- *               Approach Destination Stage               * ----

auto stage_approach_dest =
    std::make_unique<mtc::stages::MoveRelative>("approach dest", cartesian_planner);
// clang-format on
stage_approach_dest->properties().set("marker_ns", "approach_dest");
stage_approach_dest->properties().set("link", ee_frame);
stage_approach_dest->properties().configureInitFrom(mtc::Stage::PARENT, {"group"});
if (use_only_arm){
    stage_approach_dest->properties().set("group", only_arm_group);
}
stage_approach_dest->setMinMaxDistance(0.1, 0.4);

stage_approach_dest->setDirection(vec_approach_dest);
task.add(std::move(stage_approach_dest));  

geometry_msgs::msg::PoseStamped dest_pose_msg;
dest_pose_msg = getFramePose(
    dest_frame,       // target frame (world)
    dest_frame,          // TF frame name
    rclcpp::Duration::from_seconds(1.0));

// Sample place pose
auto stage_ik_dest = std::make_unique<mtc::stages::GeneratePose>("generate place pose");
stage_ik_dest->properties().configureInitFrom(mtc::Stage::PARENT);
stage_ik_dest->properties().set("marker_ns", "place_pose");
// stage_ik_dest->setObject(object);
stage_ik_dest->setPose(dest_pose_msg);
stage_ik_dest->setMonitoredStage(stage_place_ptr);

auto ik_dest = std::make_unique<mtc::stages::ComputeIK>("dest pose IK", std::move(stage_ik_dest));
ik_dest->setMaxIKSolutions(8);
ik_dest->setMinSolutionDistance(0.24);
ik_dest->setIKFrame(ee_frame);  // "tool0"

// Pipe required properties
ik_dest->properties().configureInitFrom(mtc::Stage::PARENT, { "eef", "group", "ik_frame" });
ik_dest->properties().configureInitFrom(mtc::Stage::INTERFACE, { "target_pose" });
// ik_dest->setIgnoreCollisions(true);
task.add(std::move(ik_dest));
解决方案

1. 用子任务隔离碰撞约束

Connect的双向约束传播会把后续的碰撞规则反向传递到前面阶段,导致冲突。可以把MoveRelative和IK阶段包装成子任务容器,在子容器开头添加允许碰撞的ModifyPlanningScene,让碰撞规则仅在子容器内部生效,不影响外部的Connect阶段:

// 创建子任务容器
auto place_subtask = std::make_unique<mtc::Task>("place_subtask");

// 子任务内添加允许碰撞阶段
auto stage_allow_piece_PRS = std::make_unique<mtc::stages::ModifyPlanningScene>("allow collision PRS - piece");
stage_allow_piece_PRS->properties().configureInitFrom(mtc::Stage::PARENT);
stage_allow_piece_PRS->allowCollisions(object, "PRS001", true);
place_subtask->add(std::move(stage_allow_piece_PRS));

// 子任务内添加MoveRelative阶段
auto stage_approach_dest = std::make_unique<mtc::stages::MoveRelative>("approach dest", cartesian_planner);
// ... 保留原有的stage_approach_dest配置代码 ...
place_subtask->add(std::move(stage_approach_dest));

// 子任务内添加IK相关阶段
auto stage_ik_dest = std::make_unique<mtc::stages::GeneratePose>("generate place pose");
// ... 保留原有的stage_ik_dest配置代码 ...
auto ik_dest = std::make_unique<mtc::stages::ComputeIK>("dest pose IK", std::move(stage_ik_dest));
// ... 保留原有的ik_dest配置代码 ...
place_subtask->add(std::move(ik_dest));

// 将子任务添加到主任务
task.add(std::move(place_subtask));

2. 单独给IK阶段开启碰撞忽略

取消注释ik_dest->setIgnoreCollisions(true);,让IK求解器直接忽略碰撞——毕竟放置阶段的目标姿态本身就是需要接触的,无需碰撞检查。同时保留ModifyPlanningSceneMoveRelative阶段允许碰撞,避免笛卡尔规划失败。

3. 限制Connect阶段的约束传播方向

强制Connect仅向前连接,禁止反向传播约束:

stage_move_to_predeliver->setDirection(mtc::stages::Connect::FORWARD);

这样后续的碰撞规则不会反向影响Connect阶段的无碰撞要求。

4. 验证目标姿态的合理性

日志显示失败的是grasp pose IK,和当前放置阶段的代码不符,可能是日志关联错误。可以单独测试IK阶段的目标姿态,确认在允许碰撞的情况下是否有解,再逐步整合到流水线中。

内容的提问来源于stack exchange,提问作者Walter Ronaldo Cachi Delgado

火山引擎 最新活动