尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于MATLAB的六自由度机械臂避障仿真与碰撞检测实现

基于MATLAB的六自由度机械臂避障仿真与碰撞检测实现 简介这是一个面向机器人控制学习者的MATLAB机械臂控制仿真源码重点演示多自由度机械臂在复杂障碍物环境中完成避障与动作规划覆盖机械臂动力学建模、Simulink仿真环境搭建、PID闭环控制、逆动力学解算与路径规划等核心环节。适合自动化、机器人方向的在校学生与工程师用来验证控制算法、理解关节空间与工作空间的转换关系。资源为zip压缩包内部仅含1个m文件大小约5KB代码集中且注释清晰便于直接阅读、修改和调试。目前已有185人学习下载。通过该源码可以掌握多自由度机械臂的关节坐标设置、重力/摩擦力等物理效应补偿方式、基于距离传感器的避障算法以及三维动态轨迹可视化方法还能根据仿真中实时反馈的关节响应调整控制参数为进一步扩展自由度或优化控制性能提供了可运行的基础模板。1. 自由度机械臂控制仿真的本质穿过障碍物不是画一根直线第一次在 MATLAB 里做自由度机械臂控制仿真的人最容易看见的现象是“穿模”末端执行器轨迹画得笔直大臂和小臂却把障碍物扎了进去。原因是默认轨迹插值只约束末端位置没有约束其他连杆自由度越多的机械臂这种假通过越难被发现。这篇文章按真实项目里最常见的一套做法讲清楚如何用 MATLAB 完成六自由度机械臂建模、避障路径规划、碰撞检测和动态显示并给出能直接改、直接跑的源码片段。适合做机械臂抓取、搬运和障碍穿越仿真的学生、算法工程师以及现场调试机械臂的机器人工程师。2. 用 MATLAB 建六自由度机械臂模型DH 参数、正逆解与 qlim 设置2.1 六自由度机械臂 DH 参数表自由度到底写在哪个变量里六自由度机械臂的仿真源码第一步永远是运动学建模。在 Robotics Toolbox for MATLAB 里一个旋转关节只需要四个参数决定a是相邻关节轴的公垂线长度alpha是绕 X 轴的连杆扭角d是沿 Z 轴的偏置qlim才是真正让“自由度”发挥限制作用的变量——每个关节允许旋转的范围。下面这组参数是一套用于演示的 6R 关节型机械臂不精确对应任何一家厂商的产品但结构足够用来做避障仿真连杆d(m)a(m)alpha(rad)theta offset(rad)10.3330pi/20200.190-pi/2300.216pi/2040.150-pi/2050.10pi/2060.1000写进 MATLAB 时每个 Link 一行qlim不要乱填它决定后面模拟机械臂穿过障碍物时关节空间的可达范围% dof6_model.m % Link 参数按顺序写入d, a, alpha, offset, qlim L(1) Link(d, 0.333, a, 0, alpha, pi/2, offset, 0, qlim, [-pi pi]); L(2) Link(d, 0, a, 0.19, alpha, 0, offset, -pi/2, qlim, [-pi pi]); L(3) Link(d, 0, a, 0.216, alpha, pi/2, offset, 0, qlim, [-pi pi]); L(4) Link(d, 0.15, a, 0, alpha, -pi/2, offset, 0, qlim, [-pi pi]); L(5) Link(d, 0.1, a, 0, alpha, pi/2, offset, 0, qlim, [-pi pi]); L(6) Link(d, 0.1, a, 0, alpha, 0, offset, 0, qlim, [-pi pi]); robot SerialLink(L, name, dof6-arm);这里的offset会被叠加到关节角上模拟机械臂源码里常见的零点标定。很多仿真发散问题不是出现在算法层而是 DH 参数里某个alpha符号写反了导致肩关节镜像逆解收敛到另一个完全不同的构型。2.2 用 SerialLink 建模型并验证正逆解模型建好以后先做一次正逆解闭环确认 DH 参数写对了再开始做避障路径。正运动学是把关节角变成末端位姿逆运动学正好相反都是机械臂控制仿真的地基% fk_ik_check.m q0 [0, -pi/4, 0, pi/3, -pi/4, 0]; % 初始关节角 T_end robot.fkine(q0); % 正运动学 q_ik robot.ikcon(T_end, q0); % 带初值迭代逆解 fprintf(位置误差: %.3e m\n, norm(T_end.t - robot.fkine(q_ik).t));ikcon是迭代逆解不需要机械臂满足球腕结构比ikine6s适用范围更广。代价是它对初值敏感同一个末端位姿对应多组逆解如果初值落在另一个“分支”上得到的关节角可能跨越很大的角度表现在动态效果里就是机械臂路径突然跳动。验证时看两点一是位置误差能否到 1e-6 量级二是q_ik是否落在qlim内。前者说明 DH 参数和正解一致后者说明这一组逆解在机械臂的真实工作范围里。2.3 关节空间与笛卡尔空间的插值选择自由度约束在哪里起作用穿过障碍物的路径通常不是一条直线而是绕障碍物走的曲线。生成曲线后有两种插值方式我一般先用关节空间插值因为它不会因为腕部奇异产生关节速度突变% joint_traj_example.m q_start [0, -pi/4, 0, pi/3, -pi/4, 0]; q_end [0, pi/6, -pi/3, pi/4, pi/6, pi/3]; tvec 0:0.05:2; qtraj jtraj(q_start, q_end, tvec); % 五次多项式关节插补对应地笛卡尔空间插值会直接生成末端位姿序列T1 robot.fkine(q_start); T2 robot.fkine(q_end); cpath ctraj(T1, T2, length(tvec));插值对象优势风险关节空间轨迹平滑不会因为奇异点爆炸末端路径不可控可能绕远路笛卡尔空间末端走直线或圆弧工艺上好理解接近奇异时逆解跳变仿真发散最常见实际做障碍穿越时我建议把势场法生成的路径先放到笛卡尔空间检查一次确认末端没有扎进障碍再转成关节轨迹做动态仿真。检查用到的碰撞检测就是下一章的核心。3. 机械臂避障路径在 MATLAB 里的实现势场规划与连杆碰撞检测3.1 碰撞检测先于插值把六自由度机械臂退化成连杆线段“模拟机械臂穿过障碍物的动态效果”里“穿过”有两个意思一个是末端从障碍物旁边通过另一个是整条机械臂都不和障碍物相交。后者才是真实的避障。把机械臂每个连杆看成一段线段是 MATLAB 仿真里最常用的简化做法。function pts linkPoints(robot, q) % 把旋转关节状态 q 转换为连杆线段端点 pts zeros(robot.n 1, 3); T robot.base; pts(1,:) T.t; % 基座位置 for i 1:robot.n T T * robot.links(i).A(q(i)); % 逐个关节累乘 pts(i1,:) T.t; % 第 i 个关节坐标系原点 end endlinkPoints返回从基座到末端一共 7 个点每两个相邻点组成一段连杆。之后每一段都和障碍物球体做距离判断function hit checkCollision(p1, p2, center, r) % p1 p2: 连杆两端点, center: 球心, r: 球半径 v p2 - p1; w center - p1; t dot(w, v) / dot(v, v); t min(1, max(0, t)); % 投影点限制在线段内 closest p1 t * v; hit norm(closest - center) r 0.02; % 0.02 是连杆半径补偿 end参数0.02是连杆半径和额外安全距离的总和实际机械臂越粗这个值应该越大。只检查末端会漏掉大臂只检查两个点在球外也会漏掉整段穿入所以必须遍历所有连杆段并计算投影点距离。这种算法比导入三维网格再求交快得多足够支撑实时动态显示。3.2 人工势场法生成穿过障碍物的中间节点拿到碰撞检测函数之后还需要生成一条不撞障碍物的路径。人工势场法是视觉仿真里最直观的方案目标点产生引力障碍物产生斥力路径沿着合力方向前进。function path planAttRep(start, goal, obs) % obs [x y z r] 球心坐标和半径 path start(:); pos start(:); step 0.03; % 末端步长 k_att 1.0; % 引力系数 k_rep 0.3; % 斥力系数 d0 0.18; % 斥力影响半径 for iter 1:3000 dist_g norm(pos - goal(:)); if dist_g 0.02, break; end F_att k_att * (goal(:) - pos) / dist_g; dist_o norm(pos - obs(1:3)); F_rep zeros(3, 1); if dist_o d0 F_rep k_rep * (1/dist_o - 1/d0) ... / (dist_o^3) * (pos - obs(1:3)); end pos pos step * (F_att F_rep); path [path; pos(:)]; end end这个算法的缺点是会有局部极小点比如障碍物正好挡在目标点前方且斥力大于引力时机械臂会停在原地抖动。解决方法是把势场法结果作为初始路径再做一次碰撞检查。实际工程里更稳的是 RRT 或 RRTConnect但势场法胜在代码短、动态效果好适合先跑通整个仿真链路。生成笛卡尔路径后还需要把每个点位姿转成关节角然后用linkPoints检查整机是否碰撞% plan_and_check.m T1 robot.fkine(q_start); T2 robot.fkine(q_end); path_xyz planAttRep(T1.t, T2.t, obs); q_path zeros(size(path_xyz, 1), 6); q_current q_start; for i 1:size(path_xyz, 1) T_target eye(4); T_target(1:3, 1:3) T2.R; % 保持目标姿态 T_target(1:3, 4) path_xyz(i, :); q_current robot.ikcon(T_target, q_current); q_path(i, :) q_current; end这里每一步逆解都用上一步的关节角作为初值能在一定程度上保持关节空间连续性。3.3 碰撞检测放在逆解之前还是之后一个容易漏检的顺序问题很多新手把碰撞检测放在逆解之前只判断末端位置是否在障碍物外面。这当然更快但对六自由度机械臂来说不够因为中间四个关节完全可能扫过障碍物。检测时机优点缺点只检测末端轨迹计算量小大臂小臂全部漏检末端位置加连杆线段检测能覆盖典型工况无法处理复杂形状物体完整三维网格碰撞精度高仿真速度慢不适合实时动画我一般把碰撞检测放在逆解之后构成“逆解-正解-检测-修正”的闭环function feasible isPathFeasible(robot, q_path, obs) feasible true; for i 1:size(q_path, 1) pts linkPoints(robot, q_path(i, :)); for j 1:size(pts, 1) - 1 if checkCollision(pts(j, :), pts(j1, :), obs(1:3), obs(4)) feasible false; return; end end end end如果返回false就减小step重新规划或者调整斥力系数。这样写出来的源码把运动学、碰撞检测、路径规划三个模块分开后面换 DH 参数或者换障碍物半径都不用动主框架。4. 模拟机械臂穿过障碍物的动态效果动画、参数表与仿真发散排查4.1 动态显示用 bot.plot 把机械臂路径变成可录制动画有了q_path下一步是让它动起来。这时候直接robot.plot(q_path)会有两个问题路径点太疏看起来像瞬移障碍物没有画出来无法判断是否真实穿越。先补一个画球函数function drawSphere(center, radius) [X, Y, Z] sphere(30); surf(center(1) radius * X, center(2) radius * Y, ... center(3) radius * Z, FaceAlpha, 0.35, ... EdgeColor, none, FaceColor, [0.8 0.4 0.2]); end然后用jtraj在路径点之间加密生成平滑的关节轨迹q_smooth q_path(1, :); for i 2:size(q_path, 1) q_smooth [q_smooth; jtraj(q_path(i-1, :), q_path(i, :), 10)]; end figure(Color, w); hold on; axis equal; drawSphere(obs(1:3), obs(4)); robot.plot(q_smooth, fps, 30, trail, r-);需要保存成源码级演示视频时可以用getframe逐帧写进 MPEG-4 文件wr VideoWriter(pass_obstacle.mp4, MPEG-4); wr.FrameRate 30; open(wr); for i 1:size(q_smooth, 1) robot.plot(q_smooth(i, :), fps, 30); writeVideo(wr, getframe(gcf)); end close(wr);getframe会抓当前 axes 内容所以drawSphere画的障碍物会一起录进视频。此时看到的“动态效果”已经不是末端直线而是整条机械臂在势场路径引导下绕过球体的完整运动。4.2 穿越仿真里最常调的 3 个参数参数调不好最常见结果就是仿真发散或者穿模。下面这张表是速查项参数默认值调整方向step0.03m步长过大容易漏检过小路径点太多、动画变慢0.02m连杆半径补偿越接近真实机械臂外径越好但必须留安全余量k_rep / d00.3 / 0.18障碍物挡路时增大路径震荡时减小qlim[-pi, pi]收敛不到路径时放宽真机限位根据数据表缩窄仿真发散出现时先不要改控制器先看相邻两帧的关节角是否发生跳变。逆解多解切换会让某个关节角瞬间变化超过 pi 弧度表现为机械臂从画面下方闪到上方。代码里可以加一个检测dq diff(q_smooth); dq_wrapped atan2(sin(dq), cos(dq)); % 映射到 [-pi, pi] if max(abs(dq_wrapped(:))) pi/2 warning(关节角发生跳变检查逆解初值或路径规划); end4.3 机械臂偏差来源逆解失败和碰撞漏检的区别机械臂偏差这个词在仿真里常被混用。一类是逆解误差ikcon迭代没收敛到目标位姿末端静态误差达到毫米甚至厘米级体现在动画里是末端在目标点附近漂移另一类是动态路径偏差路径规划或插值没有覆盖真实机械臂运动导致连杆扫过障碍物。前者要回到 2.2 节的正逆解闭环把位置误差打印出来。如果误差大于 1e-3先检查qlim和alpha。后者则要把碰撞检测从末端扩展到全部连杆段再用isPathFeasible对q_smooth做一次离线批量检查。动态穿越通过不等于动态效果安全只有离线逐帧碰撞检测也通过才能在后续接真机。5. 进阶验证从关节轨迹到 Simulink 仿真和 ROS 机械臂开发验证关节轨迹最直接的办法是把q_smooth输出成timeseries交给 Simulink 的 From Workspace 模块。在 MATLAB 工作区执行Q timeseries(q_smooth, tvec);在 Simulink 里添加 From Workspace 模块Data 参数填Q输出就是按时间排列的六维关节角。把输出接给 Simscape 机械臂模型或者接给一个简单的六自由度关节驱动模块就能对比原始控制量和实际机械臂位姿的偏差。这样做的意义在于机械臂穿过障碍物的动画由 MATLAB 图形引擎渲染Verification 则由 Simulink 的数值积分完成两者互相验证。如果项目后续走 ROS 机械臂开发常见做法是先把关节轨迹存成 CSV再写一个 ROS 节点发布joint_states。在 RVIZ 里加载同 URDF 模型后逐帧查看连杆是否和障碍物 Marker 相交。URDF 的几何模型比linkPoints的线段模型精确所以能发现 0.02m 补偿半径不够的情况。我一般把 MATLAB 仿真结果当作快速原型ROS 和 gazebo 仿真作为二次验证。最后一层验证是在物理真机上做。无论是六自由度还是七自由度机械臂都要在低速模式下先空跑一遍路径观察电机电流和关节跟随误差。仿真里 0.02m 的安全余量真机上至少放大到 0.05m因为 DH 标定误差和控制器延迟会让实际轨迹滞后于规划轨迹。调试时把这个余量暴露成输入参数而不是写死在碰撞检测函数里后续换机械臂型号只需要改一个变量。本文还有配套的精品资源点击获取
返回列表