Motor Selection

1b) Motor Selection

SG90 Specification

●	Rotation : 0°-180°


●	Weight of motor : 9gm


●	Operating Voltage : +5 V


●	Stall Current : 350 mA


●	Stall Torque : 2.5 kg . cm = 0.24 N.m


●	Speed : 0.12s / 60° = 82.8 rpm


●	Power : Torque * Speed / 9.5488 = 2.08 kW

This motor was selected due to the requirement of having a very lightweight actuator which did not lack the torque to move the entire load of the robot.

Power Supply Selection

1c) Power Supply Selection:

Given the stall current of the motors being used, a power supply capable of supplying far more than 350 mA is required. An Alkaline 9v battery is chosen as the power supply for the system which satisfies this requirement and has enough battery capacity to sustain the robot to operate for a reasonable span of time.

Static Friction Calculation

Static Friction Calculation:

The Angle of Repose experiment was conducted to determine the static friction coefficient of the cardstock on a smooth surface. The platform having the cardstock is lifted slowly with increasing angle to find that critical angle at which the paper starts sliding down.

Trial 1:

Coefficient of Static Friction : 0.3141

Trial 2 :

Coefficient of Static Friction : 0.4575

Trial 3 :

Coefficient of Static Friction : 0.3803

Average Coefficient of Static Friction : 0.38399


Average Coefficient of Static Friction : 0.3057

Approximation : The coefficient of kinetic friction could be determined during the same Angle of Repose experiment where the angle corresponding to when the cardstock slips down the inclined surface at constant velocity is noted. An angle of ~17 degrees let the cardstock slip down in an approximately constant velocity. Thus coefficient of kinetic friction = tan (17) = 0.3057

Compliance Calculation Using Two-Beam Method

import sympy
q = sympy.Symbol('q')
d = sympy.Symbol('d')
L = sympy.Symbol('L')
P = sympy.Symbol('P')
h = sympy.Symbol('h')
b = sympy.Symbol('b')
E = sympy.Symbol('E')
x = sympy.Symbol('x')
subs = {}
#subs[k]=1000
subs[P]=.0098
subs[L]=.100
subs[b]=.025
subs[h]=.005
subs[E]= 1.551e9
subs[x]=.5
I = b*h**3/12
d1 = P*L**3/3/E/I
d1.subs(subs)

$\displaystyle 8.08768536428111 \cdot 10^{-6}$

q1 = P*L**2/2/E/I
q1.subs(subs)

$\displaystyle 0.000121315280464217$

k1 = P*L*(1-x)/(sympy.asin(P*L**2/(3*E*I*(1-x))))
k1.subs(subs)

$\displaystyle 3.02929686179011$

d2 = L*(1-x)*sympy.sin(P*L*(1-x)/k1)
d2.subs(subs)

$\displaystyle 8.08768536428111 \cdot 10^{-6}$

q2 = P*L*(1-x)/k1
q2.subs(subs)

$\displaystyle 0.000161753707990983$

k2 = 2*E*I*(1-x)/(L)
k2

$\displaystyle \frac{E b h^{3} \left(1 - x\right)}{6 L}$

q3 = P*L*(1-x)/k2
q3.subs(subs)

$\displaystyle 0.000121315280464217$

d3 = L*(1-x)*sympy.sin(P*L*(1-x)/k2)
d1.subs(subs)

$\displaystyle 8.08768536428111 \cdot 10^{-6}$

d3.subs(subs)

$\displaystyle 6.06576400833212 \cdot 10^{-6}$

del subs[x]
error = []
error.append(d1-d2)
error.append(q1-q2)
error= sympy.Matrix(error)
error = error.subs(subs)
error

$\displaystyle \left[\begin{matrix}0\0.000121315280464217 - \operatorname{asin}{\left(\frac{8.08768536428111 \cdot 10^{-5}}{1 - x} \right)}\end{matrix}\right]$

import scipy.optimize
f = sympy.lambdify((x),error)
def f2(args):
    a = f(*args)
    b = (a**2).sum()
    return b
sol = scipy.optimize.minimize(f2,[.25])
sol
      fun: 1.816962570090524e-10
 hess_inv: array([[1]])
      jac: array([-3.87618667e-09])
  message: 'Optimization terminated successfully.'
     nfev: 2
      nit: 0
     njev: 1
   status: 0
  success: True
        x: array([0.25])
subs[x]=sol.x[0]
d2.subs(subs)


$\displaystyle 8.08768536428111 \cdot 10^{-6}$

q2.subs(subs)

$\displaystyle 0.000107835805066077$

k2.subs(subs)

$\displaystyle 6.05859375$



Cantilever Beams Material Experiment

Beams1

Beams2

Beams3

Beams4

Beams5

Solidworks Bending FEA

FEA1

FEA2

FEA3

FEA4

Joint Damping Data Collection

Damp1

Damp2

Damp3

Joint Damping Calculations

import pynamics
from pynamics.frame import Frame
from pynamics.variable_types import Differentiable,Constant
from pynamics.system import System
from pynamics.body import Body
from pynamics.dyadic import Dyadic
from pynamics.output import Output,PointsOutput
from pynamics.particle import Particle
import pynamics.integration
import numpy
import matplotlib.pyplot as plt
plt.ion()
from math import pi

import logging
import pynamics.integration
import pynamics.system
import numpy.random
import scipy.interpolate
import scipy.optimize
#import cma
import pandas as pd
import numpy
import matplotlib.pyplot as plt
import scipy.interpolate as si


system = System()
pynamics.set_system(__name__,system)

lA = Constant(1,'lA',system)
lB = Constant(1,'lB',system)
lC = Constant(1,'lC',system)

mA = Constant(1,'mA',system)
mB = Constant(1,'mB',system)
mC = Constant(1,'mC',system)

g = Constant(9.81,'g',system)
b = Constant(1e1,'b',system)
k = Constant(1e1,'k',system)

preload1 = Constant(0*pi/180,'preload1',system)
preload2 = Constant(0*pi/180,'preload2',system)
preload3 = Constant(0*pi/180,'preload3',system)

Ixx_A = Constant(1,'Ixx_A',system)
Iyy_A = Constant(1,'Iyy_A',system)
Izz_A = Constant(1,'Izz_A',system)
Ixx_B = Constant(1,'Ixx_B',system)
Iyy_B = Constant(1,'Iyy_B',system)
Izz_B = Constant(1,'Izz_B',system)
Ixx_C = Constant(1,'Ixx_C',system)
Iyy_C = Constant(1,'Iyy_C',system)
Izz_C = Constant(1,'Izz_C',system)

tol = 1e-12

tinitial = 0
tfinal = 10
fps = 30
tstep = 1/fps
t = numpy.r_[tinitial:tfinal:tstep]

qA,qA_d,qA_dd = Differentiable('qA',system)
qB,qB_d,qB_dd = Differentiable('qB',system)
qC,qC_d,qC_dd = Differentiable('qC',system)

initialvalues = {}
initialvalues[qA]=-45*pi/180
initialvalues[qA_d]=0*pi/180
initialvalues[qB]=0*pi/180
initialvalues[qB_d]=0*pi/180
initialvalues[qC]=0*pi/180
initialvalues[qC_d]=0*pi/180

statevariables = system.get_state_variables()
ini = [initialvalues[item] for item in statevariables]

N = Frame('N')
A = Frame('A')
B = Frame('B')
C = Frame('C')

system.set_newtonian(N)

A.rotate_fixed_axis_directed(N,[0,0,1],qA,system)
B.rotate_fixed_axis_directed(A,[0,0,1],qB,system)
C.rotate_fixed_axis_directed(B,[0,0,1],qC,system)

pNA=0*N.x
pAB=pNA+lA*A.x
pBC = pAB + lB*B.x
pCtip = pBC + lC*C.x

pAcm=pNA+lA/2*A.x
pBcm=pAB+lB/2*B.x
pCcm=pBC+lC/2*C.x

wNA = N.getw_(A)
wAB = A.getw_(B)
wBC = B.getw_(C)

IA = Dyadic.build(A,Ixx_A,Iyy_A,Izz_A)
IB = Dyadic.build(B,Ixx_B,Iyy_B,Izz_B)
IC = Dyadic.build(C,Ixx_C,Iyy_C,Izz_C)

BodyA = Body('BodyA',A,pAcm,mA,IA,system)
BodyB = Body('BodyB',B,pBcm,mB,IB,system)
BodyC = Body('BodyC',C,pCcm,mC,IC,system)

system.addforce(-b*wNA,wNA)
system.addforce(-b*wAB,wAB)
system.addforce(-b*wBC,wBC)

system.add_spring_force1(k,(qA-preload1)*N.z,wNA) 
system.add_spring_force1(k,(qB-preload2)*N.z,wAB)
system.add_spring_force1(k,(qC-preload3)*N.z,wBC)

system.addforcegravity(-g*N.y)

eq = []
# eq.append(pCtip.dot(N.y))
eq_d=[(system.derivative(item)) for item in eq]
eq_dd=[(system.derivative(item)) for item in eq_d]

f,ma = system.getdynamics()


2021-03-19 23:04:28,290 - pynamics.system - INFO - getting dynamic equations
unknown_constants = [b,k]
known_constants = list(set(system.constant_values.keys())-set(unknown_constants))
known_constants = dict([(key,system.constant_values[key]) for key in known_constants])
func1,lambda1 = system.state_space_post_invert(f,ma,eq_dd,return_lambda = True,constants = known_constants)

2021-03-19 23:04:28,464 - pynamics.system - INFO - solving a = f/m and creating function
2021-03-19 23:04:28,749 - pynamics.system - INFO - substituting constrained in Ma-f.
2021-03-19 23:04:28,868 - pynamics.system - INFO - done solving a = f/m and creating function
2021-03-19 23:04:28,869 - pynamics.system - INFO - calculating function for lambdas
def run_sim(args):
    constants = dict([(key,value) for key,value in zip(unknown_constants,args)])
    states=pynamics.integration.integrate(func1,ini,t,rtol=tol,atol=tol,hmin=tol, args=({'constants':constants},))
    return states
points = [pNA,pAB,pBC,pCtip]

#create data

points_output = PointsOutput(points,system)
df=pd.read_csv(r'/Users/sanchit/Downloads/data.csv', sep=',')

x = df.x.to_numpy()
y = df.y.to_numpy()
t = df.t.to_numpy()
xy = numpy.array([x,y]).T


fy = scipy.interpolate.interp1d(t,xy.T,fill_value='extrapolate')
fyt = fy(t).T


plt.figure()
plt.plot(t,fyt)
[<matplotlib.lines.Line2D at 0x7f959296e450>,
 <matplotlib.lines.Line2D at 0x7f959296e650>]

png

def calc_error(args):
    states_guess = run_sim(args)
    y_guess = points_output.calc(states_guess)
    y_guess = y_guess.reshape((390,-1))
    print(y_guess.shape)
    error = fyt - y_guess
    error **=2
    error = error.sum()
    return error   
pynamics.system.logger.setLevel(logging.ERROR)
k_guess = [1e2,1e3]
method = None
#method = 'CMA'
#method = 'BFGS'

if method is None:
    result = k_guess
elif method == 'CMA':
    es = cma.CMAEvolutionStrategy(k_guess, 0.5)
    es.logger.disp_header()
    while not es.stop():
          X = es.ask()
          es.tell(X, [calc_error(x) for x in X])
          es.logger.add()
          es.logger.disp([-1])
    result = es.best.x
else:
    sol = scipy.optimize.minimize(calc_error,k_guess,method = method)
    print(sol.fun)
    result = sol.x
calc_error(result)
2021-03-19 23:04:29,110 - pynamics.integration - INFO - beginning integration
2021-03-19 23:04:33,853 - pynamics.integration - INFO - finished integration
2021-03-19 23:04:33,854 - pynamics.output - INFO - calculating outputs
2021-03-19 23:04:33,922 - pynamics.output - INFO - done calculating outputs


(390, 8)



---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-14-9e227d5729d7> in <module>
----> 1 calc_error(result)


<ipython-input-10-4e201c5927ca> in calc_error(args)
      4     y_guess = y_guess.reshape((390,-1))
      5     print(y_guess.shape)
----> 6     error = fyt - y_guess
      7     error **=2
      8     error = error.sum()


ValueError: operands could not be broadcast together with shapes (390,2) (390,8) 
calc_error(k_guess)