Introduction
Coordinate Transformation in 2D
The motion of manipulators and robots is often very complex and mathematically demanding. A single coordinate frame usually isn’t sufficient, and its often convenient to use multiple coordinate frames (fixed or moving) to make things easier.
Terminology
Fixed and World coordinate frames are used interchangeably and mean the same thing.
Mobile and Moving coordinate frames are used interchangeably and mean the same thing.
What is a Coordinate Frame ?
If
Translation
Assume a fixed frame
The following inferences can be made from the above figure:
Position of C
Position of C
Position of
Position of
Rotation
Assume a fixed frame
The following equations can be written down based on the above figure
Upon rearranging the terms,
The above trigonometric matrix is called the rotation matrix, denoted by
Combined Translation & Rotation
Assume a fixed frame
The coordinates of point C between the mobile and fixed frame can be related using the following:
2D - RR Manipulator
Consider the following manipulator diagram for a 2 DoF planar robotic arm.
Forward Kinematics
The equations for the RR manipulator can be used to draw the arm in MATLAB, the code for the same is given below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
%% Lec1_RRManu.m %%
clc
%clear all
close all
%% Manipulator Parameters
l1 = 0.5; l2 = 0.3;
theta1 = 0.3; theta2 = 0.4;
%% World Frame
x_0 = 0; y_0 = 0;
%% Link 1
x_p0 = l1 * cos(theta1);
y_p0 = l1 * sin(theta1);
%% Link 2
x_q0 = l1 * cos(theta1) + l2 * cos(theta1 + theta2);
y_q0 = l1 * sin(theta1) + l2 * sin(theta1 + theta2);
%% Draw Lines
line([x_0, x_p0], [y_0, y_p0], 'Linewidth', 5, 'Color', [204, 204, 1] / 255);
line([x_q0, x_p0], [y_q0, y_p0], 'Linewidth', 5, 'Color', 'cyan');
axis('equal');
xlabel('x');
ylabel('y');
title('RR-Manipulator')
Upon executing the code you should be able see something similar in your figure window.
Inverse Kinematics
We can also solve for
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
%% Lec2_InverseRRManu.m %%
clc
close all
l1 = 0.5; l2 = 0.5;
x_ref = 0.5; y_ref = 0;
param = [l1 l2 x_ref y_ref];
x0 = [0.1 0.1];
[x, fval, exitflag] = fsolve(@Lec2_InvFun, x0, optimoptions('fsolve', 'Display', 'iter'), param)
theta1 = x(1);
theta2 = x(2);
%% World Frame
x_0 = 0; y_0 = 0;
%% Link 1
x_p0 = l1 * cos(theta1);
y_p0 = l1 * sin(theta1);
%% Link 2
x_q0 = l1 * cos(theta1) + l2 * cos(theta1 + theta2);
y_q0 = l1 * sin(theta1) + l2 * sin(theta1 + theta2);
%% Draw Lines
line([x_0, x_p0], [y_0, y_p0], 'Linewidth', 5, 'Color', [204, 204, 1] / 255);
line([x_q0, x_p0], [y_q0, y_p0], 'Linewidth', 5, 'Color', 'cyan');
axis('equal');
xlabel('x');
ylabel('y');
title('RR-Manipulator')
As you might have noticed the above program depends on an external function called \verb|Lec2_InvFun|. The code for the function is given below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
%% Lec2_InvFun.m %%
function F = Lec2_InvFun(x, param)
l1 = param(1); l2 = param(2);
x_ref = param(3); y_ref = param(4);
theta1 = x(1); theta2 = x(2);
x_q0 = l1 * cos(theta1) + l2 * cos(theta1 + theta2);
y_q0 = l1 * sin(theta1) + l2 * sin(theta1 + theta2);
F = [x_q0 - x_ref; y_q0 - y_ref];
end
Upon executing the code you should be able see something similar in your figure window
Tracing Trajectories
If we can write the mathematical equation for a curve the x,y points on the curve can be passed into the inverse kinematics block for the manipulator which allows the robotic arm to trace the shape of the curve. The below given program does the same, it also shows the animation of the manipulator. Note, that the below given program uses
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
%% Lec2_TrajManu.m %%
clc
close all
%% Parameter Setting
l1 = 1; l2 = 1;
%% Trajectory Generator
phi = linspace(0, 2 * pi, 51);
x_ref = 1 + 0.5 * cos(phi); y_ref = 0.5 + 0.5 * sin(phi);
theta1 = 0.5; theta2 = 0.5;
theta1_f = zeros(length(phi), 1);
theta2_f = zeros(length(phi), 1);
for i = 1:length(phi)
theta = [theta1, theta2];
options = optimoptions('fsolve', 'Display', 'Off', 'MaxIter', 100, 'MaxFunEval', 300);
param = [l1 l2 x_ref(i) y_ref(i)];
[x, fval, exitflag] = fsolve(@Lec2_InvFun, theta, options, param);
theta1 = x(1); theta2 = x(2);
theta1_f(i, 1) = x(1);
theta2_f(i, 1) = x(2);
end
%% World Frame
x_0 = 0; y_0 = 0;
%% Animation
for i = 1:length(phi)
% Link 1
x_p0 = l1 * cos(theta1_f(i));
y_p0 = l1 * sin(theta1_f(i));
% Link 2
x_q0 = l1 * cos(theta1_f(i)) + l2 * cos(theta1_f(i) + theta2_f(i));
y_q0 = l1 * sin(theta1_f(i)) + l2 * sin(theta1_f(i) + theta2_f(i));
% Tracer
plot(x_q0, y_q0, 'ko', "MarkerSize", 5, 'MarkerEdgeColor', 'k', 'MarkerFaceColor', 'k');
hold on;
h1 = line([x_0, x_p0], [y_0, y_p0], 'Linewidth', 5, 'Color', [204, 204, 1] / 255);
h2 = line([x_q0, x_p0], [y_q0, y_p0], 'Linewidth', 5, 'Color', 'cyan');
grid on;
axis('equal');
xlabel('x');
ylabel('y');
title('RR-Manipulator')
xlim([- 2 2]);
ylim([- 2 2]);
pause(0.3);
if i < length(phi)
delete(h1);
delete(h2);
end
end
Upon executing the code you should be able see something similar in your figure window
Differential Drive
Consider a fixed frame (
Let
Forward Kinematics
The forward kinematics of the differential drive car involves finding (
The distance traveled by the wheel if it rotates by an angle
Case 1:
The distance moved by the right wheel is given by,
From geometry, the speed of the center C in the direction of
Case 2:
From symmetry similar arguments can be made for the left wheel, giving the following equations.
From case 1 \& 2, the velocity of the point C in the directions of
The velocity of point C in frame 0 and 1 can be related as,
For finding the expression for rate of change of
Case 1:
from geometry,
therefore gives,
Similar arguments can be made for the other case, only exception being the angle
Therefore to summarize,
To find
Upon rearranging the terms,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
%% Lec3_DiffCar.m %%
clc
close all
parms.R = 0.1; %Radius of the chassis for animation
% parms.writeMovie = 0; %set to 1 to get a movie output
% parms.nameMovie = 'car.avi';
%% Initialize States
fps = 10;
parms.delay = 0.2;
z0 = [0 0 - pi / 2]; %initial position of the car
h = 0.1; %step size
%% Motion
t1 = 0:h:1;
speed1 = ones(1, length(t1));
omega1 = zeros(1, length(t1));
t2 = 1 + h:h:2;
speed2 = zeros(1, length(t2));
omega2 = pi / 2 * ones(1, length(t2));
t3 = 2 + h:h:3;
speed3 = ones(1, length(t3));
omega3 = zeros(1, length(t3));
t4 = 3 + h:h:4;
t5 = 4 + h:h:5;
t6 = 5 + h:h:6;
t7 = 6 + h:h:7;
t = [t1 t2 t3 t4 t5 t6 t7];
speed = [speed1 speed2 speed3 speed2 speed3 speed2 speed3];
omega = [omega1 omega2 omega3 omega2 omega3 omega2 omega3];
%% Euler Integration
z = z0; %Initial parameters
for i = 1:length(t) - 1
u = [speed(i) omega(i)];
zz = Lec3_Euler(h, z0, u);
z0 = zz;
z = [z; z0];
end
% t_interp = linspace(0,t(end),fps*t(end));
% [m,n] = size(z);
% for i=1:n
% z_interp(:,i) = interp1(t,z(:,i),t_interp);
% end
%% Animation
figure(1)
Lec3_Animate(t, z, parms);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
%% Lec3_Animate.m %%
function Lec3_Animate(t, z, parms)
R = parms.R;
phi = linspace(0, 2 * pi);
x_circle = R * cos(phi);
y_circle = R * sin(phi);
% if (parms.writeMovie)
% mov = VideoWriter(parms.nameMovie);
% open(mov);
%end
n = length(t);
for i = 1:n
theta = z(i, 3);
x_robot = z(i, 1) + x_circle;
y_robot = z(i, 2) + y_circle;
x_dir = z(i, 1) + [0 R * cos(theta)];
y_dir = z(i, 2) + [0 R * sin(theta)];
plot(z(1:i, 1), z(1:i, 2), 'r', 'Linewidth', 2); hold on;
light_blue = [176, 224, 230] / 255;
h1 = patch(x_robot, y_robot, light_blue);
h2 = line(x_dir, y_dir, 'Color', 'black', 'Linewidth', 2);
axis('equal');
%span = max([-min(min(z(:,1:2))) max(max(z(:,1:2)))]);
%span = max([span 2]);
%axis([-span span -span span]);
axis([- 2 2 - 2 2]);
grid on;
pause(parms.delay)
delete(h1);
delete(h2);
% if (parms.writeMovie)
% axis off %does not show axis
% set(gcf,'Color',[1,1,1]) %set background to white
% writeVideo(mov,getframe);
% end
end
% if (parms.writeMovie)
% close(mov);
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
%% Lec3_Euler.m %%
function F = Lec3_Euler(h, z0, u)
v = u(1);
omega = u(2);
x_t0 = z0(1);
y_t0 = z0(2);
theta_t0 = z0(3);
xdot_c = v * cos(theta_t0);
ydot_c = v * sin(theta_t0);
thetadot = omega;
x_t1 = x_t0 + xdot_c * h;
y_t1 = y_t0 + ydot_c * h;
theta_t1 = theta_t0 + thetadot * h;
F = [x_t1, y_t1, theta_t1];
end
Upon successful execution of the above program you should be able to see a figure similar to this
Inverse Kinematics
Inverse Kinematics is defined as finding the values of
From previous sections, we have the following relations
Differentiating the above equations with time,
We will be using a proportional controller for driving the error towards zero.
Where
Also from forward kinematics we know the following,
All of the above derived equations can be used to create a trajectory following differential drive robot the code attached below follows a mathematical trajectory called “astroid” the code also has an PD controller implemented to keep the error close to zero.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
%% Lec4_InvDiff.m %%
clc
close all
%% Parameters
parms.R = 0.1;
parms.px = 0.05;
parms.py = 0;
parms.Kp = 100;
parms.Kd = 0.5;
parms.delay = 0.001;
t0 = 0;
tend = 10;
fps = 10;
t = t0:0.01:tend;
h = 0.01;
%% Trajectory
x_center = 0;
y_center = 0;
a = 1;
x_ref = x_center + a * cos(2 * pi * t / tend) .^ 3;
y_ref = y_center + a * sin(2 * pi * t / tend) .^ 3;
%% Initilization
theta0 = pi / 2;
[x0 y0] = Lec4_ptP_to_ptC(x_ref(1), y_ref(1), theta0, parms);
z0 = [x0 y0 theta0];
z = z0;
e = [0 0];
v = 0;
omega = 0;
for i = 1:length(t) - 1
x_c = z(end, 1);
y_c = z(end, 2);
theta = z(end, 3);
[x_p, y_p] = Lec4_ptC_to_ptP(x_c, y_c, theta, parms);
error = [x_ref(i + 1) - x_p y_ref(i + 1) - y_p];
e = [e; error];
err_p_dot = [parms.Kp * error(1) + parms.Kd * ((e(end, 1) - e(end - 1, 1)) / h); parms.Kp * error(2) + parms.Kd * ((e(end, 2) - e(end - 1, 2)) / h)];
c = cos(theta); s = sin(theta);
px = parms.px; py = parms.py;
A = [c - (py / px) * s s + (py / px) * c; ...
- (1 / px) * s (1 / px) * c];
u = A * err_p_dot; %u = [v omega]
v = [v; u(1)];
omega = [omega; u(2)];
%zz = ode4(@Lec4_RHS,[t(i) t(i+1)],z0,u);
zz = Lec3_Euler(h, z0, u);
z0 = zz(end, :);
z = [z; z0];
end
t_interp = linspace(t0, tend, fps * tend);
[m, n] = size(z);
for i = 1:n
z_interp(:, i) = interp1(t, z(:, i), t_interp);
end
figure(1)
Lec3_Animate(t_interp, z_interp, parms);
figure(2)
subplot(2, 1, 1)
plot(t, v, 'm'); hold on
plot(t, omega, 'c');
ylabel('Velocity');
legend('v', '\omega', 'Location', 'Best');
subplot(2, 1, 2)
plot(t, e(:, 1), 'r'); hold on
plot(t, e(:, 2), 'b');
legend('error x', 'error y', 'Location', 'Best');
ylabel('error');
xlabel('time');
1
2
3
4
5
6
7
8
9
%% Lec4_ptC_to_ptP.m %%
function [x_p, y_p] = Lec4_ptC_to_ptP(x_c, y_c, theta, parms)
c = cos(theta); s = sin(theta);
p = [parms.px; parms.py];
Xp = [c - s; s c] * p + [x_c; y_c];
x_p = Xp(1); y_p = Xp(2);
end
1
2
3
4
5
6
7
8
%% Lec4_ptP_to_ptC.m %%
function [x_c, y_c] = Lec4_ptP_to_ptC(x_p, y_p, theta, parms)
c = cos(theta); s = sin(theta);
p = [parms.px; parms.py];
Xc = - [c - s; s c] * p + [x_p; y_p];
x_c = Xc(1); y_c = Xc(2);
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
%% ode4.m %%
function Y = ode4(odefun, tspan, y0, varargin)
%ODE4 Solve differential equations with a non-adaptive method of order 4.
% Y = ODE4(ODEFUN,TSPAN,Y0) with TSPAN = [T1, T2, T3, ... TN] integrates
% the system of differential equations y' = f(t,y) by stepping from T0 to
% T1 to TN. Function ODEFUN(T,Y) must return f(t,y) in a column vector.
% The vector Y0 is the initial conditions at T0. Each row in the solution
% array Y corresponds to a time specified in TSPAN.
%
% Y = ODE4(ODEFUN,TSPAN,Y0,P1,P2...) passes the additional parameters
% P1,P2... to the derivative function as ODEFUN(T,Y,P1,P2...).
%
% This is a non-adaptive solver. The step sequence is determined by TSPAN
% but the derivative function ODEFUN is evaluated multiple times per step.
% The solver implements the classical Runge-Kutta method of order 4.
%
% Example
% tspan = 0:0.1:20;
% y = ode4(@vdp1,tspan,[2 0]);
% plot(tspan,y(:,1));
% solves the system y' = vdp1(t,y) with a constant step size of 0.1,
% and plots the first component of the solution.
%
if ~ isnumeric(tspan)
error('TSPAN should be a vector of integration steps.');
end
if ~ isnumeric(y0)
error('Y0 should be a vector of initial conditions.');
end
h = diff(tspan);
if any(sign(h(1)) * h <= 0)
error('Entries of TSPAN are not in order.')
end
try
f0 = feval(odefun, tspan(1), y0, varargin{:});
catch
msg = ['Unable to evaluate the ODEFUN at t0,y0. ', lasterr];
error(msg);
end
y0 = y0(:); % Make a column vector.
if ~ isequal(size(y0), size(f0))
error('Inconsistent sizes of Y0 and f(t0,y0).');
end
neq = length(y0);
N = length(tspan);
Y = zeros(neq, N);
F = zeros(neq, 4);
Y(:, 1) = y0;
for i = 2:N
ti = tspan(i - 1);
hi = h(i - 1);
yi = Y(:, i - 1);
F(:, 1) = feval(odefun, ti, yi, varargin{:});
F(:, 2) = feval(odefun, ti + 0.5 * hi, yi + 0.5 * hi * F(:, 1), varargin{:});
F(:, 3) = feval(odefun, ti + 0.5 * hi, yi + 0.5 * hi * F(:, 2), varargin{:});
F(:, 4) = feval(odefun, tspan(i), yi + hi * F(:, 3), varargin{:});
Y(:, i) = yi + (hi / 6) * (F(:, 1) + 2 * F(:, 2) + 2 * F(:, 3) + F(:, 4));
end
Y = Y.';
1
2
3
4
5
6
7
8
9
10
%% Lec4_RHS.m %%
function zdot = Lec4_RHS(t, z, u)
v = u(1); omega = u(2);
theta = z(3);
x_c_dot = v * cos(theta);
y_c_dot = v * sin(theta);
theta_dot = omega;
zdot = [x_c_dot y_c_dot theta_dot]';
Upon successful execution of the above program, you will end up with the following two figures.
Projectile Motion
2-D projectile motion will be analyzed in this section, Euler Lagrange Equations will be introduced and used for finding out the equations of motion of the projectile.
Forward Kinematics
Let the position of the projectile wrt to the fixed frame be denoted as (
From Euler-Lagrange Formulaizm,
Given that,
In the direction of x,
In the direction of y,
Integrating