ጦማር (Blogs)

Theoretical understanding

The very beginning step of understanding robot architecture and working principles in a professional way is learning its kinematics. Studying the kinematic behavior of robotic manipulators requires basic linear algebra understanding, and beginners are advised to review linear algebraic concepts such as vectors, matrices, and linear transformation techniques.

Basics of kinematics

Open loop

Closed loop

Hybrid

Implementation

Robotics in Python

The five bar mechanism shown in the figure 1 is a most commonly used lower DoF planar manipulator. In this


Kinematics of a closed-loop two DoF mechanism.

Figure 1: Five bar manipulator

Figure 1 2021-06-27 08-47-25_Trim.mp4

Simulation video

#Code- Python

# kinematics.py


import numpy as np

from math import acos,asin,atan,atan2,sin,cos



# 'r' for lengths

# 'a' for angles


class five_bar():

def __init__(self,link1,link2,link3,link4,link5):

self.r1 = link1

self.r2 = link2

self.r3 = link3

self.r4 = link4

self.r5 = link5


def foward(self,a1,a4):

r1 = self.r1

r2 = self.r2

r3 = self.r3

r4 = self.r4

r5 = self.r5


A_1 = r1**2-r2**2

B_1 = -2*r1*cos(a1)

C_1 = -2*r1*sin(a4)


A_2 = r5**2+r4**2-r3**2

B_2 = -2*r5 -2*r4*cos(a1)

C_2 = -2*r4*sin(a4)


D = (C_1-C_2)/(B_1-B_2)

E = (A_2-A_1)/(B_1-B_2)


F = 2*D*E + B_1*D + C_1

G = A_1 +B_1*E+ E**2

D_1 = D**2


self.y1 = (-F-np.sqrt(F**2-4*G*D_1))/(2*D_1)

self.y2 = (-F+np.sqrt(F**2-4*G*D_1))/(2*D_1)


self.x1 = D*self.y1 + E

self.x2 = D*self.y2 + E



def inverse(self,p_x,p_y):

r1 = self.r1

r2 = self.r2

r3 = self.r3

r4 = self.r4

r5 = self.r5

#### First Loop #####

A1 = p_x**2 + p_y**2 + r1**2 + 2*r1*p_x - r2**2

B1 = -4*r1*p_y

C1 = r1**2 - 2*r1*p_x + p_x**2 + p_y**2 - r2**2


t_11 = (-B1+np.sqrt(B1**2-4*A1*C1))/(2*A1)

t_12 = (-B1-np.sqrt(B1**2-4*A1*C1))/(2*A1)

self.a11 = atan2((2*t_11),(1-t_11**2))

self.a12 = atan2((2*t_12),(1-t_12**2))


#### Second Loop ####


A2 = p_x**2 + p_y**2 + r5**2 + r4**2 - 2*p_x*r5 - r3**2 + 2*p_x*r4 - 2*r4*r5

B2 = -4*p_y*r4

C2 = p_x**2 + p_y**2 + r5**2 + r4**2 - 2*p_x*r5 - r3**2 + 2*r4*r5 - 2*p_x*r4


t_21 = (-B2+np.sqrt(B2**2-4*A2*C2))/(2*A2)

t_22 = (-B2-np.sqrt(B2**2-4*A2*C2))/(2*A2)

self.a41 = atan2((2*t_21),(1-t_21**2))

self.a42 = atan2((2*t_22),(1-t_22**2))

def get_a11(self):

return self.a11


def get_a12(self):

return self.a12


def get_a2(self,a1,p_x,p_y):

a2 = atan2((p_y - self.r1*sin(a1)),(p_x-self.r1*cos(a1)))

return a2

def get_a3(self,a4,p_x,p_y):

a3 = atan2((p_y-self.r4*sin(a4)),(p_x-self.r5-self.r4*cos(a4)))

return a3

def get_a41(self):

return self.a41

def get_a42(self):

return self.a42


def get_x1(self):

return self.x1

def get_x2(self):

return self.x2

def get_y1(self):

return self.y1

def get_y2(self):

return self.y2




# graph.py

import numpy as np

import matplotlib.pyplot as plt

import matplotlib.animation as animation

import matplotlib.lines as lines

import kinematics

def onclick(event):

global cid_m

cid_m = fig.canvas.mpl_connect('motion_notify_event',pull)

def check_nan():

# to control, is the point in workspace of robot

return not np.isnan(a[0]) and not np.isnan(a[1]) and not np.isnan(a[2]) and not np.isnan(a[3])

def pull(event):

global a

x = event.xdata-origin[0]

y = event.ydata-origin[1]

#print(x,y)

robot.inverse(x,y)

a[0] = robot.get_a11()

a[1] = robot.get_a2(a[0],x,y)

a[3] = robot.get_a42()

a[2] = robot.get_a3(a[3],x,y)

#print(a)

if check_nan():

x_end.append(event.xdata)

y_end.append(event.ydata)

else:

pass

def disconnect(event):

fig.canvas.mpl_disconnect(cid_m)

def update(s):

if check_nan():

## line 1

x = [origin[0],origin[0]+r1*np.cos(a[0])]

y = [origin[1],origin[1]+r1*np.sin(a[0])]

line1.set_data(x,y)


## line 2

x = [x[1],x[1]+r2*np.cos(a[1])]

y = [y[1],y[1]+r2*np.sin(a[1])]

line2.set_data(x,y)

## line 4

x = [origin[0]+r5,origin[0]+r5+r4*np.cos(a[3])]

y = [origin[1],origin[1]+r4*np.sin(a[3])]

line4.set_data(x,y)

## line 3

x = [x[1],x[1]+r3*np.cos(a[2])]

y = [y[1],y[1]+r3*np.sin(a[2])]

line3.set_data(x,y)

## line 5

x = [origin[0],origin[0]+r5]

y = [origin[1],pad]

line5.set_data(x,y)

line6.set_data(x_end,y_end)

else:

pass

return line6,line1,line2,line3,line4,line5

# pyhsical constrait of five bar mechanism, to get further information check kinetics.py

# Please change r[1:5] values, if you want to try another configuration

r1 = 60

r2 = 100

r3 = 100

r4 = 60

r5 = 80

robot = kinematics.five_bar(r1,r2,r3,r4,r5)

x_in = 40 # initial end efector y position

y_in = 150 # initial end efector y position

# initial declarations of graph

pad = 30 # do not make me zero, unless you do not want everything will mess up

if r2>r3:

big_l = r2

else:

big_l = r3

a = [0,0,0,0]

xmax = r1+big_l+r5/2+pad

ymax = r1+big_l+pad*2

fig, ax = plt.subplots()

ax.axis([0,xmax,0,ymax])

origin = [xmax/2-r5/2,pad]

line1, = ax.plot([], [],lw=2,animated=True,c='b')

line2, = ax.plot([], [],lw=2,animated=True,c='b')

line3, = ax.plot([], [],lw=2,animated=True,c='b')

line4, = ax.plot([], [],lw=2,animated=True,c='b')

line5, = ax.plot([], [],lw=2,animated=True,c='b')

line6, = ax.plot([], [],lw=1,animated=True,c='g')

robot.inverse(x_in,y_in)

a[0] = robot.get_a11()

a[1] = robot.get_a2(a[0],x_in,y_in)

a[3] = robot.get_a42()

a[2] = robot.get_a3(a[3],x_in,y_in)

x_end = []

y_end = []

# graph control functions

fig.canvas.mpl_connect('button_press_event', onclick)

fig.canvas.mpl_connect('button_release_event',disconnect)

ani = animation.FuncAnimation(fig, update,frames=None,blit=True,interval=25)

plt.show()


Robotics in MATLAB