sliderCrank3Dtest.py
You can view and download this file on Github: sliderCrank3Dtest.py
1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2# This is an EXUDYN example
3#
4# Details: Slidercrank 3D (iftomm benchmark problem)
5# Ref.: https://www.iftomm-multibody.org/benchmark/problem/... spatial rigid slider-crank mechanism
6#
7# Author: Johannes Gerstmayr
8# Date: 2020-02-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 *
16from exudyn.lieGroupIntegration import *
17
18import numpy as np
19from numpy import linalg as LA
20
21useGraphics = True #without test
22#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
23#you can erase the following lines and all exudynTestGlobals related operations if this is not intended to be used as TestModel:
24try: #only if called from test suite
25 from modelUnitTests import exudynTestGlobals #for globally storing test results
26 useGraphics = exudynTestGlobals.useGraphics
27except:
28 class ExudynTestGlobals:
29 pass
30 exudynTestGlobals = ExudynTestGlobals()
31#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
32
33SC = exu.SystemContainer()
34mbs = SC.AddSystem()
35
36
37###############################################################################
38# given parameters:
39
40g = [0,0,-9.81]
41lAB = 0.08 #crank length
42lBC = 0.3 #conrod
43theta0 = 0 #initial crank angle
44omega0 = [6,0,0] #initial crank angular velocity
45
46#initial values for bodies 1 and 2 computed from initial value problem with constant angular velocity
47v1Init = [1.2e-01, -2.400e-01, 0]
48#omega1Init = [7.29730172e-01, -1.39497250e+00, 4.79376439e-01]
49omega1Init = [1.6941176470530785, -0.8470588235366621, 0.705882352947701] #appr. 10 digits accuracy
50#initial values: 0.12,-0.24,0,-0.9343942376,-2.73093948,-0.6316790456
51v2Init = [0.24,0,0]
52omega2Init = [0,0,0]
53
54zA = 0.12 #z-position of crank CoR
55yA = 0.1 #y-position of crank CoR
56
57#initial x-position of slider:
58xD = np.sqrt(lBC**2 - yA**2 - (zA + lAB)**2);
59exu.Print('slider initial position =', xD)
60
61#initial positions of points A-C
62pA = [0, yA, zA]
63pB = VAdd([0, yA, zA], [0,0,lAB])
64pC = [xD, 0, 0]
65
66vCB = np.array(pC) - np.array(pB)
67exu.Print('vCB len=', LA.norm(vCB))
68#xAxis1 = (1/lBC)*vCB #local x-axis of conrod
69[xAxis1,zAxis1, vDummy] = GramSchmidt(vCB, pA) # compute projected pA to xAxis1 ==> gives z axis
70yAxis1 = -np.cross(xAxis1, zAxis1)
71
72rotMatBC=np.array([xAxis1, yAxis1, zAxis1]).transpose()
73
74#mass and inertia
75mAB = 0.12
76mBC = 0.5
77mSlider = 2
78
79iAB = np.diag([0.0001,0.00001,0.0001]) #crank inertia
80#iBC = np.diag([0.004,0.0004,0.004]) #conrod inertia; iftomm: x=axis of conrod; McPhee: y=axis of conrod
81iSlider = np.diag([0.0001,0.0001,0.0001]) #slider inertia; McPhee: no inertia of slider / does not rotate
82
83#Maple / McPhee ?
84#<Text-field prompt="> " style="Maple Input" layout="Normal">m1:= 0.12; m2:= 0.5; m3:= 2; L1:= 0.08; L2:= 0.3; Ay:= 0.1; Az:= 0.12;</Text-field>
85#<Text-field prompt="> " style="Maple Input" layout="Normal">Ixx1:= 0.0001; Ixx2:= 0.0004; Iyy2:= 0.004; Izz2:= 0.004; G:= 9.81;</Text-field>
86
87#we choose x-axis as conrod axis!
88iBC = np.diag([0.0004,0.004,0.004]) #conrod inertia; iftomm: x=axis of conrod; McPhee: y=axis of conrod
89
90
91inertiaAB = RigidBodyInertia(mass=mAB, inertiaTensor=iAB)
92inertiaBC = RigidBodyInertia(mass=mBC, inertiaTensor=iBC)
93inertiaSlider = RigidBodyInertia(mass=mSlider, inertiaTensor=iSlider)
94
95fixedVelocity = False #constrain angular velocity of crank
96
97nodeType=exu.NodeType.RotationEulerParameters
98#nodeType=exu.NodeType.RotationRxyz
99
100
101################ Body0: CRANK
102#graphicsAB = GraphicsDataOrthoCube(-d/2,-d/2,0, d/2,d/2, lAB, [0.1,0.1,0.8,1])
103graphicsAB = GraphicsDataRigidLink(p0=[0,0,0],p1=[0,0,lAB], axis0=[1,0,0],
104 radius=[0.01,0.01], thickness = 0.01,
105 width = [0.02,0.02], color=color4steelblue)
106
107[n0,b0]=AddRigidBody(mainSys = mbs, inertia=inertiaAB, nodeType=str(nodeType),
108 position=pA, angularVelocity=omega0, gravity=g,
109 graphicsDataList=[graphicsAB])
110
111################ Body1: CONROD
112graphicsBC = GraphicsDataRigidLink(p0=[-0.5*lBC,0,0],p1=[0.5*lBC,0,0], axis1=[0,0,0],
113 radius=[0.01,0.01], thickness = 0.01,
114 width = [0.02,0.02], color=color4lightred)
115pBC = ScalarMult(0.5,VAdd(pB,pC))
116[n1,b1]=AddRigidBody(mainSys = mbs, inertia=inertiaBC, nodeType=str(nodeType),
117 position=pBC, velocity=v1Init, angularVelocity=omega1Init,
118 rotationMatrix=rotMatBC, gravity=g, graphicsDataList=[graphicsBC])
119
120################ Body2: SLIDER
121d = 0.03
122graphicsSlider = GraphicsDataOrthoCube(-d/2,-d/2,-d/2, d/2,d/2, d/2, [0.5,0.5,0.5,0.5])
123[n2,b2]=AddRigidBody(mainSys = mbs, inertia=inertiaSlider, nodeType=str(nodeType),
124 position=pC, velocity=v2Init, angularVelocity=[0,0,0],
125 graphicsDataList=[graphicsSlider])
126
127
128oGround = mbs.AddObject(ObjectGround())
129markerGroundA = mbs.AddMarker(MarkerBodyRigid(name='markerGroundA', bodyNumber=oGround, localPosition=pA))
130markerGroundD = mbs.AddMarker(MarkerBodyRigid(name='markerGroundD', bodyNumber=oGround, localPosition=[0,0,0]))
131
132markerCrankA = mbs.AddMarker(MarkerBodyRigid(bodyNumber=b0))
133markerCrankB = mbs.AddMarker(MarkerBodyRigid(bodyNumber=b0, localPosition=[0,0,lAB]))
134
135markerConrodB = mbs.AddMarker(MarkerBodyRigid(bodyNumber=b1, localPosition=[-0.5*lBC,0,0]))
136markerConrodC = mbs.AddMarker(MarkerBodyRigid(bodyNumber=b1, localPosition=[ 0.5*lBC,0,0]))
137
138markerSlider = mbs.AddMarker(MarkerBodyRigid(bodyNumber=b2))
139
140mbs.AddObject(GenericJoint(markerNumbers=[markerGroundA, markerCrankA], constrainedAxes=[1,1,1,0,1,1],
141 visualization=VObjectJointGeneric(axesRadius=0.005, axesLength=0.02)))
142
143mbs.AddObject(GenericJoint(markerNumbers=[markerGroundD, markerSlider], constrainedAxes=[0,1,1,1,1,1],
144 visualization=VObjectJointGeneric(axesRadius=0.005, axesLength=0.02)))
145
146mbs.AddObject(GenericJoint(markerNumbers=[markerCrankB, markerConrodB], constrainedAxes=[1,1,1,0,0,0],
147 visualization=VObjectJointGeneric(axesRadius=0.005, axesLength=0.02)))
148
149#classical cardan, x=locked
150#mbs.AddObject(GenericJoint(markerNumbers=[markerConrodC, markerSlider], constrainedAxes=[1,1,1,1,0,0],
151# visualization=VObjectJointGeneric(axesRadius=0.005, axesLength=0.02)))
152
153mbs.AddObject(GenericJoint(markerNumbers=[markerSlider, markerConrodC], constrainedAxes=[1,1,1,0,0,1], # xAxisMarker0=free, yAxisMarker1=free
154 visualization=VObjectJointGeneric(axesRadius=0.005, axesLength=0.02)))
155
156if useGraphics:
157 sCrankAngle=mbs.AddSensor(SensorNode(nodeNumber = n0, storeInternal=True,#fileName='solution/crankAngle.txt',
158 outputVariableType=exu.OutputVariableType.Rotation))
159 sCrankAngVel=mbs.AddSensor(SensorNode(nodeNumber = n0, storeInternal=True,#fileName='solution/crankAngularVelocity.txt',
160 outputVariableType=exu.OutputVariableType.AngularVelocity))
161 sSliderPos=mbs.AddSensor(SensorNode(nodeNumber = n2, storeInternal=True,#fileName='solution/sliderPosition.txt',
162 outputVariableType=exu.OutputVariableType.Position))
163 sSliderVel=mbs.AddSensor(SensorNode(nodeNumber = n2, storeInternal=True,#fileName='solution/sliderVelocity.txt',
164 outputVariableType=exu.OutputVariableType.Velocity))
165
166if fixedVelocity:
167 groundNode = mbs.AddNode(NodePointGround(referenceCoordinates=[0,0,0])) #add a coordinate fixed to ground
168 markerGroundCoordinate = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber=groundNode, coordinate=0))
169 markerRotX = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber=n0, coordinate=3)) #Euler angle x
170
171 mbs.AddObject(CoordinateConstraint(markerNumbers=[markerGroundCoordinate, markerRotX],
172 offset = 6, velocityLevel=True))
173
174#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
175mbs.Assemble()
176#mbs.systemData.Info()
177
178simulationSettings = exu.SimulationSettings() #takes currently set values or default values
179
180fact = 1000 #1000 for testing
181outputFact = 1000
182simulationSettings.timeIntegration.numberOfSteps = 1*fact
183simulationSettings.timeIntegration.endTime = 0.2 #0.2 for testing
184simulationSettings.solutionSettings.solutionWritePeriod = simulationSettings.timeIntegration.endTime/outputFact
185simulationSettings.solutionSettings.sensorsWritePeriod = simulationSettings.timeIntegration.endTime/outputFact
186simulationSettings.solutionSettings.writeSolutionToFile = useGraphics
187simulationSettings.timeIntegration.verboseMode = 1
188
189simulationSettings.timeIntegration.generalizedAlpha.useIndex2Constraints = True
190simulationSettings.timeIntegration.generalizedAlpha.useNewmark = True
191simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 0.5 #0.6 works well
192
193simulationSettings.timeIntegration.generalizedAlpha.computeInitialAccelerations=True
194
195SC.visualizationSettings.connectors.showJointAxes = True
196SC.visualizationSettings.connectors.jointAxesLength = 0.02
197SC.visualizationSettings.connectors.jointAxesRadius = 0.002
198
199if useGraphics:
200# simulationSettings.timeIntegration.numberOfSteps = 4*5000
201# simulationSettings.timeIntegration.endTime = 5 #0.2 for testing
202
203 exu.StartRenderer()
204 mbs.WaitForUserToContinue()
205
206mbs.SolveDynamic(simulationSettings)
207
208
209#compute initial velocities:
210#if fixedVelocity:
211# v0 = mbs.GetNodeOutput(n0,exu.OutputVariableType.Coordinates_t)
212# exu.Print('v0=',v0)
213#
214# v1 = mbs.GetNodeOutput(n1,exu.OutputVariableType.Coordinates_t)
215# exu.Print('v1=',v1[0:3])
216# omega1 = mbs.GetNodeOutput(n1,exu.OutputVariableType.AngularVelocity)
217# exu.Print('omega1=',omega1[0],omega1[1],omega1[2])
218#
219# v2 = mbs.GetNodeOutput(n2,exu.OutputVariableType.Coordinates_t)
220# exu.Print('v2=',v2[0:3])
221
222
223#+++++++++++++++++++++++++++++++++++++++++++++
224#compute TestModel error for EulerParameters and index2 solver
225sol = mbs.systemData.GetODE2Coordinates();
226solref = mbs.systemData.GetODE2Coordinates(configuration=exu.ConfigurationType.Reference);
227#exu.Print('sol=',sol)
228u = 0
229for i in range(14): #take coordinates of first two bodies
230 u += abs(sol[i]+solref[i])
231
232exu.Print('solution of 3D slidercrank iftomm benchmark=',u)
233
234exudynTestGlobals.testError = u - (3.36427617809219) #2020-04-22(corrected GenericJoint): 3.36427617809219;2020-02-19: 3.3642838177004832
235exudynTestGlobals.testResult = u
236
237
238if useGraphics:
239 #SC.WaitForRenderEngineStopFlag()
240 exu.StopRenderer() #safely close rendering window!
241
242if useGraphics:
243 import matplotlib.pyplot as plt
244 import matplotlib.ticker as ticker
245 plt.close("all")
246
247 [fig1, ax1] = plt.subplots()
248 [fig2, ax2] = plt.subplots()
249 # data1 = np.loadtxt('solution/crankAngularVelocity.txt', comments='#', delimiter=',')
250 data1 = mbs.GetSensorStoredData(sCrankAngVel)
251 ax1.plot(data1[:,0], data1[:,1], 'r-', label='crank angular velocity')
252 # data1 = np.loadtxt('solution/crankAngle.txt', comments='#', delimiter=',')
253 data1 = mbs.GetSensorStoredData(sCrankAngle)
254 ax1.plot(data1[:,0], data1[:,1], 'b-', label='crank angle')
255 if False: #only if available ...
256 data1 = np.loadtxt('../../../docs/verification/Slidercrank3DiftommBenchmark/Spatial_rigid_slider-crank_mechanism_Masarati.txt', comments='#', delimiter=',')
257 ax1.plot(data1[:,0], data1[:,2], 'r:', label='Ref Masarati: crank angle')
258 data1 = np.loadtxt('../../../docs/verification/Slidercrank3DiftommBenchmark/Spatial_rigid_slider-crank_mechanism_Masoudi.txt', comments='#', delimiter='\t')
259 ax1.plot(data1[:,0], data1[:,2], 'k:', label='Ref Masoudi: crank angle')
260 data1 = np.loadtxt('../../../docs/verification/Slidercrank3DiftommBenchmark/Spatial_rigid_slider-crank_mechanism_Chaojie.txt', comments='#', delimiter=',')
261 ax1.plot(data1[:,0], data1[:,2], 'g:', label='Ref Chaojie: crank angle')
262
263
264 # data2 = np.loadtxt('solution/sliderPosition.txt', comments='#', delimiter=',')
265 data2 = mbs.GetSensorStoredData(sSliderPos)
266 ax2.plot(data2[:,0], data2[:,1], 'b-', label='slider position')
267 #data2 = np.loadtxt('solution/sliderPosition_1e-4.txt', comments='#', delimiter=',')
268 #ax2.plot(data2[:,0], data2[:,1], 'r-', label='slider position, dt=1e-4')
269# data2 = np.loadtxt('solution/sliderVelocity.txt', comments='#', delimiter=',')
270# ax2.plot(data2[:,0], data2[:,1], 'r-', label='slider velocity')
271
272 if False: #only if available ...
273 data2 = np.loadtxt('../../../docs/verification/Slidercrank3DiftommBenchmark/Spatial_rigid_slider-crank_mechanism_Masarati.txt', comments='#', delimiter=',')
274 ax2.plot(data2[:,0], data2[:,1], 'r:', label='Ref Masarati: slider position')
275 data2 = np.loadtxt('../../../docs/verification/Slidercrank3DiftommBenchmark/Spatial_rigid_slider-crank_mechanism_Masoudi.txt', comments='#', delimiter='\t')
276 ax2.plot(data2[:,0], data2[:,1], 'k:', label='Ref Masoudi: slider position')
277 data2 = np.loadtxt('../../../docs/verification/Slidercrank3DiftommBenchmark/Spatial_rigid_slider-crank_mechanism_Chaojie.txt', comments='#', delimiter=',')
278 ax2.plot(data2[:,0], data2[:,1], 'g:', label='Ref Chaojie: slider position')
279
280
281 axList=[ax1,ax2]
282 figList=[fig1, fig2]
283
284 for ax in axList:
285 ax.grid(True, 'major', 'both')
286 ax.xaxis.set_major_locator(ticker.MaxNLocator(10))
287 ax.yaxis.set_major_locator(ticker.MaxNLocator(10))
288 ax.set_xlabel("time (s)")
289 ax.legend()
290
291 ax1.set_ylabel("crank angle / angular velocity")
292 ax2.set_ylabel("slider position (m)")
293
294 for f in figList:
295 f.tight_layout()
296 f.show() #bring to front