- 积分
 - 9841
 
- 回帖
 - 0
 
- 西莫币
 -  
 
- 贡献
 -  
 
- 威望
 -  
 
- 存款
 -  
 
- 阅读权限
 - 120
 
- 最后登录
 - 1970-1-1
 
 
 
 
 
该用户从未签到  
 | 
 
 楼主 |
发表于 2020-8-2 17:48
|
显示全部楼层
来自: 中国山东济南  
 
 
第三步:看!它左手右手一个慢动作! 
 
我们已经知道如何用 MATLAB 搭建一个简单的机器人了。然而这样搭建的机器人,和小朋友用积木搭建的玩具并无二致 —— 既然是用软件做成的机器人,我们自然希望它能动起来。我们以加拿大机器人公司 Kinova 的第三代机械臂为例,来看看 MATLAB 如何让这支麒麟臂动起来。 
 
  
 
在 MATLAB 界面中输入 
>> robot = loadrobot("kinovaGen3"); 
>> showdetails(robot) 
 
我们可以看到输出如下  
 
 
 
 
不难看出,第三代 Kinova 是由 8 根连杆和 8 个关节拼接而成。如果我们要想知道某个具体连杆的信息,例如名叫 “Shoulder_Link” 的连杆, 依次输入 
 
>> robot.getBody( Shoulder_Link ).Joint 
>> robot.getBody( Shoulder_Link ).Joint.JointToParentTransform 
>> robot.getBody( Shoulder_Link ).Joint.ChildToJointTransform 
 
即可分别查询属于该连杆的关节,以及关节到母连杆和子连杆的转移矩阵。如此一来,我们就可以从这种方法重建出第三代 Kinova 机械臂了! 
 
现在我们有两种方法可以让让机械臂动起来。第一种方法是通过变换关节旋转角度的方式,这种方法叫正运动学(Forward kinematics);第二种方法是通过给定每个连杆末端位置,这种方法叫逆运动学(Inverse kinematics)。正运动学可以很方便地对机械臂进行直接操控,而逆运动学则更有利于直接指定机械臂完成任务,例如抓取处于某位置的快递等等。这两种方法各有千秋。 
 
有几何背景的读者知道,n 维欧式空间中的刚体形变可分为平移(Translation)、旋转(Rotation)和镜像(Reflection)三种,这三种变化可以用群作用,或者矩阵来表示。由这三种作用组成的群叫做欧几里得群(Euclidean Group)记作 E(n),因为 E(n) 中的元素都可以用矩阵表示,所以 E(n) n+1 阶矩阵群的子群(具体解释见下图)。群 E(n) 中只由平移和旋转(不含镜像)构成的子群叫做特殊欧几里得群,记作 SE(n)。 
 
 
 
 
下面我们 MATLAB 中的逆运动学函数 inverseKinematics 来让机械臂动起来。我们只需要定义出机械臂所要经过的几个路径点的位置、速度以及加速度,MATLAB 即可通过对特殊欧几里得群求逆来计算出整个机械臂所经过的路径,以及每个时刻的速度以及加速度等信息。 
 
 
% 关节起始旋转角及初始位置 
positions = [2*pi, 0.2619, pi, 4.0142, 2*pi, 0.9598, pi/2]; 
config = homeConfiguration(robot); 
for k = 1:length(positions) 
  config(k).JointPosition = positions(k); 
end 
 
% 定义机械臂需要通过的路径点以及对应速度、加速度信息 
waypoints = [0.5639 0.0013 0.4336]  + [-0.1 0.2 0.4 ; -0.2 0 0.1 ; -0.1 -0.2 0.4 ;] ; 
waypointTimes = 0:4:8; 
ts = 0.2; 
trajTimes = 0:ts:waypointTimes(end); 
waypointVels = 0.1 *[ 0  1  0; -1  0  0; 0 -1  0;] ; 
waypointAccels = zeros(size(waypointVels)); 
waypointAccelTimes = diff(waypointTimes)/4; 
[q,qd,qdd] = trapveltraj(waypoints,numel(trajTimes), ... 
             AccelTime ,repmat(waypointAccelTimes,[3 1]), ...  
             EndTime ,repmat(diff(waypointTimes),[3 1])); 
 
% 画出初始状态 
%% 画图--机械臂 
show(gen3,config, Frames , off , PreservePlot ,false); 
hold on 
%% 画图--路径初始化 
hTraj = plot3(waypoints(1,1),waypoints(2,1),waypoints(3,1), b.- ); 
set(hTraj,  xdata , q(1,:),  ydata , q(2,:),  zdata , q(3,:)); 
%% 画图--路径点 
plot3(waypoints(1,:),waypoints(2,:),waypoints(3,:), ro , LineWidth ,2); 
set(gca,  Position , [-.2, -.2, 1.5, 1.5]); 
xlim([-1 1]), ylim([-1 1]), zlim([0 1.2]); 
 
 
 
 
% 初始化机械臂的逆运动学方程 
ik = inverseKinematics( RigidBodyTree ,robot); 
ikWeights = [1 1 1 1 1 1]; 
ikInitGuess = robot.homeConfiguration; % 随机设置一个初始状态 
 
% 让机器人动起来! 
for idx = 1:numel(trajTimes)  
    % 解逆运动学方程 
    tgtPose = trvec2tform(q(:,idx) ); 
    [config,info] = ik( EndEffector_Link , tgtPose,ikWeights,ikInitGuess); 
    ikInitGuess = config; % 以上一时刻的状态作为下一时刻的初始值 
 
    % 画出机器人的动态 
    show(robot,config,  Frames , off , PreservePlot ,false); 
    title([  Trajectory at t =   num2str(trajTimes(idx))]) 
    drawnow     
end 
 
 
最后得到的轨迹图如下: 
 
 
 
 
有兴趣的读者可以修改上面代码中的参数(例如路径点的位置、机械臂的速度加速度等),来看看结果会出现怎样的变化。 
 
 
 |   
 
 
 
 |