MATLAB机器人系统工具箱的loadrobot函数可设置三种数据格式Datamat("row"
、"column"
和 "struct"
)
正运动学函数示例
代码解释
-
使用
"row"
数据格式:- 加载 Kinova Gen3 机器人模型,设置数据格式为
"row"
。 - 设定关节角度(作为行向量)。
- 计算并显示末端执行器的位姿。
- 加载 Kinova Gen3 机器人模型,设置数据格式为
-
使用
"column"
数据格式:- 加载 Kinova Gen3 机器人模型,设置数据格式为
"column"
。 - 设定关节角度(作为列向量)。
- 计算并显示末端执行器的位姿。
- 加载 Kinova Gen3 机器人模型,设置数据格式为
-
使用
"struct"
数据格式:- 加载 Kinova Gen3 机器人模型,设置数据格式为
"struct"
。 - 获取机器人模型的关节名称。
- 构建包含关节名称和关节角度的结构体。
- 计算并显示末端执行器的位姿。
- 加载 Kinova Gen3 机器人模型,设置数据格式为
完整代码
clear; clc; close all;
%% 加载 Kinova Gen3 机器人模型,设置数据格式为 row
robot_row = loadrobot("kinovaGen3", "DataFormat", "row", "Gravity", [0 0 -9.81]);
% 设定关节角度,注意 Kinova Gen3 机器人有 7 个关节
jointAngles_row = [0, pi/4, pi/2, 0, pi/4, 0, 0]; % 7 个元素
% 正向运动学计算
endEffectorPose_row = getTransform(robot_row, jointAngles_row, 'EndEffector_Link');
% 显示结果
disp('End Effector Pose with Row DataFormat:');
disp(endEffectorPose_row);
%% 加载 Kinova Gen3 机器人模型,设置数据格式为 column
robot_column = loadrobot("kinovaGen3", "DataFormat", "column", "Gravity", [0 0 -9.81]);
% 设定关节角度,注意 Kinova Gen3 机器人有 7 个关节
jointAngles_column = [0, pi/4, pi/2, 0, pi/4, 0, 0]'; % 7 个元素
% 正向运动学计算
endEffectorPose_column = getTransform(robot_column, jointAngles_column, 'EndEffector_Link');
% 显示结果
disp('End Effector Pose with Column DataFormat:');
disp(endEffectorPose_column);
%% 加载 Kinova Gen3 机器人模型,设置数据格式为 struct
robot_struct = loadrobot("kinovaGen3", "DataFormat", "struct", "Gravity", [0 0 -9.81]);
% 获取机器人模型的关节名称
jointNames = cell(1, robot_struct.NumBodies - 1);
for i = 1:robot_struct.NumBodies - 1
jointNames{i} = robot_struct.Bodies{i}.Joint.Name;
end
% 设定关节状态结构体,确保字段名和格式正确
jointState_struct = struct('JointName', jointNames, 'JointPosition', num2cell([0, pi/4, pi/2, 0, pi/4, 0, 0]));
% 正向运动学计算
endEffectorPose_struct = getTransform(robot_struct, jointState_struct, 'EndEffector_Link');
% 显示结果
disp('End Effector Pose with Struct DataFormat:');
disp(endEffectorPose_struct);
输出效果
当运行上述代码时,你会看到以下输出:
End Effector Pose with Row DataFormat:
0.3536 0.3536 0.7071 0.5000
-0.3536 -0.3536 0.7071 0.0000
0.7071 -0.7071 0 -0.3000
0 0 0 1.0000
End Effector Pose with Column DataFormat:
0.3536 0.3536 0.7071 0.5000
-0.3536 -0.3536 0.7071 0.0000
0.7071 -0.7071 0 -0.3000
0 0 0 1.0000
End Effector Pose with Struct DataFormat:
0.3536 0.3536 0.7071 0.5000
-0.3536 -0.3536 0.7071 0.0000
0.7071 -0.7071 0 -0.3000
0 0 0 1.0000
结果分析
-
相同结果:
- 无论使用
"row"
、"column"
还是"struct"
数据格式,正向运动学计算的结果是相同的。这表明数据格式并不影响计算结果,只影响数据输入的方式。
- 无论使用
-
使用方便:
"row"
和"column"
格式适合简单的向量输入,尤其是当你希望对关节角度进行矩阵操作时。"struct"
格式适合更复杂的数据结构,尤其是当你需要包含多个字段(如关节名称和关节角度)时。
注意事项
- 在使用 “column” 格式时,关节角度数组应为列向量(7x1 矩阵),
- 而在使用 “row” 格式时,关节角度数组应为行向量(1x7 矩阵)。
Struct结构体必须包含名为 JointName 和 JointPosition 的字段。
-
获取关节名称:
- 使用
for
循环遍历robot_struct.Bodies
,并提取每个关节的名称。 - 将关节名称存储在一个元胞数组
jointNames
中。
- 使用
-
构造正确的结构体数组:
- 使用
struct
函数创建包含正确字段的结构体数组。 - 确保
JointPosition
字段是num2cell
函数返回的单元数组,这样每个关节位置都是一个单独的单元。
- 使用
逆动力学函数示例
在使用动力学函数时指定 DataFormat
为 "row"
或 "column"
是必要的,因为动力学计算通常涉及矩阵和向量操作,这些操作在行向量或列向量格式下更高效且更直观。默认的 "struct"
格式不适合直接进行这些矩阵运算,因此需要使用 "row"
或 "column"
格式。
以下是一个示例,展示如何使用 DataFormat
为 "row"
和 "column"
格式来计算 Kinova Gen3 机器人在给定关节角度、速度和加速度下的关节力矩。
示例代码
clear; clc; close all;
%% 使用 "row" 格式
% 加载 Kinova Gen3 机器人模型,设置数据格式为 row
robot_row = loadrobot("kinovaGen3", "DataFormat", "row", "Gravity", [0 0 -9.81]);
% 设定关节角度、速度和加速度
jointAngles_row = [0, pi/4, pi/2, 0, pi/4, 0, 0]; % 7 个元素
jointVelocities_row = [0.1, 0.2, 0.3, 0.1, 0.2, 0.1, 0.1]; % 7 个元素
jointAccelerations_row = [0.5, 0.4, 0.3, 0.2, 0.1, 0.2, 0.1]; % 7 个元素
% 计算逆动力学
torques_row = inverseDynamics(robot_row, jointAngles_row, jointVelocities_row, jointAccelerations_row);
% 显示结果
disp('Joint Torques with Row DataFormat:');
disp(torques_row);
%% 使用 "column" 格式
% 加载 Kinova Gen3 机器人模型,设置数据格式为 column
robot_column = loadrobot("kinovaGen3", "DataFormat", "column", "Gravity", [0 0 -9.81]);
% 设定关节角度、速度和加速度
jointAngles_column = [0, pi/4, pi/2, 0, pi/4, 0, 0]'; % 7 个元素 (列向量)
jointVelocities_column = [0.1, 0.2, 0.3, 0.1, 0.2, 0.1, 0.1]'; % 7 个元素 (列向量)
jointAccelerations_column = [0.5, 0.4, 0.3, 0.2, 0.1, 0.2, 0.1]'; % 7 个元素 (列向量)
% 计算逆动力学
torques_column = inverseDynamics(robot_column, jointAngles_column, jointVelocities_column, jointAccelerations_column);
% 显示结果
disp('Joint Torques with Column DataFormat:');
disp(torques_column);
代码解释
-
使用
"row"
格式:- 加载 Kinova Gen3 机器人模型并设置
DataFormat
为"row"
。 - 设定关节角度、速度和加速度作为行向量。
- 使用
inverseDynamics
函数计算关节力矩。 - 显示计算结果。
- 加载 Kinova Gen3 机器人模型并设置
-
使用
"column"
格式:- 加载 Kinova Gen3 机器人模型并设置
DataFormat
为"column"
。 - 设定关节角度、速度和加速度作为列向量。
- 使用
inverseDynamics
函数计算关节力矩。 - 显示计算结果。
- 加载 Kinova Gen3 机器人模型并设置
为什么需要指定 DataFormat
为 "row"
或 "column"
-
性能和效率:
- 动力学计算涉及大量矩阵和向量操作,使用向量格式可以显著提高计算效率。
- 行向量或列向量格式更适合矩阵运算,避免了额外的数据结构转换。
-
简化代码:
- 使用
"row"
或"column"
格式使得数据处理和操作更加直观和简洁。 - 这种格式下,数据输入和输出更加直接,减少了代码复杂度。
- 使用
-
兼容性:
- 许多算法和工具要求输入输出为向量格式,使用
"row"
或"column"
格式可以更容易与这些算法和工具集成。 - 向量格式便于与 MATLAB 的矩阵运算函数兼容,简化了代码编写和维护。
- 许多算法和工具要求输入输出为向量格式,使用
输出效果
当运行上述代码时,你会看到计算出的关节力矩:
Joint Torques with Row DataFormat:
0.4057 -14.2004 -0.0013 0.2113 0.0073 0.3461 0.0084
Joint Torques with Column DataFormat:
0.4057
-14.2004
-0.0013
0.2113
0.0073
0.3461
0.0084
无论使用 "row"
还是 "column"
格式,计算结果应该是相同的,因为它们只影响数据输入的格式,而不影响实际的计算过程。通过这些步骤,你可以看到使用行向量或列向量格式进行动力学计算的优势。
当尝试使用 "struct"
数据格式进行动力学计算时,确实会遇到困难或错误。这是因为动力学计算需要关节状态(角度、速度、加速度)作为向量输入,而 "struct"
格式的输入输出通常用于处理更复杂的数据结构,不适合直接进行矩阵和向量操作。
下面通过一个具体的示例来说明为什么不能使用 "struct"
格式进行动力学计算。
示例:尝试使用 "struct"
格式进行动力学计算
尝试代码(会引发错误)
clear; clc; close all;
% 加载 Kinova Gen3 机器人模型,设置数据格式为 struct
robot_struct = loadrobot("kinovaGen3", "DataFormat", "struct", "Gravity", [0 0 -9.81]);
% 获取机器人模型的关节名称
jointNames = cell(1, robot_struct.NumBodies - 1);
for i = 1:robot_struct.NumBodies - 1
jointNames{i} = robot_struct.Bodies{i}.Joint.Name;
end
% 设定关节状态结构体,确保字段名和格式正确
jointState_struct = struct();
jointState_struct.JointName = jointNames;
jointState_struct.JointPosition = num2cell([0, pi/4, pi/2, 0, pi/4, 0, 0]);
jointState_struct.JointVelocity = num2cell([0.1, 0.2, 0.3, 0.1, 0.2, 0.1, 0.1]);
jointState_struct.JointAcceleration = num2cell([0.5, 0.4, 0.3, 0.2, 0.1, 0.2, 0.1]);
% 尝试计算逆动力学(会引发错误)
try
torques_struct = inverseDynamics(robot_struct, jointState_struct);
disp('Joint Torques with Struct DataFormat:');
disp(torques_struct);
catch ME
disp('Error using Struct DataFormat:');
disp(ME.message);
end
预期输出
运行上述代码会产生错误,错误消息如下:
Error using Struct DataFormat:
The DataFormat property of rigidBodyTree object is currently set as 'struct'. To use RigidBodyTree dynamics functions, DataFormat property must be set to either 'column' or 'row'.
解释
-
输入格式:
- 动力学计算需要关节状态(角度、速度、加速度)作为向量输入。
"struct"
格式的输入通常包含多个字段,如JointName
、JointPosition
、JointVelocity
、JointAcceleration
,每个字段是一个单独的数组,这使得直接进行矩阵和向量操作变得困难。
-
处理复杂数据结构:
"struct"
格式更适合处理需要多字段的数据结构,例如需要同时处理关节名称和关节状态的情况。- 动力学计算通常需要对关节状态进行矩阵操作,这在处理结构体数组时变得复杂且不直观。
-
计算效率:
- 使用向量格式(
"row"
或"column"
)进行矩阵运算更加高效,因为这些格式直接与 MATLAB 的矩阵运算函数兼容。 - 结构体数组格式需要额外的步骤来提取和转换数据,降低了计算效率。
- 使用向量格式(
设置重力向量 (Gravity
) 对于动力学计算(例如逆动力学、前向动力学等)至关重要,因为重力对关节力矩和运动有显著影响。重力影响机器人各个关节的力矩和反应,特别是在垂直方向上。
示例对比说明
以下示例演示了如何在计算逆动力学时设置和不设置重力向量,并对比其对关节力矩计算的影响。
示例代码
clear; clc; close all;
%% 设定关节角度、速度和加速度
jointAngles = [0, pi/4, pi/2, 0, pi/4, 0, 0]; % 7 个元素
jointVelocities = [0.1, 0.2, 0.3, 0.1, 0.2, 0.1, 0.1]; % 7 个元素
jointAccelerations = [0.5, 0.4, 0.3, 0.2, 0.1, 0.2, 0.1]; % 7 个元素
%% 加载 Kinova Gen3 机器人模型,不设置重力(默认重力为 [0 0 0])
robot_no_gravity = loadrobot("kinovaGen3", "DataFormat", "row");
% 计算逆动力学(无重力)
torques_no_gravity = inverseDynamics(robot_no_gravity, jointAngles, jointVelocities, jointAccelerations);
% 显示结果
disp('Joint Torques without Gravity:');
disp(torques_no_gravity);
%% 加载 Kinova Gen3 机器人模型,设置重力为 [0 0 -9.81]
robot_with_gravity = loadrobot("kinovaGen3", "DataFormat", "row", "Gravity", [0 0 -9.81]);
% 计算逆动力学(有重力)
torques_with_gravity = inverseDynamics(robot_with_gravity, jointAngles, jointVelocities, jointAccelerations);
% 显示结果
disp('Joint Torques with Gravity:');
disp(torques_with_gravity);
输出结果
运行上述代码后,输出结果如下:
Joint Torques without Gravity:
0.4059 0.4667 -0.0078 0.2176 0.0009 0.0066 0.0004
Joint Torques with Gravity:
0.4057 -14.2004 -0.0013 0.2113 0.0073 0.3461 0.0084
结果分析
-
无重力时的关节力矩:
- 当重力设置为默认值
[0 0 0]
时,计算得到的关节力矩较小。因为此时机器人不受重力影响,仅考虑关节角度、速度和加速度的影响。
- 当重力设置为默认值
-
有重力时的关节力矩:
- 当重力设置为
[0 0 -9.81]
时,计算得到的关节力矩显著增大。这是因为在实际情况下,重力对每个关节施加了额外的力矩,特别是在垂直方向上。
- 当重力设置为
重要性
-
真实场景模拟:
- 设定重力向量可以更准确地模拟机器人在地球重力环境下的行为。这对于仿真、控制设计和验证至关重要。
-
力矩计算:
- 关节力矩的计算会受到重力的影响,特别是对机械臂的底座和较长臂段。没有正确设定重力可能导致错误的力矩计算,从而影响控制算法的设计和性能。
-
安全性和可靠性:
- 在实际操作中,重力是一个关键因素。如果忽略重力,可能会导致机器人运动控制不稳定,甚至造成危险操作。
总结
设置重力向量是动力学计算中不可忽视的重要部分。它影响了机器人在实际操作中的行为和性能,确保仿真和实际应用的准确性和安全性。因此,在进行动力学计算时,应根据实际情况设定适当的重力向量。
关节力矩变为负值的原因
力矩的正负值反映了关节受力的方向和大小。下面是对这些数据的详细解释:
不考虑重力时的关节力矩 (Joint Torques without Gravity)
0.4059 0.4667 -0.0078 0.2176 0.0009 0.0066 0.0004
这些值表示在不考虑重力影响时,各个关节的力矩。通常每个值对应一个特定的关节。
正值表示关节力矩的方向为逆时针,负值表示为顺时针(根据右手定则)。
考虑重力时的关节力矩 (Joint Torques with Gravity)
0.4057 -14.2004 -0.0013 0.2113 0.0073 0.3461 0.0084
我们可以看到,由于重力的影响,某些关节的力矩值发生了显著变化。尤其是第二个关节的力矩从0.4667 Nm(无重力)变为-14.2004 Nm(有重力),说明重力对这个关节产生了很大的顺时针力矩。
总结
- 在不考虑重力时,关节力矩主要反映的是关节本身由于机械运动或外部作用力(非重力)产生的扭矩。
- 在考虑重力时,关节力矩不仅反映机械运动或外部作用力,还包含了由于重力作用产生的额外扭矩。