HydraulicActuator2Arms.py

You can view and download this file on Github: HydraulicActuator2Arms.py

  1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2# This is an EXUDYN example
  3#
  4# Details:  A two arm mechanism is actuated by the HydraulicActuatorSimple;
  5#           The actuator contains internal dynamics based on GenericODE1 node
  6#
  7# Author:   Johannes Gerstmayr
  8# Date:     2022-06-16
  9#
 10# Copyright:This file is part of Exudyn. Exudyn is free software. You can redistribute it and/or modify it under the terms of the Exudyn license. See 'LICENSE.txt' for more details.
 11#
 12#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 13
 14import exudyn as exu
 15from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities
 16import exudyn.graphics as graphics #only import if it does not conflict
 17
 18#import numpy as np
 19from math import sin, cos, sqrt,pi
 20
 21SC = exu.SystemContainer()
 22mbs = SC.AddSystem()
 23
 24L = 1    #x-dim of arm
 25b = 0.1  #y-dim of arm
 26addArm2 = True
 27
 28#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 29#one arm mechanism
 30background = [graphics.CheckerBoard(point=[L,0,-2*b],size=5)]
 31background += [graphics.Cylinder(pAxis=[0,-0.25*L-0.5*b,-0.5*b], vAxis= [0,0,1.*b], radius = 0.25*b,
 32                                     color= graphics.color.grey, addEdges=True, nTiles=32)]
 33
 34oGround=mbs.AddObject(ObjectGround(referencePosition= [0,0,0], visualization=VObjectGround(graphicsData= background)))
 35massRigid = 12*10
 36inertiaRigid = massRigid/12*(L)**2
 37g = 9.81    # gravity
 38
 39#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 40#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 41#arm1
 42#graphics for arm1
 43colCyl = graphics.color.orange
 44colArm = graphics.color.dodgerblue
 45graphicsList = [graphics.Brick(size= [L,0.75*b,1.4*b], color= colArm, addEdges=True)]
 46
 47graphicsList += [graphics.Cylinder(pAxis=[-0.5*L,0,-0.75*b], vAxis= [0,0,1.5*b], radius = 0.55*b,
 48                                     color= colArm, addEdges=True, nTiles=32)]
 49
 50graphicsList += [graphics.Cylinder(pAxis=[-0.5*L,0,-0.8*b], vAxis= [0,0,1.6*b], radius = 0.25*b,
 51                                     color= graphics.color.grey, addEdges=True, nTiles=32)]
 52
 53#bolt
 54graphicsList += [graphics.Cylinder(pAxis=[-0.25*L,-0.5*b,-0.7*b], vAxis= [0,0,1.4*b], radius = 0.15*b,
 55                                     color= graphics.color.grey, addEdges=True, nTiles=32)]
 56
 57graphicsList += [graphics.Cylinder(pAxis=[-0.25*L,-0.5*b,-0.6*b], vAxis= [0,0,0.25*b], radius = 0.3*b,
 58                                     color= colArm, addEdges=True, nTiles=32)]
 59graphicsList += [graphics.Cylinder(pAxis=[-0.25*L,-0.5*b, 0.6*b], vAxis= [0,0,-0.25*b], radius = 0.3*b,
 60                                     color= colArm, addEdges=True, nTiles=32)]
 61
 62if addArm2:
 63    graphicsList += [graphics.Cylinder(pAxis=[ 0.25*L,-0.5*b,-0.7*b], vAxis= [0,0,1.4*b], radius = 0.15*b,
 64                                         color= graphics.color.grey, addEdges=True, nTiles=32)]
 65
 66    graphicsList += [graphics.Cylinder(pAxis=[ 0.25*L,-0.5*b,-0.6*b], vAxis= [0,0,0.25*b], radius = 0.3*b,
 67                                         color= colArm, addEdges=True, nTiles=32)]
 68    graphicsList += [graphics.Cylinder(pAxis=[ 0.25*L,-0.5*b, 0.6*b], vAxis= [0,0,-0.25*b], radius = 0.3*b,
 69                                         color= colArm, addEdges=True, nTiles=32)]
 70
 71#+++++++++++++++++++++++++++++++++++++++++++++++++++
 72
 73#print(graphicsList)
 74nRigid = mbs.AddNode(Rigid2D(referenceCoordinates=[0.5*L,0,0], initialVelocities=[0,0,0]));
 75oRigid = mbs.AddObject(RigidBody2D(physicsMass=massRigid, physicsInertia=inertiaRigid,nodeNumber=nRigid,
 76                                   visualization=VObjectRigidBody2D(graphicsData= graphicsList)))
 77
 78mR1 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid, localPosition=[-0.5*L,0.,0.])) #support point
 79mCOM1 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid, localPosition=[ 0.,0.,0.]))
 80mR1end = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid, localPosition=[0.5*L,0.,0.])) #end point
 81
 82#add joint
 83mG0 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oGround, localPosition=[0,0,0]))
 84mbs.AddObject(RevoluteJoint2D(markerNumbers=[mG0,mR1]))
 85
 86mbs.AddLoad(Force(markerNumber = mCOM1, loadVector = [0, -massRigid*g, 0]))
 87
 88#%%+++++++++++++++++++++++++++++++++++++++++++++++++++++
 89#add hydraulics actuator:
 90mGH = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oGround, localPosition=[0,-0.25*L-0.5*b,0.]))
 91mRH = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid,  localPosition=[-0.25*L,-0.5*b,0.]))
 92
 93
 94LH0 = sqrt(2*(0.25*L)**2) #zero length of actuator
 95
 96#hydraulics parameters:
 97V0 = 1. #oil volume (could actually change ...)
 98V1 = V0 #oil volume (could actually change ...)
 99A=[0.01,0.01] #piston area side 1/2
100Eoil = 1e12
101Av1 = 1 #valve opening (factor)
102Av2 = 0.0 #valve opening (factor)
103Qn = 2e-5 #nominal flow
104pS = 200.*1e5 #system pressure (200bar)
105pT = 1e-16+0.*1e5   #tank pressure;
106actuatorDamping = 2e5
107
108#ODE1 for pressures:
109nODE1 = mbs.AddNode(NodeGenericODE1(referenceCoordinates=[0,0],
110                                    initialCoordinates=[2e6,2e6], #initialize with 20 bar
111                                    numberOfODE1Coordinates=2))
112
113oHA = mbs.AddObject(HydraulicActuatorSimple(markerNumbers=[mGH, mRH],
114                                            nodeNumbers=[nODE1],
115                                            offsetLength=LH0, strokeLength=LH0*0.7,
116                                            chamberCrossSection0=A[0], chamberCrossSection1=A[1],
117                                            hoseVolume0=V0, hoseVolume1=V1,
118                                            valveOpening0=0, valveOpening1=0,
119                                            oilBulkModulus=Eoil, actuatorDamping=actuatorDamping, nominalFlow=Qn,
120                                            systemPressure=pS, tankPressure=pT,
121                                            useChamberVolumeChange=False,
122                                            visualization=VHydraulicActuatorSimple(cylinderRadius= 0.55*b, rodRadius= 0.3*b,
123                                                                                   baseMountLength = 0.4*b, baseMountRadius = 0.4*b,
124                                                                                   rodMountRadius = 0.3*b, pistonLength = 0.2*b, pistonRadius = 0.5*b,
125                                                                                   colorCylinder=colCyl, colorPiston=graphics.color.lightgrey),
126                                            ))
127
128
129#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
130#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
131#arm2
132#graphics for arm2
133oHA2 = -1
134if addArm2:
135    graphicsList = [graphics.Brick(size= [L,0.75*b,1.4*b], color= colArm, addEdges=True)]
136
137    graphicsList += [graphics.Cylinder(pAxis=[-0.5*L,0,-0.75*b], vAxis= [0,0,1.5*b], radius = 0.55*b,
138                                         color= colArm, addEdges=True, nTiles=32)]
139
140    graphicsList += [graphics.Cylinder(pAxis=[-0.5*L,0,-0.8*b], vAxis= [0,0,1.6*b], radius = 0.25*b,
141                                         color= graphics.color.grey, addEdges=True, nTiles=32)]
142
143    #bolt
144    graphicsList += [graphics.Cylinder(pAxis=[-0.25*L,-0.5*b,-0.7*b], vAxis= [0,0,1.4*b], radius = 0.15*b,
145                                         color= graphics.color.grey, addEdges=True, nTiles=32)]
146
147    graphicsList += [graphics.Cylinder(pAxis=[-0.25*L,-0.5*b,-0.6*b], vAxis= [0,0,0.25*b], radius = 0.3*b,
148                                         color= colArm, addEdges=True, nTiles=32)]
149    graphicsList += [graphics.Cylinder(pAxis=[-0.25*L,-0.5*b, 0.6*b], vAxis= [0,0,-0.25*b], radius = 0.3*b,
150                                         color= colArm, addEdges=True, nTiles=32)]
151    #+++++++++++++++++++++++++++++++++++++++++++++++++++
152
153    #print(graphicsList)
154    nRigid2 = mbs.AddNode(Rigid2D(referenceCoordinates=[1.*L,-0.5*L,-0.5*pi], initialVelocities=[0,0,0]));
155    oRigid2 = mbs.AddObject(RigidBody2D(physicsMass=massRigid, physicsInertia=inertiaRigid,nodeNumber=nRigid2,
156                                       visualization=VObjectRigidBody2D(graphicsData= graphicsList)))
157
158    mR1 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid2, localPosition=[-0.5*L,0.,0.])) #support point
159    mCOM2 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid2, localPosition=[ 0.,0.,0.]))
160
161    #add joint
162    mbs.AddObject(RevoluteJoint2D(markerNumbers=[mR1end,mR1]))
163
164    mbs.AddLoad(Force(markerNumber = mCOM2, loadVector = [0, -massRigid*g, 0]))
165
166    #%%+++++++++++++++++++++++++++++++++++++++++++++++++++++
167    #add hydraulics actuator:
168    mH12 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid, localPosition=[0.25*L,-0.5*b,0.]))
169    mH2 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid2,  localPosition=[-0.25*L,-0.5*b,0.]))
170
171
172    LH02 = sqrt(2*(0.25*L-0.5*b)**2) #zero length of actuator
173
174
175    #ODE1 for pressures:
176    nODE1_2 = mbs.AddNode(NodeGenericODE1(referenceCoordinates=[0,0],
177                                        initialCoordinates=[2e6,2e6], #initialize with 20 bar
178                                        numberOfODE1Coordinates=2))
179
180    oHA2 = mbs.AddObject(HydraulicActuatorSimple(markerNumbers=[mH12, mH2],
181                                                nodeNumbers=[nODE1_2],
182                                                offsetLength=LH02, strokeLength=LH02*0.7,
183                                                chamberCrossSection0=A[0], chamberCrossSection1=A[1],
184                                                hoseVolume0=V0, hoseVolume1=V1,
185                                                valveOpening0=0, valveOpening1=0,
186                                                oilBulkModulus=Eoil, actuatorDamping=actuatorDamping, nominalFlow=Qn,
187                                                systemPressure=pS, tankPressure=pT,
188                                                useChamberVolumeChange=False,
189                                                visualization=VHydraulicActuatorSimple(cylinderRadius= 0.45*b, rodRadius= 0.2*b,
190                                                                                       baseMountLength = 0.3*b, baseMountRadius = 0.3*b,
191                                                                                       rodMountRadius = 0.2*b, pistonLength = 0.1*b, pistonRadius = 0.4*b,
192                                                                                       colorCylinder=colCyl, colorPiston=graphics.color.lightgrey),
193                                                ))
194
195
196
197#add some simpistic trajectory and valve control
198def PreStepUserFunction(mbs, t):
199    LHact = mbs.GetObjectOutput(oHA, variableType=exu.OutputVariableType.Distance)
200    x = (max(0.5, min(1.5,(1-cos(t*pi*2*0.5))) ) - 0.5)*0.15+LH0
201
202    Av0 = (x-LHact)*2 #valve position control ==> penalize set value LH0
203    #print('Av0=',Av0)
204    Av1 = -Av0
205    mbs.SetObjectParameter(oHA, "valveOpening0", Av0)
206    mbs.SetObjectParameter(oHA, "valveOpening1", Av1)
207
208    if oHA2 != -1:
209        LHact2 = mbs.GetObjectOutput(oHA2, variableType=exu.OutputVariableType.Distance)
210        x = (max(0.5, min(1.5,(1-cos(2*t*pi*2*0.5))) ) - 0.5)*0.2+LH02
211        #if t>2: x=LH0
212
213        Av0 = (x-LHact2)*2 #valve position control ==> penalize set value LH0
214        #print('Av0=',Av0)
215        Av1 = -Av0
216        mbs.SetObjectParameter(oHA2, "valveOpening0", Av0)
217        mbs.SetObjectParameter(oHA2, "valveOpening1", Av1)
218
219    return True
220
221mbs.SetPreStepUserFunction(PreStepUserFunction)
222
223
224sForce = mbs.AddSensor(SensorObject(objectNumber=oHA, storeInternal=True, outputVariableType=exu.OutputVariableType.Force))
225sDistance = mbs.AddSensor(SensorObject(objectNumber=oHA, storeInternal=True, outputVariableType=exu.OutputVariableType.Distance))
226sPressures = mbs.AddSensor(SensorNode(nodeNumber=nODE1, storeInternal=True, outputVariableType=exu.OutputVariableType.Coordinates))
227
228sForce2 = mbs.AddSensor(SensorObject(objectNumber=oHA2, storeInternal=True, outputVariableType=exu.OutputVariableType.Force))
229sDistance2 = mbs.AddSensor(SensorObject(objectNumber=oHA2, storeInternal=True, outputVariableType=exu.OutputVariableType.Distance))
230sPressures2 = mbs.AddSensor(SensorNode(nodeNumber=nODE1_2, storeInternal=True, outputVariableType=exu.OutputVariableType.Coordinates))
231
232sVelocity = mbs.AddSensor(SensorObject(objectNumber=oHA, storeInternal=True, outputVariableType=exu.OutputVariableType.Velocity))
233
234mbs.Assemble()
235
236#%%+++++++++++++++++++++++++++++++++++++++++++++++++++++
237
238simulationSettings = exu.SimulationSettings() #takes currently set values or default values
239
240
241tEnd = 30
242stepSize = 0.001
243simulationSettings.solutionSettings.sensorsWritePeriod = 2*stepSize
244simulationSettings.timeIntegration.numberOfSteps = int(tEnd/stepSize)
245simulationSettings.timeIntegration.endTime = tEnd
246simulationSettings.timeIntegration.startTime = 0
247simulationSettings.timeIntegration.newton.relativeTolerance = 1e-8*100 #10000
248simulationSettings.timeIntegration.newton.absoluteTolerance = 1e-10
249simulationSettings.timeIntegration.verboseMode = 1
250#simulationSettings.timeIntegration.simulateInRealtime = True #to see what happens ...
251
252simulationSettings.timeIntegration.newton.useModifiedNewton = True
253simulationSettings.timeIntegration.newton.numericalDifferentiation.minimumCoordinateSize = 1
254simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 0.5
255simulationSettings.displayStatistics = True
256
257simulationSettings.solutionSettings.solutionInformation = 'Hydraulic actuator test'
258
259SC.visualizationSettings.openGL.multiSampling = 4
260SC.visualizationSettings.openGL.lineWidth = 2
261SC.visualizationSettings.openGL.shadow = 0.5
262SC.visualizationSettings.window.renderWindowSize = [1600,1200]
263
264exu.StartRenderer()
265mbs.WaitForUserToContinue()
266
267#use %timeit to measure time!
268mbs.SolveDynamic(simulationSettings, showHints=False)
269
270
271if True: #use this to reload the solution and use SolutionViewer
272    SC.visualizationSettings.general.autoFitScene = False
273
274    mbs.SolutionViewer() #can also be entered in IPython ...
275
276exu.StopRenderer() #safely close rendering window!
277
278
279mbs.PlotSensor(sensorNumbers=[sForce,sForce2], components=[exudyn.plot.componentNorm]*2, labels=['connector force arm1','connector force arm1'], yLabel='force (N)', closeAll=True)
280mbs.PlotSensor(sensorNumbers=[sDistance,sDistance2], components=0)
281mbs.PlotSensor(sensorNumbers=[sPressures]*2+[sPressures2]*2, components=[0,1,0,1], labels=['p0 arm1', 'p1 arm1', 'p0 arm2', 'p1 arm2'], yLabel='pressure (N/m^2)')
282
283#p01 = mbs.GetSensorStoredData(sPressures)
284#p01[:,1] = A[0]*p01[:,1] - A[1]*p01[:,2]
285#mbs.PlotSensor(sensorNumbers=p01, components=0, labels=['differential hydraulic force'], yLabel='hydraulic force (N)')