机器人运动学基础理论
1. 什么是机器人运动学
机器人运动学是研究机器人关节运动与其末端执行器位置和姿态之间的关系的学科。它主要分为正运动学和逆运动学两部分。正运动学是从已知的关节角度计算末端执行器的位置和姿态,而逆运动学则是从已知的末端执行器位置和姿态计算关节角度。在机器人设计和控制中,运动学是基础性的内容,对机器人的路径规划、运动控制和任务执行具有重要意义。
1.1 正运动学
正运动学是从已知的关节角度出发,计算机器人末端执行器的位置和姿态。这通常涉及到机器人的连杆参数(如长度、旋转角度等)和关节变量(如关节角度)的数学模型。在MATLAB Robotics System Toolbox中,可以通过创建机器人模型并使用内置函数来实现正运动学的计算。
1.1.1 坐标系和变换矩阵
在机器人运动学中,坐标系的定义至关重要。通常,每个连杆都有自己的局部坐标系,而机器人的整体运动则需要将这些局部坐标系转换到全局坐标系中。这可以通过齐次变换矩阵来实现。齐次变换矩阵是一个4x4的矩阵,用于描述一个坐标系相对于另一个坐标系的位置和姿态。
% 创建一个齐次变换矩阵,表示坐标系1相对于坐标系0的变换
% 平移向量 [x, y, z] 和旋转矩阵 R
x = 1; y = 2; z = 3;
R = [1 0 0; 0 1 0; 0 0 1]; % 旋转矩阵,这里假设没有旋转
T = [R, [x; y; z]; 0 0 0 1]; % 齐次变换矩阵
% 输出齐次变换矩阵
disp('齐次变换矩阵 T:');
disp(T);
1.1.2 串联机器人正运动学
串联机器人是最常见的机器人类型,其各个连杆依次连接。在MATLAB Robotics System Toolbox中,可以通过创建一个rigidBodyTree
对象来表示串联机器人的结构,并使用fk
函数来计算正运动学。
% 创建一个串联机器人模型
robot = rigidBodyTree;
% 添加连杆
body1 = rigidBody('body1');
body2 = rigidBody('body2');
body3 = rigidBody('body3');
% 设置连杆的变换关系
body1.Joint = rigidBodyJoint('revolute', 'xyz');
body2.Joint = rigidBodyJoint('revolute', 'xyz');
body3.Joint = rigidBodyJoint('revolute', 'xyz');
% 设置连杆的平移和旋转参数
body1.T = trvec2tform([0 0 1]); % 平移向量 [0, 0, 1]
body2.T = trvec2tform([1 0 0]); % 平移向量 [1, 0, 0]
body3.T = trvec2tform([0 1 0]); % 平移向量 [0, 1, 0]
% 将连杆添加到机器人模型中
addBody(robot, body1);
addBody(robot, body2, 'body1');
addBody(robot, body3, 'body2');
% 设置关节角度
jointAngles = [0, pi/4, -pi/4];
% 计算正运动学
pose = fk(robot, jointAngles);
% 输出末端执行器的姿态
disp('末端执行器的齐次变换矩阵:');
disp(pose);
1.2 逆运动学
逆运动学是从已知的末端执行器位置和姿态出发,计算使机器人达到该位置和姿态的关节角度。这通常是一个非线性问题,需要使用数值方法或解析方法来求解。在MATLAB Robotics System Toolbox中,可以通过创建一个inverseKinematics
对象并使用ik
函数来实现逆运动学的计算。
1.2.1 逆运动学的基本概念
逆运动学问题可以分为以下几种类型:
-
解析逆运动学:通过解析方法直接求解关节角度。这种方法通常适用于结构简单的机器人。
-
数值逆运动学:通过数值方法(如梯度下降、优化算法等)逐步逼近关节角度。这种方法适用于结构复杂的机器人。
1.2.1.1 解析逆运动学
解析逆运动学通过数学公式直接求解关节角度。对于简单的两关节平面机器人,解析逆运动学可以通过三角函数来实现。
% 两关节平面机器人
% 已知末端执行器位置 (x, y)
x = 2;
y = 2;
% 连杆长度
L1 = 2;
L2 = 2;
% 计算关节角度
theta1 = atan2(y, x) - acos((x^2 + y^2 - L1^2 - L2^2) / (2 * L1 * L2));
theta2 = atan2(sqrt(x^2 + y^2 - L1^2 - L2^2), (L1 + L2 * cos(theta1)));
% 输出关节角度
disp('关节1的角度 (theta1):');
disp(theta1);
disp('关节2的角度 (theta2):');
disp(theta2);
1.2.1.2 数值逆运动学
数值逆运动学通过迭代方法逐步逼近关节角度。在MATLAB Robotics System Toolbox中,可以使用inverseKinematics
对象来实现这一过程。
% 创建一个逆运动学对象
ik = inverseKinematics;
% 设置目标姿态
targetPose = trvec2tform([1, 2, 3]) * eul2tform([pi/4, -pi/4, 0], 'ZYX');
% 设置机器人模型
robot = rigidBodyTree;
body1 = rigidBody('body1');
body2 = rigidBody('body2');
body3 = rigidBody('body3');
% 设置连杆的变换关系
body1.Joint = rigidBodyJoint('revolute', 'xyz');
body2.Joint = rigidBodyJoint('revolute', 'xyz');
body3.Joint = rigidBodyJoint('revolute', 'xyz');
% 设置连杆的平移和旋转参数
body1.T = trvec2tform([0 0 1]);
body2.T = trvec2tform([1 0 0]);
body3.T = trvec2tform([0 1 0]);
% 将连杆添加到机器人模型中
addBody(robot, body1);
addBody(robot, body2, 'body1');
addBody(robot, body3, 'body2');
% 求解逆运动学
jointAngles = ik(robot, targetPose, 'body3');
% 输出关节角度
disp('求解的关节角度:');
disp(jointAngles);
1.3 机器人运动学的常见问题
在实际应用中,机器人运动学常常遇到一些问题,如奇异点、多解性等。这些问题需要通过适当的算法和技巧来解决。
1.3.1 奇异点
机器人在某些特定的关节角度下,可能会出现奇异点。在奇异点处,机器人的某些自由度会失去控制能力,导致逆运动学问题无法求解。在MATLAB Robotics System Toolbox中,可以通过检测雅可比矩阵的秩来判断机器人是否处于奇异点。
1.3.1.1 检测奇异点
% 创建一个机器人模型
robot = rigidBodyTree;
body1 = rigidBody('body1');
body2 = rigidBody('body2');
body3 = rigidBody('body3');
% 设置连杆的变换关系
body1.Joint = rigidBodyJoint('revolute', 'xyz');
body2.Joint = rigidBodyJoint('revolute', 'xyz');
body3.Joint = rigidBodyJoint('revolute', 'xyz');
% 设置连杆的平移和旋转参数
body1.T = trvec2tform([0 0 1]);
body2.T = trvec2tform([1 0 0]);
body3.T = trvec2tform([0 1 0]);
% 将连杆添加到机器人模型中
addBody(robot, body1);
addBody(robot, body2, 'body1');
addBody(robot, body3, 'body2');
% 设置关节角度
jointAngles = [0, pi/2, 0];
% 计算雅可比矩阵
J = geometricJacobian(robot, jointAngles, 'body3');
% 检测雅可比矩阵的秩
rankJ = rank(J);
% 输出雅可比矩阵的秩
disp('雅可比矩阵的秩:');
disp(rankJ);
% 如果秩小于自由度数,则处于奇异点
if rankJ < 6
disp('机器人处于奇异点。');
else
disp('机器人不在奇异点。');
end
1.3.2 多解性
逆运动学问题常常存在多解性,即同一个目标姿态可能对应多个不同的关节角度组合。在MATLAB Robotics System Toolbox中,可以通过设置初始猜测值或限制关节角度范围来选择合适的解。
1.3.2.1 处理多解性
% 创建一个逆运动学对象
ik = inverseKinematics('MaxIterations', 100, 'Solver', 'LevenbergMarquardt');
% 设置目标姿态
targetPose = trvec2tform([1, 2, 3]) * eul2tform([pi/4, -pi/4, 0], 'ZYX');
% 设置机器人模型
robot = rigidBodyTree;
body1 = rigidBody('body1');
body2 = rigidBody('body2');
body3 = rigidBody('body3');
% 设置连杆的变换关系
body1.Joint = rigidBodyJoint('revolute', 'xyz');
body2.Joint = rigidBodyJoint('revolute', 'xyz');
body3.Joint = rigidBodyJoint('revolute', 'xyz');
% 设置连杆的平移和旋转参数
body1.T = trvec2tform([0 0 1]);
body2.T = trvec2tform([1 0 0]);
body3.T = trvec2tform([0 1 0]);
% 将连杆添加到机器人模型中
addBody(robot, body1);
addBody(robot, body2, 'body1');
addBody(robot, body3, 'body2');
% 设置初始猜测值
initialGuess = [0, 0, 0];
% 求解逆运动学
jointAngles = ik(robot, targetPose, 'body3', initialGuess);
% 输出求解的关节角度
disp('求解的关节角度:');
disp(jointAngles);
% 验证解是否满足目标姿态
pose = fk(robot, jointAngles);
disp('计算的末端执行器姿态:');
disp(pose);
1.4 机器人运动学的应用实例
在实际应用中,机器人运动学可以用于路径规划、避障、抓取物体等任务。通过仿真软件,可以直观地观察和验证运动学计算的结果。
1.4.1 路径规划
路径规划是机器人运动学的一个重要应用。通过正运动学计算,可以生成机器人从起始位置到目标位置的路径。在MATLAB Robotics System Toolbox中,可以使用animate
函数来可视化路径规划的过程。
1.4.1.1 路径规划示例
% 创建一个机器人模型
robot = rigidBodyTree;
body1 = rigidBody('body1');
body2 = rigidBody('body2');
body3 = rigidBody('body3');
% 设置连杆的变换关系
body1.Joint = rigidBodyJoint('revolute', 'xyz');
body2.Joint = rigidBodyJoint('revolute', 'xyz');
body3.Joint = rigidBodyJoint('revolute', 'xyz');
% 设置连杆的平移和旋转参数
body1.T = trvec2tform([0 0 1]);
body2.T = trvec2tform([1 0 0]);
body3.T = trvec2tform([0 1 0]);
% 将连杆添加到机器人模型中
addBody(robot, body1);
addBody(robot, body2, 'body1');
addBody(robot, body3, 'body2');
% 设置路径上的目标姿态
targetPoses = [trvec2tform([1, 1, 1]) * eul2tform([0, 0, 0], 'ZYX');
trvec2tform([2, 2, 2]) * eul2tform([pi/4, 0, 0], 'ZYX');
trvec2tform([3, 3, 3]) * eul2tform([0, pi/4, 0], 'ZYX')];
% 创建逆运动学对象
ik = inverseKinematics;
% 计算路径上的关节角度
jointAngles = [];
for pose = targetPoses
angles = ik(robot, pose, 'body3');
jointAngles = [jointAngles; angles];
end
% 可视化路径规划
figure;
view(3);
animate(robot, jointAngles, 'FramesPerSecond', 10);
1.4.2 抓取物体
抓取物体是机器人运动学的另一个重要应用。通过逆运动学计算,可以使机器人的末端执行器达到指定物体的位置和姿态。在MATLAB Robotics System Toolbox中,可以使用ik
函数来实现这一过程。
1.4.2.1 抓取物体示例
% 创建一个机器人模型
robot = rigidBodyTree;
body1 = rigidBody('body1');
body2 = rigidBody('body2');
body3 = rigidBody('body3');
% 设置连杆的变换关系
body1.Joint = rigidBodyJoint('revolute', 'xyz');
body2.Joint = rigidBodyJoint('revolute', 'xyz');
body3.Joint = rigidBodyJoint('revolute', 'xyz');
% 设置连杆的平移和旋转参数
body1.T = trvec2tform([0 0 1]);
body2.T = trvec2tform([1 0 0]);
body3.T = trvec2tform([0 1 0]);
% 将连杆添加到机器人模型中
addBody(robot, body1);
addBody(robot, body2, 'body1');
addBody(robot, body3, 'body2');
% 设置目标物体的位置和姿态
objectPose = trvec2tform([2, 2, 2]) * eul2tform([pi/4, 0, 0], 'ZYX');
% 创建逆运动学对象
ik = inverseKinematics;
% 求解逆运动学
jointAngles = ik(robot, objectPose, 'body3');
% 可视化机器人抓取物体
figure;
view(3);
show(robot, jointAngles);
hold on;
plot3(objectPose(1,4), objectPose(2,4), objectPose(3,4), 'ro', 'MarkerSize', 10);
hold off;
1.5 机器人运动学的高级技巧
在实际应用中,机器人运动学的计算可能会遇到一些复杂的情况,如关节角度限制、外部约束等。这些情况下,需要使用一些高级技巧来确保计算的准确性和有效性。
1.5.1 关节角度限制
对于某些机器人,关节的角度范围是有限制的。在求解逆运动学时,需要考虑这些限制,以避免机器人执行超出范围的动作。在MATLAB Robotics System Toolbox中,可以通过设置关节的限位来实现这一目标。
1.5.1.1 设置关节限位
% 创建一个机器人模型
robot = rigidBodyTree;
body1 = rigidBody('body1');
body2 = rigidBody('body2');
body3 = rigidBody('body3');
% 设置连杆的变换关系
body1.Joint = rigidBodyJoint('revolute', 'xyz');
body2.Joint = rigidBodyJoint('revolute', 'xyz');
body3.Joint = rigidBodyJoint('revolute', 'xyz');
% 设置连杆的平移和旋转参数
body1.T = trvec2tform([0 0 1]);
body2.T = trvec2tform([1 0 0]);
body3.T = trvec2tform([0 1 0]);
% 将连杆添加到机器人模型中
addBody(robot, body1);
addBody(robot, body2, 'body1');
addBody(robot, body3, 'body2');
% 设置关节的限位
setJointLimits(robot, 'body1', [-pi/2, pi/2]);
setJointLimits(robot, 'body2', [-pi/2, pi/2]);
setJointLimits(robot, 'body3', [-pi/2, pi/2]);
% 设置目标姿态
targetPose = trvec2tform([1, 2, 3]) * eul2tform([pi/4, -pi/4, 0], 'ZYX');
% 创建逆运动学对象
ik = inverseKinematics;
% 求解逆运动学
jointAngles = ik(robot, targetPose, 'body3');
% 输出求解的关节角度
disp('求解的关节角度:');
disp(jointAngles);
% 验证关节角度是否在限位范围内
isWithinLimits = all(jointAngles >= -pi/2) && all(jointAngles <= pi/2);
disp('关节角度是否在限位范围内:');
disp(isWithinLimits);
1.5.2 外部约束
在某些情况下,机器人的运动可能会受到外部约束的影响,如避障、路径跟踪等。这些约束条件可以显著影响逆运动学的求解过程,确保机器人在运动过程中不会发生碰撞或偏离预定路径。在MATLAB Robotics System Toolbox中,可以通过添加约束条件来解决这些问题。
1.5.2.1 避障示例
假设我们有一个串联机器人,需要在运动过程中避免与特定的障碍物发生碰撞。我们可以使用MATLAB Robotics System Toolbox中的约束函数来实现这一目标。
% 创建一个机器人模型
robot = rigidBodyTree;
body1 = rigidBody('body1');
body2 = rigidBody('body2');
body3 = rigidBody('body3');
% 设置连杆的变换关系
body1.Joint = rigidBodyJoint('revolute', 'xyz');
body2.Joint = rigidBodyJoint('revolute', 'xyz');
body3.Joint = rigidBodyJoint('revolute', 'xyz');
% 设置连杆的平移和旋转参数
body1.T = trvec2tform([0 0 1]);
body2.T = trvec2tform([1 0 0]);
body3.T = trvec2tform([0 1 0]);
% 将连杆添加到机器人模型中
addBody(robot, body1);
addBody(robot, body2, 'body1');
addBody(robot, body3, 'body2');
% 设置关节的限位
setJointLimits(robot, 'body1', [-pi/2, pi/2]);
setJointLimits(robot, 'body2', [-pi/2, pi/2]);
setJointLimits(robot, 'body3', [-pi/2, pi/2]);
% 设置目标姿态
targetPose = trvec2tform([1, 2, 3]) * eul2tform([pi/4, -pi/4, 0], 'ZYX');
% 创建逆运动学对象
ik = inverseKinematics;
% 添加避障约束
% 假设障碍物是一个球体,中心在 [2, 1, 1],半径为 1
obstacleCenter = [2, 1, 1];
obstacleRadius = 1;
% 定义避障约束函数
constraintFcn = @(q) norm(getTransform(robot, q, 'body3', 'base') * [0; 0; 0; 1] - [obstacleCenter; 1]) - obstacleRadius;
% 设置约束条件
ik.Constraint = constraintFcn;
% 求解逆运动学
jointAngles = ik(robot, targetPose, 'body3');
% 输出求解的关节角度
disp('求解的关节角度:');
disp(jointAngles);
% 验证避障约束是否满足
isConstraintSatisfied = constraintFcn(jointAngles) > 0;
disp('避障约束是否满足:');
disp(isConstraintSatisfied);
% 可视化机器人避障
figure;
view(3);
show(robot, jointAngles);
hold on;
sphere = surf(sphere(20) * obstacleRadius + obstacleCenter(1), sphere(20) * obstacleRadius + obstacleCenter(2), sphere(20) * obstacleRadius + obstacleCenter(3));
set(sphere, 'FaceColor', 'r', 'EdgeColor', 'none');
hold off;
1.5.2.2 路径跟踪示例
路径跟踪是另一个常见的外部约束问题,要求机器人在运动过程中沿着预定的路径移动。这可以通过在逆运动学求解过程中添加路径跟踪约束来实现。
% 创建一个机器人模型
robot = rigidBodyTree;
body1 = rigidBody('body1');
body2 = rigidBody('body2');
body3 = rigidBody('body3');
% 设置连杆的变换关系
body1.Joint = rigidBodyJoint('revolute', 'xyz');
body2.Joint = rigidBodyJoint('revolute', 'xyz');
body3.Joint = rigidBodyJoint('revolute', 'xyz');
% 设置连杆的平移和旋转参数
body1.T = trvec2tform([0 0 1]);
body2.T = trvec2tform([1 0 0]);
body3.T = trvec2tform([0 1 0]);
% 将连杆添加到机器人模型中
addBody(robot, body1);
addBody(robot, body2, 'body1');
addBody(robot, body3, 'body2');
% 设置关节的限位
setJointLimits(robot, 'body1', [-pi/2, pi/2]);
setJointLimits(robot, 'body2', [-pi/2, pi/2]);
setJointLimits(robot, 'body3', [-pi/2, pi/2]);
% 预定路径
path = [trvec2tform([1, 1, 1]) * eul2tform([0, 0, 0], 'ZYX');
trvec2tform([2, 2, 2]) * eul2tform([pi/4, 0, 0], 'ZYX');
trvec2tform([3, 3, 3]) * eul2tform([0, pi/4, 0], 'ZYX')];
% 创建逆运动学对象
ik = inverseKinematics;
% 求解路径上的关节角度
jointAngles = [];
for pose = path
% 求解逆运动学
angles = ik(robot, pose, 'body3');
jointAngles = [jointAngles; angles];
end
% 可视化路径跟踪
figure;
view(3);
animate(robot, jointAngles, 'FramesPerSecond', 10);
hold on;
plot3(path(:,1,4), path(:,2,4), path(:,3,4), 'b-', 'LineWidth', 2);
hold off;
1.6 机器人运动学的优化方法
在某些复杂的机器人运动学问题中,简单的解析或数值方法可能无法提供满意的解决方案。此时,可以使用优化方法来求解逆运动学问题。优化方法通过最小化一个目标函数(如关节角度的误差)来找到最佳的关节角度组合。
1.6.1 使用优化方法求解逆运动学
在MATLAB中,可以使用fmincon
等优化函数来求解逆运动学问题。以下是一个简单的示例,展示如何使用优化方法来求解机器人末端执行器的逆运动学。
1.6.1.1 优化逆运动学示例
% 创建一个机器人模型
robot = rigidBodyTree;
body1 = rigidBody('body1');
body2 = rigidBody('body2');
body3 = rigidBody('body3');
% 设置连杆的变换关系
body1.Joint = rigidBodyJoint('revolute', 'xyz');
body2.Joint = rigidBodyJoint('revolute', 'xyz');
body3.Joint = rigidBodyJoint('revolute', 'xyz');
% 设置连杆的平移和旋转参数
body1.T = trvec2tform([0 0 1]);
body2.T = trvec2tform([1 0 0]);
body3.T = trvec2tform([0 1 0]);
% 将连杆添加到机器人模型中
addBody(robot, body1);
addBody(robot, body2, 'body1');
addBody(robot, body3, 'body2');
% 设置关节的限位
setJointLimits(robot, 'body1', [-pi/2, pi/2]);
setJointLimits(robot, 'body2', [-pi/2, pi/2]);
setJointLimits(robot, 'body3', [-pi/2, pi/2]);
% 设置目标姿态
targetPose = trvec2tform([1, 2, 3]) * eul2tform([pi/4, -pi/4, 0], 'ZYX');
% 定义目标函数
objectiveFcn = @(q) norm(poseError(robot, q, targetPose, 'body3'));
% 定义关节角度的限位
lb = [-pi/2, -pi/2, -pi/2];
ub = [pi/2, pi/2, pi/2];
% 初始猜测值
initialGuess = [0, 0, 0];
% 使用优化函数求解逆运动学
options = optimoptions('fmincon', 'Display', 'iter', 'Algorithm', 'interior-point');
jointAngles = fmincon(objectiveFcn, initialGuess, [], [], [], [], lb, ub, [], options);
% 输出求解的关节角度
disp('求解的关节角度:');
disp(jointAngles);
% 验证解是否满足目标姿态
pose = fk(robot, jointAngles);
disp('计算的末端执行器姿态:');
disp(pose);
% 定义姿态误差函数
function error = poseError(robot, q, targetPose, bodyName)
% 计算当前姿态
currentPose = fk(robot, q, bodyName);
% 计算姿态误差
error = norm(currentPose - targetPose);
end
1.7 总结
机器人运动学是机器人技术中的一个基础而重要的领域,它研究机器人关节运动与其末端执行器位置和姿态之间的关系。通过正运动学和逆运动学的计算,可以实现机器人的路径规划、运动控制和任务执行。在实际应用中,需要注意奇异点、多解性等问题,并使用适当的算法和技巧来解决这些问题。此外,优化方法可以用于复杂情况下的逆运动学求解,确保机器人在运动过程中能够高效、准确地完成任务。