Project

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.

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.