2R Robotic Arm Simulation using forward kinematics (MATLAB)
Aim: Simulation of 2R Robotic Arm using forward kinematics
Objective: Generate animation to visualize arm workspace
Following assumptions were made for the simulation, a few additional assumptions have been made to demonstrate the level of control over the simulation.
Assumption:
1) A robotic arm with two links of length L and l are considered
2) The links are assumed to have a planar workspace say X-Y
3) Link 1 is connected to the base through joint 1 and link 2 is connected to link one through joint 2
4) Link 1 makes an angle 'T' and Link 2 makes an angle 't' with respect to +ve X-axis.
5) The links move in the X-Y plane at the joints about the Z axis.
6) The base is assumed to an infinite table along X-Z palne and the arm is fixed at co-ordinates (0,0,0) in the assumed co-ordinate system.
Implications:
1) The arms cannot enter -Y plane
2) Link 1 moves from 0degrees to 180degrees
3) range of 't' is dependant on 'T'
Procedure:
1) A function was defined to generate the co-ordinates of the link end points when the lengths and angles described by the links are given:
function [a1 b1 a2 b2] = nodes(L,l,T,t)
a1 = L*cosd(T);
b1 = L*sind(T);
a2 = (L*cosd(T))+(l*cosd(t));
b2 = (L*sind(T))+(l*sind(t));
end
2) Loops and conditional statements were used to assign various possible 'T' and 't' values and the constraints for 't' were arrived at by using simple geometry and basic trignometry.
3) For each combination of T,t that was thus generated, the end points of the links were then plotted by calling in the user defined function and using the output in the plot function
4) Simultaneously the plots were saved into an array in the form of frames using 'getframe' function which was later used to generate an uncompressed AVI video using matlab's inbuild VideoWriter function.
Conditions Explanation:
As the arm is restricted to +Y plane, for T such that link2 cannot rotate a complete 360degrees, limits need to found. On one end the link can rotate till it aligns with link1, on the other it can rotate till it meets the X-axis.
When link2 meets the axis, basic triangle properties can be used to determine the angle 't'. Thus the limits for t can be found based on T.
Using the same conditions for 'T' where such ranges are applicable can also be found by simply making sure (Lsin(T)/l) is less than one. For all other cases link2 can simply rotate 360degrees.
Problems and Solutions:
1) Warning on non real scalar assignments:
Solution: While the angles used through out the program were in degrees, it is clear that in lines 15 and 8 a 'sin' command was used to call sin function. Changing the command to sind solved the issue
2) Warning on non real scalar entries:
Solution: Similar problem arose again but this time it was due to a typing error, instead of using letter 'l' in line 19 column 36 number '1' was used. Correcting the typo solved the issue.
Final code:
clear all
close all
clc
L = 1
l = 0.75
i=1;
for T = 0:10:180
if L*sind(T) < l && T <= 90
a = -(asind((L*sind(T))/l));
for t = linspace(a,(180+T),30)
[x1 y1 x2 y2] = nodes(L,l,T,t);
plot([0 x1],[0 y1],[x1 x2],[y1 y2],'linewidth',2)
axis([-2 2 -1 2])
grid on
pause(0.02)
F(i)=getframe(gcf);
i = i+1;
end
elseif L*sind(T) < l
a = 180+asind(L*sind(T)/l);
for t = linspace(-(180-T),a,30)
[x1 y1 x2 y2] = nodes(L,l,T,t);
plot([0 x1],[0 y1],[x1 x2],[y1 y2],'linewidth',2)
axis([-2 2 -1 2])
grid on
pause(0.02)
F(i)=getframe(gcf);
i = i+1;
end
else
for t = linspace(-(180-T),(180+T),30)
[x1 y1 x2 y2] = nodes(L,l,T,t);
plot([0 x1],[0 y1],[x1 x2],[y1 y2],'linewidth',2)
axis([-2 2 -1 2])
grid on
pause(0.02)
F(i)=getframe(gcf);
i = i+1;
end
end
end
movie(F)
v = VideoWriter('RoboArmConstraint.avi','uncompressed AVI');
open(v)
writeVideo(v,F)
close(v)
Results and Discussion:
1) The animation shows the entire workspace of a 2R Robotic arm
2) The constraints were achieved and can be observed in the animation.
3) Length of the code reduced with the use of user defined function for determining the nodes
4) Number of variables was also reduced by directly using the angle variables to initiate and run the loops instead of introducing a separate variable to do so.
5)Variables used for making the video were also experimented upon to check the freedom in naming convention given by the software.
Animation:
RoboArmFrwdKinematics.avi
Scope:
1) Length of code can further be reduced by defining a function to plot and capture frames.
2) variable 'a' was used to calculate the limiting value for 't', the condition can directly be used in the colon operator eliminating the need for the variable and also reducing the length of code
Extension:
1) To display the constraints more clearly I wanted to plot the X-axis, so I used the 'hold on' command and added the plot for the axis with color and thickness specifications. But 'hold on' command would hold the plots of all the iterations so I had used a clf command to clear the figure.
Note: The code uses same nodes function.
clear all
close all
clc
L = 1
l = 0.75
i=1;
for T = 0:10:180
if L*sind(T) < l && T <= 90
a = -(asind((L*sind(T))/l));
for t = linspace(a,(180+T),30)
[x1 y1 x2 y2] = nodes(L,l,T,t);
hold on
plot([0 x1],[0 y1],[x1 x2],[y1 y2],'linewidth',2);
plot([-2 2],[0 0],'linewidth',1,'color',[0 0 0]);
axis([-2 2 -1 2])
grid on
pause(0.02)
F(i) = getframe(gcf);
clf
i = i+1;
end
elseif L*sind(T) < l
a = 180+asind(L*sind(T)/l);
for t = linspace(-(180-T),a,30)
[x1 y1 x2 y2] = nodes(L,l,T,t);
hold on
plot([0 x1],[0 y1],[x1 x2],[y1 y2],'linewidth',2);
plot([-2 2],[0 0],'linewidth',1,'color',[0 0 0]);
axis([-2 2 -1 2])
grid on
pause(0.02)
F(i)=getframe(gcf);
clf
i = i+1;
end
else
for t = linspace(-(180-T),(180+T),30)
[x1 y1 x2 y2] = nodes(L,l,T,t);
hold on
plot([0 x1],[0 y1],[x1 x2],[y1 y2],'linewidth',2);
plot([-2 2],[0 0],'linewidth',1,'color',[0 0 0]);
axis([-2 2 -1 2])
grid on
pause(0.02)
F(i) = getframe(gcf);
clf
i = i+1;
end
end
end
movie(F)
v = VideoWriter('RoboArmConstraint.avi','uncompressed AVI');
open(v)
writeVideo(v,F)
close(v)
Results:
RoboArmConstraint.avi
2) Octave does not have an inbulit movie function hence each frame was first captured to a variable using sprintf command with names based on a counter in png format and then saved using 'saveas' function. Files were later tailored into a gif using Image Magick.
Note: same nodes function was used.
clear all
close all
clc
L = 1
l = 0.75
i=1;
for T = 0:18:180
if L*sind(T) < l && T <= 90
for t = linspace(-(asind((L*sind(T))/l)),(180+T),10)
[x1 y1 x2 y2] = nodes(L,l,T,t);
plot([0 x1],[0 y1],[x1 x2],[y1 y2],'linewidth',2)
axis([-2 2 -1 2])
grid on
pause(0.001)
F=sprintf("roboarm%d.png",i);
saveas(gca,F);
i = i+1;
end
elseif L*sind(T) < l
for t = linspace(-(180-T),180+asind(L*sind(T)/l),10)
[x1 y1 x2 y2] = nodes(L,l,T,t);
plot([0 x1],[0 y1],[x1 x2],[y1 y2],'linewidth',2)
axis([-2 2 -1 2])
grid on
pause(0.001)
F=sprintf("roboarm%d.png",i);
saveas(gca,F);
i = i+1;
end
else
for t = linspace(-(180-T),(180+T),10)
[x1 y1 x2 y2] = nodes(L,l,T,t);
plot([0 x1],[0 y1],[x1 x2],[y1 y2],'linewidth',2)
axis([-2 2 -1 2])
grid on
pause(0.001)
F=sprintf("roboarm%d.png",i);
saveas(gca,F);
i = i+1;
end
end
end
Results:
Animation.gif
The gif made from raw png files obtained from the program had issues in the order of images as naming was based on the counter. the files were named x1, x10, x100 etc and not x001, x010, x100.
So the order was not as expected. Manually adding zeros in the name fixed the error. But better naming convension could make it easier.