2. C空间与构型空间:关节空间 vs 笛卡尔空间、C空间障碍物建模、C空间连通性

做机械臂路径规划,第一个绕不开的概念就是C空间。说白了,C空间就是描述机械臂所有可能姿态的集合。你想想看,一个六轴机械臂,每个关节都有一个角度范围,把这些角度组合起来,就是一个六维空间。嗯,这就是C空间的核心思想。

我个人习惯把C空间理解成「机械臂的姿势宇宙」。在这个宇宙里,每一个点都对应着机械臂的一个唯一姿态。听起来有点抽象?别急,我们一步步拆开看。

2.1 关节空间 vs 笛卡尔空间

先说说这两个空间的区别。关节空间,就是直接用关节角度来描述机械臂的状态。比如一个六轴臂,状态就是 (θ₁, θ₂, θ₃, θ₄, θ₅, θ₆)。笛卡尔空间呢,是用末端执行器的位置和姿态来描述,比如 (x, y, z, roll, pitch, yaw)。

我在项目中遇到过不少新手,上来就在笛卡尔空间里做路径规划,结果发现奇异性问题搞得头大。为什么会这样?因为笛卡尔空间里的直线运动,映射到关节空间可能是一条非常扭曲的曲线,甚至经过关节极限位置。

核心区别:
  • 关节空间:维度等于关节数,无奇异性,计算简单
  • 笛卡尔空间:直观易理解,但存在奇异性,计算复杂

我建议做路径规划时,优先在关节空间里做。原因很简单——关节空间是连续的、无奇异的。你想想看,每个关节角度都是独立变化的,不会出现「突然卡住」的情况。而在笛卡尔空间里,末端执行器经过奇异位形时,关节速度会趋近无穷大,这在物理上根本实现不了。

特性 关节空间 笛卡尔空间
维度 等于关节数(如6) 6(位置+姿态)
奇异性 无 存在奇异位形
直观性 不直观 直观
路径规划难度 低 高
避障计算 需转换 直接

不过,笛卡尔空间也有它的优势。比如你要让机械臂末端走一条直线轨迹,那在笛卡尔空间里描述就非常自然。我记得有一次做焊接路径规划,工件焊缝是直线,我直接在笛卡尔空间里插值,然后通过逆运动学转换成关节角度,效果很好。

我的经验:路径规划用关节空间,轨迹插值用笛卡尔空间。两者结合使用,才是工程实践中的正确姿势。

2.2 C空间障碍物建模

C空间障碍物,是路径规划里最核心的概念之一。说白了,就是把真实世界里的障碍物,映射到C空间里。真实空间里的一个点障碍物,在C空间里可能变成一个复杂的曲面。

为什么会这样?因为机械臂是一个多连杆机构,每个连杆都可能与障碍物碰撞。一个障碍物在真实空间里是固定的,但机械臂的不同姿态会导致不同的碰撞情况。把这些「会导致碰撞的姿态」全部收集起来,就构成了C空间障碍物。

我刚开始做这个的时候,觉得C空间障碍物建模特别难。后来发现,其实有几种经典方法:

  1. 离散采样法:在C空间里均匀采样,检查每个采样点是否碰撞。简单粗暴,但精度受采样密度影响。
  2. 包络体法:用球体、圆柱体等简单几何体包络机械臂和障碍物,计算碰撞检测更快。
  3. 距离场法:预先计算障碍物的距离场,在C空间里快速查询。
注意:C空间障碍物的维度等于关节数。六轴臂的C空间障碍物是六维的,无法直接可视化。我一般用二维或三维切片来观察。

我曾经踩过一个坑:用离散采样法时,采样分辨率设得太粗,结果路径规划出来的轨迹直接穿过了障碍物。后来我改用自适应采样,在障碍物附近加密采样点,才解决了这个问题。

这里给出一段简单的碰撞检测伪代码,帮你理解C空间障碍物的构建逻辑:

function isCollision(q, obstacles, robot):
    # q: 关节角度向量
    # obstacles: 障碍物列表
    # robot: 机械臂模型
    
    # 1. 正运动学:计算各连杆位置
    links = forwardKinematics(q, robot)
    
    # 2. 对每个连杆,检查是否与障碍物碰撞
    for link in links:
        for obstacle in obstacles:
            if checkCollision(link, obstacle):
                return True
    
    return False

# 构建C空间障碍物
function buildCSpaceObstacles(robot, obstacles, resolution):
    c_obstacles = []
    for each joint angle combination q:
        if isCollision(q, obstacles, robot):
            c_obstacles.append(q)
    return c_obstacles

实际工程中,我们不会真的去遍历所有角度组合。六轴臂每个关节分100份,那就是100⁶个点,算到天荒地老。一般用随机采样或者启发式搜索来构建近似的C空间障碍物。

2.3 C空间连通性

C空间连通性,决定了路径规划能不能找到解。简单说,如果起点和终点在C空间的同一个连通分量里,那路径就存在;否则,无解。

你想想看,真实空间里看起来很近的两个点,在C空间里可能隔着「一堵墙」。这堵墙就是C空间障碍物。有时候,机械臂需要绕很大一圈才能从起点到终点,就是因为C空间里这两个点不在同一个连通区域。

连通性判断:
  • 如果起点和终点在同一个连通分量 → 路径存在
  • 如果不在同一个连通分量 → 路径不存在,需要重新规划或调整目标

我记得有一次做码垛任务,机械臂要从A点抓取箱子放到B点。路径规划算法一直报错,说找不到路径。我检查了半天,发现是因为C空间里A点和B点被一个障碍物隔开了。后来我调整了机械臂的安装位置,才解决了这个问题。

C空间连通性分析,常用的方法有:

  • PRM(概率路图法):在C空间随机采样,构建连通图,然后查询起点终点是否连通。
  • RRT(快速随机搜索树):从起点开始生长树,看能不能长到终点。
  • 连通分量标记:对离散化的C空间做连通分量分析。

下面这张图展示了C空间、C空间障碍物和连通性的关系:

C空间结构示意图 C空间(关节空间) C障碍物 C障碍物 自由空间(白色区域) 起点 终点 可行路径 连通性分析 连通分量 1 起点 可达点 连通分量 2 终点 不可达点 连通性判断 起点和终点在同一连通分量 → 路径存在 不在同一连通分量 → 路径不存在,需调整 C空间障碍物将自由空间分割成多个连通分量 路径规划的目标:在同一个连通分量内找到连接起点和终点的连续路径

从这张图可以看出,C空间障碍物把自由空间分割成了多个连通分量。起点和终点如果在同一个分量里,路径规划就能找到解;如果不在,那就需要重新考虑任务规划了。

工程建议:在做路径规划之前,先做一次连通性检查。如果起点和终点不在同一个连通分量,直接报错,避免浪费计算资源。我一般在系统初始化阶段就构建好C空间连通图,后续查询就是O(1)的复杂度。

嗯,C空间的概念就讲到这里。记住一句话:路径规划的本质,就是在C空间的自由区域里,找到一条连接起点和终点的连续路径。理解了C空间,你就掌握了路径规划的钥匙。