stiffFlyballGovernor2.py
You can view and download this file on Github: stiffFlyballGovernor2.py
1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2# This is an EXUDYN example
3#
4# Details: Stiff flyball governor with rigid and compliant joints (IFToMM benchmark problem);
5# Ref.: https://www.iftomm-multibody.org/benchmark/problem/Stiff_flyball_governor/
6# This version uses the newer C++ implemented Lie group solvers
7#
8# Model: Flyball governor as redundant multibody system
9#
10# Author: Johannes Gerstmayr, Stefan Holzinger
11# Date: 2020-02-13
12#
13# 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.
14#
15# *clean example*
16#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17
18## import libaries
19import exudyn as exu
20from exudyn.itemInterface import *
21from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities
22import exudyn.graphics as graphics #only import if it does not conflict
23from exudyn.graphicsDataUtilities import *
24
25import numpy as np
26from numpy import linalg as LA
27
28## set up MainSystem mbs
29SC = exu.SystemContainer()
30mbs = SC.AddSystem()
31
32##
33useCompliantCase = False
34useLieGroup = useCompliantCase
35
36
37## create background graphics and ground object
38color = [0.1,0.1,0.8,1]
39r = 0.2 #radius
40L = 1 #length
41
42background0 = GraphicsDataRectangle(-L,-L,L,L,color)
43oGround=mbs.AddObject(ObjectGround(referencePosition= [0,0,0], visualization=VObjectGround(graphicsData= [background0])))
44
45# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
46## set up body dimensions according to reference in m
47
48# shaft
49lengthShaft = 1 #z
50widthShaft = 0.01 #=height
51
52# rod
53lengthRod = 1
54widthRod = 0.01 #=height
55
56# slider
57dimSlider = 0.1 #x=y=z
58sSlider = 0.5
59
60# scalar distance between point A and B
61xAB = 0.1
62beta0 = np.deg2rad(30)
63initAngleRod = np.deg2rad(60)
64
65# initial angular velocity of shaft and slider
66omega0 = [0., 0., 0.16*2*np.pi]
67
68# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
69## body masses according to reference in kg
70
71density = 3000
72
73mShaft = 0.3
74mRod = 0.3
75mSlider = 3
76mMassPoint = 5
77mRodMassPoint = mRod + mMassPoint
78
79
80# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
81# gravity
82g = [0,0,-9.81]
83
84## setup inertia for rod along x-direction
85iRod = InertiaCuboid(density=density, sideLengths=[lengthRod,widthRod,0.01])
86iMass = InertiaMassPoint(mass=mMassPoint).Translated([lengthRod/2,0,0])
87iRodSum = iRod+iMass
88
89#compute reference point of rod (midpoint)
90refRod = -iRodSum.com
91iRodSum = iRodSum.Translated(refRod)
92
93if useLieGroup:
94 nodeType = exu.NodeType.RotationRotationVector
95else:
96 nodeType = exu.NodeType.RotationEulerParameters
97
98
99nRigidBodyNodes = 4
100#nRB=[-1]*nRigidBodyNodes #final node numbers
101
102## create inertia for shaft and slider
103inertiaList=[InertiaCuboid(density=density, sideLengths=[widthShaft,widthShaft,lengthShaft]),
104 InertiaCuboid(density=density, sideLengths=[dimSlider,dimSlider,dimSlider]),
105 iRodSum, iRodSum]
106
107## set up reference position list
108refPosList=[[0,0,lengthShaft/2], # shaft
109 [0,0,sSlider], # slider
110 [ xAB/2 + (lengthRod/2-refRod[0])*np.cos(beta0), 0, lengthShaft - (lengthRod/2-refRod[0])*np.sin(beta0)], # rodAC
111 [-xAB/2 - (lengthRod/2-refRod[0])*np.cos(beta0), 0, lengthShaft - (lengthRod/2-refRod[0])*np.sin(beta0)]] # rodBD
112
113## set up initial velocity vector list
114refVelList = [[0., 0., 0.], # shaft
115 [0., 0., 0.], # slider
116 [0,omega0[2]*refPosList[2][0],0], # rodAC
117 [0,omega0[2]*refPosList[3][0],0]] # rodBD
118
119## set up initial (global) angular velocity vector list
120refAngularVelList = [omega0, # shaft
121 omega0, # slider
122 omega0, # rodAC
123 omega0] # rodBD
124
125## create graphics objects for bodies
126graphicsRodAC = graphics.BrickXYZ(-(lengthRod/2-refRod[0]),-widthRod/2,-widthRod/2, lengthRod/2+refRod[0],widthRod/2,widthRod/2, [0.1,0.1,0.8,1])
127graphicsRodBD = graphics.BrickXYZ(-lengthRod/2-refRod[0],-widthRod/2,-widthRod/2, lengthRod/2-refRod[0],widthRod/2,widthRod/2, [0.1,0.1,0.8,1])
128graphicsSlider = graphics.BrickXYZ(-dimSlider/2,-dimSlider/2,-dimSlider/2, dimSlider/2,dimSlider/2,dimSlider/2, [0.1,0.1,0.8,1])
129graphicsShaft = graphics.BrickXYZ(-widthShaft/2,-widthShaft/2,-lengthShaft/2, widthShaft/2,widthShaft/2,lengthShaft/2, [0.1,0.1,0.8,1])
130
131#lists for 4 nodes/bodies: [shaft, slider, rodAC, rodBD]
132graphicsList=[graphicsShaft, graphicsSlider, graphicsRodAC, graphicsRodBD]
133
134#eulerParameters0 = [1, 0, 0, 0]
135rotParList = []
136if nodeType == exu.NodeType.RotationEulerParameters:
137 refRotParList = [eulerParameters0, # shaft
138 eulerParameters0, # slider
139 RotationMatrix2EulerParameters(RotationMatrixY(beta0)), # rodAC
140 RotationMatrix2EulerParameters(RotationMatrixY(-beta0))] # rodBD
141 refRotMatList = [EulerParameters2RotationMatrix(refRotParList[0]),
142 EulerParameters2RotationMatrix(refRotParList[1]),
143 EulerParameters2RotationMatrix(refRotParList[2]),
144 EulerParameters2RotationMatrix(refRotParList[3])]
145
146elif nodeType == exu.NodeType.RotationRxyz:
147 refRotParList = [[0,0,0], # shaft
148 [0,0,0], # slider
149 [0,beta0,0], # rodAC
150 [0,-beta0,0]] # rodBD
151 refRotMatList = [RotXYZ2RotationMatrix(refRotParList[0]),
152 RotXYZ2RotationMatrix(refRotParList[1]),
153 RotXYZ2RotationMatrix(refRotParList[2]),
154 RotXYZ2RotationMatrix(refRotParList[3])]
155
156elif nodeType == exu.NodeType.RotationRotationVector:
157 refRotParList = [[0,0,0], # shaft
158 [0,0,0], # slider
159 [0,beta0,0], # rodAC
160 [0,-beta0,0]] # rodBD
161 refRotMatList = [RotationVector2RotationMatrix(refRotParList[0]),
162 RotationVector2RotationMatrix(refRotParList[1]),
163 RotationVector2RotationMatrix(refRotParList[2]),
164 RotationVector2RotationMatrix(refRotParList[3])]
165
166# add rigid bodies to mbs
167nodeNumberList = [-1]*nRigidBodyNodes
168bodyNumberList = [-1]*nRigidBodyNodes
169for i in range(nRigidBodyNodes):
170 [n0,b0]=AddRigidBody(mainSys = mbs,
171 inertia = inertiaList[i],
172 nodeType = str(nodeType),
173 position = refPosList[i],
174 velocity = refVelList[i],
175 rotationMatrix = [],#refRotMatList[i],
176 rotationParameters = refRotParList[i],
177 angularVelocity = refAngularVelList[i],
178 gravity = g,
179 graphicsDataList = [graphicsList[i]])
180 nodeNumberList[i] = n0
181 bodyNumberList[i] = b0
182
183
184
185
186# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
187## spring-damper parameters for connecting the rods with the slider
188
189# spring
190k = 8.e5*0.005 # spring stiffness in N/m
191l0 = 0.5 # relaxed spring length in m
192
193# damper
194c = 4.e4*0.005
195
196## connecting points
197# slider
198pointEslider = [dimSlider/2, 0., 0.]
199pointFslider = [-dimSlider/2, 0., 0.]
200
201# connectin points for connecting rods with slider
202connectingPointRodACWithSlider = [refRod[0], 0, 0]
203connectingPointRodBDWithSlider = [-refRod[0], 0, 0]
204
205# connecting points for connecting rods with shaft
206pointA = [xAB/2, 0, lengthShaft/2]
207pointB = [-xAB/2, 0, lengthShaft/2]
208pointARodAC = [-(lengthRod/2-refRod[0]), 0, 0]
209pointARodBD = [(lengthRod/2-refRod[0]), 0, 0]
210
211# connecting point of shaft with ground
212connectingPointShaftWithGround = [0, 0, -lengthShaft/2]
213
214# markers
215markerShaftCOM = mbs.AddMarker(MarkerBodyRigid(name='markerShaftCOM', bodyNumber=bodyNumberList[0], localPosition=[0,0,0]))
216markerShaftGround = mbs.AddMarker(MarkerBodyRigid(name='markerShaftGround', bodyNumber=bodyNumberList[0], localPosition=connectingPointShaftWithGround))
217markerShaftPointA = mbs.AddMarker(MarkerBodyRigid(name='markerShaftPointA', bodyNumber=bodyNumberList[0], localPosition=pointA))
218markerShaftPointB = mbs.AddMarker(MarkerBodyRigid(name='markerShaftPointB', bodyNumber=bodyNumberList[0], localPosition=pointB))
219
220markerSliderCOM = mbs.AddMarker(MarkerBodyRigid(name='markerSliderCOM', bodyNumber=bodyNumberList[1], localPosition=[0,0,0]))
221markerSliderPointE = mbs.AddMarker(MarkerBodyRigid(name='markerSliderPointE', bodyNumber=bodyNumberList[1], localPosition=pointEslider))
222markerSliderPointF = mbs.AddMarker(MarkerBodyRigid(name='markerSliderPointF', bodyNumber=bodyNumberList[1], localPosition=pointFslider))
223
224markerRodACShaft = mbs.AddMarker(MarkerBodyRigid(name='markerRodACShaft', bodyNumber=bodyNumberList[2], localPosition=pointARodAC))
225markerRodACSlider = mbs.AddMarker(MarkerBodyRigid(name='markerRodACSlider', bodyNumber=bodyNumberList[2], localPosition=connectingPointRodACWithSlider))
226
227markerRodBDShaft = mbs.AddMarker(MarkerBodyRigid(name='markerRodBDShaft', bodyNumber=bodyNumberList[3], localPosition=pointARodBD))
228markerRodBDSlider = mbs.AddMarker(MarkerBodyRigid(name='markerRodBDSlider', bodyNumber=bodyNumberList[3], localPosition=connectingPointRodBDWithSlider))
229
230
231
232oGround = mbs.AddObject(ObjectGround())
233markerGround = mbs.AddMarker(MarkerBodyRigid(name='markerGround', bodyNumber=oGround, localPosition=[0,0,0]))
234
235nj2=-1
236
237if not useCompliantCase:
238
239 mbs.AddObject(GenericJoint(markerNumbers=[markerGround, markerShaftGround], constrainedAxes=[1,1,1,1,1,0],
240 visualization=VObjectJointGeneric(axesRadius=0.01, axesLength=0.1)))
241
242 mbs.AddObject(GenericJoint(markerNumbers=[markerShaftCOM, markerSliderCOM], constrainedAxes=[1*0,1*0,0,1,1,1],
243 visualization=VObjectJointGeneric(axesRadius=0.01, axesLength=0.1)))
244
245 mbs.AddObject(GenericJoint(markerNumbers=[markerShaftPointA, markerRodACShaft], constrainedAxes=[1,1,1,1,0,1],
246 visualization=VObjectJointGeneric(axesRadius=0.01, axesLength=0.1)))
247
248 mbs.AddObject(GenericJoint(markerNumbers=[markerShaftPointB, markerRodBDShaft], constrainedAxes=[1,1,1,1,0,1],
249 visualization=VObjectJointGeneric(axesRadius=0.01, axesLength=0.1)))
250
251else:
252 kj=1e5*0.2
253 dj = kj*0.05
254
255 kj2 = kj*0.05 #rotatory springs can be softer!
256 dj2 = kj2*0.05
257
258 mbs.AddObject(RigidBodySpringDamper(markerNumbers=[markerGround, markerShaftGround],
259 stiffness=np.diag([kj,kj,kj,kj2,kj2,0]), damping=np.diag([dj,dj,dj,dj2,dj2,0])))
260
261 mbs.AddObject(RigidBodySpringDamper(markerNumbers=[markerShaftCOM, markerSliderCOM],
262 stiffness=np.diag([kj,kj,0,kj2,kj2,kj2]), damping=0*np.diag([dj,dj,0,0,0,0])))
263
264 nj2 = mbs.AddObject(RigidBodySpringDamper(markerNumbers=[markerShaftPointA, markerRodACShaft],
265 stiffness=np.diag([kj,kj,kj,kj2,0,kj2]), damping=0.*np.diag([dj,dj,dj,0,0,0])))
266
267 mbs.AddObject(RigidBodySpringDamper(markerNumbers=[markerShaftPointB, markerRodBDShaft],
268 stiffness=np.diag([kj,kj,kj,kj2,0,kj2]), damping=0.*np.diag([dj,dj,dj,0,0,0])))
269
270
271
272
273# spring-damper elements
274mbs.AddObject(SpringDamper(markerNumbers=[markerSliderPointE, markerRodACSlider], stiffness=k, damping=c, referenceLength=l0))
275mbs.AddObject(SpringDamper(markerNumbers=[markerSliderPointF, markerRodBDSlider], stiffness=k, damping=c, referenceLength=l0))
276
277mbs.AddSensor(SensorNode(nodeNumber = nodeNumberList[1], fileName='solution/flyballSliderPosition.txt',outputVariableType=exu.OutputVariableType.Position))
278mbs.AddSensor(SensorNode(nodeNumber = nodeNumberList[2], fileName='solution/flyballSliderRotation.txt',outputVariableType=exu.OutputVariableType.Rotation)) #Tait Bryan rotations
279mbs.AddSensor(SensorNode(nodeNumber = nodeNumberList[0], fileName='solution/flyballShaftAngularVelocity.txt',outputVariableType=exu.OutputVariableType.AngularVelocity))
280
281
282# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
283mbs.Assemble()
284
285
286useGraphics=True
287if useGraphics: #only start graphics once, but after background is set
288 exu.StartRenderer()
289 #mbs.WaitForUserToContinue()
290
291# dynamicSolver = exu.MainSolverImplicitSecondOrder()
292
293tEnd = 10
294h = 2e-5 #RK44
295#h = 1e-3
296
297simulationSettings = exu.SimulationSettings() #takes currently set values or default values
298simulationSettings.timeIntegration.explicitIntegration.useLieGroupIntegration = useLieGroup
299
300simulationSettings.timeIntegration.numberOfSteps = int(tEnd/h)
301simulationSettings.timeIntegration.endTime = tEnd
302
303
304SC.visualizationSettings.markers.show = True
305#SC.visualizationSettings.markers.showNumbers = True
306
307#simulationSettings.displayComputationTime = True
308simulationSettings.timeIntegration.verboseMode = 1
309
310simulationSettings.solutionSettings.sensorsWritePeriod = simulationSettings.timeIntegration.endTime/2000
311simulationSettings.solutionSettings.solutionWritePeriod = simulationSettings.timeIntegration.endTime/2000
312
313if nodeType != exu.NodeType.RotationRotationVector:
314 simulationSettings.timeIntegration.generalizedAlpha.computeInitialAccelerations = True
315else:
316 simulationSettings.timeIntegration.generalizedAlpha.computeInitialAccelerations = False
317
318
319solverType = exu.DynamicSolverType.TrapezoidalIndex2
320if useLieGroup:
321 solverType = exu.DynamicSolverType.RK44
322 simulationSettings.timeIntegration.stepSizeSafety = 0.5 #almost no step rejection
323
324mbs.SolveDynamic(simulationSettings, solverType=solverType)
325print(mbs.sys['dynamicSolver'].it)
326
327
328if useGraphics: #only start graphics once, but after background is set
329 exu.StopRenderer() #safely close rendering window!
330
331
332for i in range(4):
333 om=mbs.GetNodeOutput(i,exu.OutputVariableType.AngularVelocity)
334 # exu.Print("om",i,"=",om)
335
336for i in range(4):
337 vel=mbs.GetNodeOutput(i,exu.OutputVariableType.Velocity)
338 # exu.Print("v",i,"=",vel)
339
340for i in range(2):
341 rot=mbs.GetNodeOutput(i+2,exu.OutputVariableType.RotationMatrix)
342 # exu.Print("Rot",i+2,"=",rot)
343
344result = mbs.GetNodeOutput(2,exu.OutputVariableType.Velocity)[1] #y-velocity of bar
345exu.Print('solution of stiffFlyballGovernor=',result)
346
347
348plist=[]
349plist += [mbs.GetObjectOutputBody(objectNumber = bodyNumberList[2], variableType = exu.OutputVariableType.Velocity, localPosition = list(pointARodAC), configuration =
350exu.ConfigurationType.Current)]
351plist += [mbs.GetObjectOutputBody(objectNumber = bodyNumberList[2], variableType = exu.OutputVariableType.Velocity, localPosition = connectingPointRodACWithSlider, configuration =
352exu.ConfigurationType.Current)]
353plist += [mbs.GetObjectOutputBody(objectNumber = bodyNumberList[3], variableType = exu.OutputVariableType.Velocity, localPosition = pointARodBD, configuration =
354exu.ConfigurationType.Current)]
355
356#locU = mbs.GetObjectOutput(objectNumber = nj2, variableType =exu.OutputVariableType.DisplacementLocal)
357#exu.Print('locU=', locU)
358#locR = mbs.GetObjectOutput(objectNumber = nj2, variableType =exu.OutputVariableType.Rotation)
359#exu.Print('locR=', locR)
360
361
362#Rxyz initial velocities:
363#om 0 = [0. 0. 6.28318531]
364#om 1 = [0. 0. 6.28318531]
365#om 2 = [ 0.00000000e+00 -8.54693196e-10 6.28318531e+00]
366#om 3 = [0.00000000e+00 8.54693196e-10 6.28318531e+00]
367#v 0 = [ 0.00000000e+00 0.00000000e+00 -4.90499796e-10]
368#v 1 = [ 0.00000000e+00 0.00000000e+00 -4.90499608e-10]
369#v 2 = [-1.91975841e-16 5.60155553e+00 -4.90500111e-10]
370#v 3 = [ 1.91975841e-16 -5.60155553e+00 -4.90500111e-10]
371
372if useGraphics:
373 import matplotlib.pyplot as plt
374 import matplotlib.ticker as ticker
375 plt.close('all')
376
377 data = np.loadtxt('solution/flyballSliderPosition.txt', comments='#', delimiter=',')
378 #plt.plot(data[:,0], data[:,3], 'r-') #z coordinate of slider
379 #data = np.loadtxt('solution/flyballShaftAngularVelocity.txt', comments='#', delimiter=',')
380 plt.plot(data[:,0], data[:,1], 'b-') #z coordinate of slider
381 plt.plot(data[:,0], data[:,2], 'g-') #z coordinate of slider
382 plt.plot(data[:,0], data[:,3], 'k-') #z coordinate of slider
383
384 data = np.loadtxt('solution/flyballSliderRotation.txt', comments='#', delimiter=',')
385 plt.plot(data[:,0], data[:,1], 'r--') #z coordinate of slider
386 plt.plot(data[:,0], data[:,2], 'g--') #z coordinate of slider
387 plt.plot(data[:,0], data[:,3], 'b--') #z coordinate of slider
388
389 if False:
390 #data = np.loadtxt('solution/flyballSliderPositionRxyz.txt', comments='#', delimiter=',') #rigid joints?
391 data = np.loadtxt('solution/flyballSliderPositionRK4Rxyz.txt', comments='#', delimiter=',') #compliant joints
392 #plt.plot(data[:,0], data[:,3], 'r:') #z coordinate of slider
393 plt.plot(data[:,0], data[:,1], 'b:') #z coordinate of slider
394 plt.plot(data[:,0], data[:,2], 'g:') #z coordinate of slider
395 plt.plot(data[:,0], data[:,3], 'k:') #z coordinate of slider
396
397# data = np.loadtxt('solution/flyballSliderPositionRK4Rxyz.txt', comments='#', delimiter=',')
398# plt.plot(data[:,0], data[:,3], 'g:') #z coordinate of slider
399# data = np.loadtxt('solution/flyballShaftAngularVelocityRK4Rxyz.txt', comments='#', delimiter=',')
400# plt.plot(data[:,0], data[:,3], 'k:') #z coordinate of slider
401
402 ax=plt.gca() # get current axes
403 ax.grid(True, 'major', 'both')
404 ax.xaxis.set_major_locator(ticker.MaxNLocator(10))
405 ax.yaxis.set_major_locator(ticker.MaxNLocator(10))
406 plt.tight_layout()
407 plt.show()