MATLAB机器人系统工具箱的loadrobot函数使用三种不同的数据格式Datamat(`“row“`、`“column“` 和 `“struct“`)的对比和有无重力的逆动力学的力矩对比

MATLAB机器人系统工具箱的loadrobot函数可设置三种数据格式Datamat("row""column""struct"

在这里插入图片描述

正运动学函数示例

代码解释

  1. 使用 "row" 数据格式

    • 加载 Kinova Gen3 机器人模型,设置数据格式为 "row"
    • 设定关节角度(作为行向量)。
    • 计算并显示末端执行器的位姿。
  2. 使用 "column" 数据格式

    • 加载 Kinova Gen3 机器人模型,设置数据格式为 "column"
    • 设定关节角度(作为列向量)。
    • 计算并显示末端执行器的位姿。
  3. 使用 "struct" 数据格式

    • 加载 Kinova Gen3 机器人模型,设置数据格式为 "struct"
    • 获取机器人模型的关节名称。
    • 构建包含关节名称和关节角度的结构体。
    • 计算并显示末端执行器的位姿。

完整代码

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

结果分析

  1. 相同结果

    • 无论使用 "row""column" 还是 "struct" 数据格式,正向运动学计算的结果是相同的。这表明数据格式并不影响计算结果,只影响数据输入的方式。
  2. 使用方便

    • "row""column" 格式适合简单的向量输入,尤其是当你希望对关节角度进行矩阵操作时。
    • "struct" 格式适合更复杂的数据结构,尤其是当你需要包含多个字段(如关节名称和关节角度)时。

注意事项

  • 在使用 “column” 格式时,关节角度数组应为列向量(7x1 矩阵),
  • 而在使用 “row” 格式时,关节角度数组应为行向量(1x7 矩阵)。

Struct结构体必须包含名为 JointName 和 JointPosition 的字段。

  1. 获取关节名称

    • 使用 for 循环遍历 robot_struct.Bodies,并提取每个关节的名称。
    • 将关节名称存储在一个元胞数组 jointNames 中。
  2. 构造正确的结构体数组

    • 使用 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);

代码解释

  1. 使用 "row" 格式

    • 加载 Kinova Gen3 机器人模型并设置 DataFormat"row"
    • 设定关节角度、速度和加速度作为行向量。
    • 使用 inverseDynamics 函数计算关节力矩。
    • 显示计算结果。
  2. 使用 "column" 格式

    • 加载 Kinova Gen3 机器人模型并设置 DataFormat"column"
    • 设定关节角度、速度和加速度作为列向量。
    • 使用 inverseDynamics 函数计算关节力矩。
    • 显示计算结果。

为什么需要指定 DataFormat"row""column"

  1. 性能和效率

    • 动力学计算涉及大量矩阵和向量操作,使用向量格式可以显著提高计算效率。
    • 行向量或列向量格式更适合矩阵运算,避免了额外的数据结构转换。
  2. 简化代码

    • 使用 "row""column" 格式使得数据处理和操作更加直观和简洁。
    • 这种格式下,数据输入和输出更加直接,减少了代码复杂度。
  3. 兼容性

    • 许多算法和工具要求输入输出为向量格式,使用 "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'.

解释

  1. 输入格式

    • 动力学计算需要关节状态(角度、速度、加速度)作为向量输入。
    • "struct" 格式的输入通常包含多个字段,如 JointNameJointPositionJointVelocityJointAcceleration,每个字段是一个单独的数组,这使得直接进行矩阵和向量操作变得困难。
  2. 处理复杂数据结构

    • "struct" 格式更适合处理需要多字段的数据结构,例如需要同时处理关节名称和关节状态的情况。
    • 动力学计算通常需要对关节状态进行矩阵操作,这在处理结构体数组时变得复杂且不直观。
  3. 计算效率

    • 使用向量格式("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

结果分析

  1. 无重力时的关节力矩

    • 当重力设置为默认值 [0 0 0] 时,计算得到的关节力矩较小。因为此时机器人不受重力影响,仅考虑关节角度、速度和加速度的影响。
  2. 有重力时的关节力矩

    • 当重力设置为 [0 0 -9.81] 时,计算得到的关节力矩显著增大。这是因为在实际情况下,重力对每个关节施加了额外的力矩,特别是在垂直方向上。

重要性

  1. 真实场景模拟

    • 设定重力向量可以更准确地模拟机器人在地球重力环境下的行为。这对于仿真、控制设计和验证至关重要。
  2. 力矩计算

    • 关节力矩的计算会受到重力的影响,特别是对机械臂的底座和较长臂段。没有正确设定重力可能导致错误的力矩计算,从而影响控制算法的设计和性能。
  3. 安全性和可靠性

    • 在实际操作中,重力是一个关键因素。如果忽略重力,可能会导致机器人运动控制不稳定,甚至造成危险操作。

总结

设置重力向量是动力学计算中不可忽视的重要部分。它影响了机器人在实际操作中的行为和性能,确保仿真和实际应用的准确性和安全性。因此,在进行动力学计算时,应根据实际情况设定适当的重力向量。

关节力矩变为负值的原因

力矩的正负值反映了关节受力的方向和大小。下面是对这些数据的详细解释:

不考虑重力时的关节力矩 (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(有重力),说明重力对这个关节产生了很大的顺时针力矩。

总结

  • 在不考虑重力时,关节力矩主要反映的是关节本身由于机械运动或外部作用力(非重力)产生的扭矩。
  • 在考虑重力时,关节力矩不仅反映机械运动或外部作用力,还包含了由于重力作用产生的额外扭矩。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值