全世界只有3.14 % 的人关注了
如果说机器人是一粒种子,那么《机器人大擂台》这档节目就是那个播种人。节目中,不同选手操纵着机器人,在擂台上各显神威 —— 冲撞、翻滚、撬杠、喷火等各种技能,总能令人眼花缭乱,同时点燃心中关于机器人的各种幻想。
图片来自 https://giphy.com/gifs/
如今的机器人应用广泛,机器人技术也开始源源不断地向人类活动的各个领域渗透,机器人分拣系统和随处可见的无人机。
例如机器人分拣系统,显著地提升了物流公司货物配送的效率:
另一个例子是无人机。如果说分拣机器人还属于各大物流公司的核心机密,如下凡天仙一般平日里难得一睹芳容,那无人机早已化身邻家女孩,平易近人地装点着我们的生活:
机器人的发展不会止步于此。2020年以来,新基建概念大热,其三大方向更是与机器人产业密切相关。教育机器人、送餐机器人、情感机器人及自动驾驶技术,都是机器人及自动化技术的下一个重要落地目标:
动图来自《美国国家地理》
银河补习班里有句经典台词:“我的孩子,上的是全世界最好的补习班,银河补习班。”今天,MATLAB就为你带来宇宙最强机器人补习班,手把手教你如何建造属于自己的机器人!
许多人认为 MATLAB 是数学或教育软件。事实上,MATLAB 最初被广泛采用是在控制工程领域,随后开发了多种技术领先的算法包和工具箱,并被全球各大高校广泛采纳为数学教育软件 [1]。即将进入机器人补习班的你,准备好了吗?
第一步:安装机器人工具箱
>> ver
Robotics System Toolbox Version 2.x (Rxxxxx)
第二步:你想要什么样的机器人?建模是关键
%设置 DH 参数
dhparams = [0 pi/2 0 0;
0.4318 0 0 0;
];
robot = rigidBodyTree; % 初始化机械臂
body1 = rigidBody( body1 ); % 定义第一个连杆
jnt1 = rigidBodyJoint( jnt1 , revolute ); % 定义第一个关节
setFixedTransform(jnt1,dhparams(1,:), dh );
body1.Joint = jnt1; % 给底座加上关节
addBody(robot,body1, base ) % 定义机械臂为机器人的底座
% 添加第二、三只连杆
body2 = rigidBody( body2 );
jnt2 = rigidBodyJoint( jnt2 , revolute );
body3 = rigidBody( body3 );
jnt3 = rigidBodyJoint( jnt3 , revolute );
setFixedTransform(jnt2,dhparams(2,:), dh );
setFixedTransform(jnt3,dhparams(3,:), dh );
body2.Joint = jnt2;
body3.Joint = jnt3;
showdetails(robot)
addBody(robot,body2, body1 )
addBody(robot,body3, body2 )
show(robot); % 画图
第三步:看!它左手右手一个慢动作!
>> robot = loadrobot("kinovaGen3");
>> showdetails(robot)
>> robot.getBody( Shoulder_Link ).Joint
>> robot.getBody( Shoulder_Link ).Joint.JointToParentTransform
>> robot.getBody( Shoulder_Link ).Joint.ChildToJointTransform
% 关节起始旋转角及初始位置
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
更高级的智能
% 初始化机器人及起始点、终点
% 我们的目的是希望机器人能顺利躲过障碍物并到达终点
map = LandmarkMap(20, 10); % 10*10 地图,20 个障碍物
V = diag([0.005, 0.5*pi/180].^2); % 机器(每个步长)的误差矩阵
robot = Bicycle( covar , V); % 初始化机器人
robot.add_driver( RandomPath(10)); % 定义终点
% 定义传感器
% angle:传感器扫射角度范围
% range:传感器扫射距离
W = diag([0.1, 1*pi/180].^2); % 传感器(每个步长)的误差矩阵
sensor = RangeBearingSensor(robot, map, covar , W, ...
animate , angle , [-pi/2 pi/2], range , 5);
% 初始化 EKF, 并运行 150 个步长
P0 = diag([0.005, 0.005, 0.001].^2); % 卡曼滤波初始时刻的协方差矩阵
ekf = EKF(robot, V, P0, sensor, W, []);
ekf.run(150);
造机器人?就是如此简单!