openVRengine.py
You can view and download this file on Github: openVRengine.py
1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2# This is an EXUDYN example
3#
4# Details: test creating piston engine with variable number of pistons and piston angles;
5# possibility to interact with openVR
6#
7# Author: Johannes Gerstmayr
8# Date: 2023-01-17
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
14
15import exudyn as exu
16from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities
17import exudyn.graphics as graphics #only import if it does not conflict
18from math import sin, cos, asin, acos, pi, exp, log, tan, atan, radians
19from exudyn.interactive import InteractiveDialog
20
21
22omegaDrive = 4*pi*0.5
23tEnd = 3600
24nodeType = exu.NodeType.RotationEulerParameters
25fixedSpeed = False #if false, the speed is given only for first 1 second
26
27# nodeType = exu.NodeType.RotationRxyz
28#nodeType = exu.NodeType.RotationRotationVector
29
30# import matplotlib.pyplot as plt
31# plt.close('all')
32zOffAdd = -0.5
33
34class EngineParameters:
35 def __init__(self, crankAnglesDegrees=[], pistonAnglesDegrees=[]):
36 #parameters in m, s, kg, rad, ...
37 self.crankAnglesDegrees = crankAnglesDegrees
38 if pistonAnglesDegrees == []:
39 self.pistonAnglesDegrees = list(0*np.array(crankAnglesDegrees))
40 else:
41 self.pistonAnglesDegrees = pistonAnglesDegrees
42
43 crankAngles = pi/180*np.array(crankAnglesDegrees)
44 self.crankAngles = list(crankAngles)
45
46 pistonAngles = pi/180*np.array(self.pistonAnglesDegrees)
47 self.pistonAngles = list(pistonAngles)
48
49 densitySteel = 7850
50 #kinematics & inertia & drawing
51 fZ = 1#0.2
52 self.pistonDistance = 0.08
53 self.pistonMass = 0.5
54 self.pistonLength = 0.05
55 self.pistonRadius = 0.02
56
57 self.conrodLength = 0.1 #X
58 self.conrodHeight = 0.02*fZ#Y
59 self.conrodWidth = 0.02*fZ #Z
60 self.conrodRadius = 0.012*fZ #Z
61
62 self.crankArmLength = 0.04 #X
63 self.crankArmHeight = 0.016 #Y
64 self.crankArmWidth = 0.01*fZ #Z width of arm
65 self.crankBearingWidth = 0.012*fZ #Z
66 self.crankBearingRadius = 0.01
67
68 self.conrodCrankCylLength = 0.024*fZ #Z; length of cylinder (bearing conrod-crank)
69 self.conrodCrankCylRadius = 0.008 #radius of cylinder (bearing conrod-crank)
70
71 self.pistonDistance = self.crankBearingWidth + 2*self.crankArmWidth + self.conrodCrankCylLength #Z distance
72
73 self.inertiaConrod = InertiaCuboid(densitySteel, sideLengths=[self.conrodLength, self.conrodHeight, self.conrodWidth])
74
75 eL = self.Length()
76 #last bearing:
77 densitySteel2 = densitySteel
78 self.inertiaCrank = InertiaCylinder(densitySteel2, self.crankBearingWidth, self.crankBearingRadius, axis=2).Translated([0,0,0.5*eL-0.5*self.crankBearingWidth])
79
80
81
82 for cnt, angle in enumerate(self.crankAngles):
83 A = RotationMatrixZ(angle)
84 zOff = -0.5*eL + cnt*self.pistonDistance
85 arm = InertiaCuboid(densitySteel2, sideLengths=[self.crankArmLength, self.crankArmHeight, self.crankArmWidth])
86 cylCrank = InertiaCylinder(densitySteel2, self.crankBearingWidth, self.crankBearingRadius, axis=2)
87 cylConrod = InertiaCylinder(densitySteel2, self.conrodCrankCylLength, self.conrodCrankCylRadius, axis=2)
88 #add inertias:
89 self.inertiaCrank += cylCrank.Translated([0,0,zOff+self.crankBearingWidth*0.5])
90 self.inertiaCrank += arm.Rotated(A).Translated(A@[self.crankArmLength*0.5,0,zOff+self.crankBearingWidth+self.crankArmWidth*0.5])
91 self.inertiaCrank += cylConrod.Translated(A@[self.crankArmLength,0,zOff+self.crankBearingWidth+self.crankArmWidth+self.conrodCrankCylLength*0.5])
92 self.inertiaCrank += arm.Rotated(A).Translated(A@[self.crankArmLength*0.5,0,zOff+self.crankBearingWidth+self.crankArmWidth*1.5+self.conrodCrankCylLength])
93
94 # self.inertiaCrank = InertiaCylinder(1e-8*densitySteel, length=self.pistonLength,
95 # outerRadius=self.pistonRadius, innerRadius=0.5*self.pistonRadius, axis=2)
96
97 self.inertiaPiston = InertiaCylinder(densitySteel, length=self.pistonLength,
98 outerRadius=self.pistonRadius, innerRadius=0.5*self.pistonRadius, axis=0)
99
100 #self.inertiaCrank.com = [0,0,0]
101 # print('crank COM=',np.array(self.inertiaCrank.com).round(8))
102 # print('inertiaCrank=',self.inertiaCrank)
103 # print('inertiaConrod=',self.inertiaConrod)
104 # print('inertiaPiston=',self.inertiaPiston)
105
106 def Length(self):
107 return self.pistonDistance*len(self.crankAngles) + self.crankBearingWidth
108
109 def MaxDimX(self):
110 return self.crankArmLength + self.conrodLength + self.pistonLength
111
112def ComputeSliderCrank(angleCrank, anglePiston, l1, l2):
113 phi1 = angleCrank-anglePiston
114 h = l1*sin(phi1) #height of crank-conrod bearing
115 phi2 = asin(h/l2) #angle of conrod in 2D slider-crank, corotated with piston rotation
116 angleConrod = anglePiston-phi2
117 Acr = RotationMatrixZ(angleConrod)
118 dp = l1*cos(phi1) + l2*cos(phi2) #distance of piston from crank rotation axis
119 return [phi1,phi2, angleConrod, Acr, dp]
120
121
122#this function (re-)creates gear geometry
123def CreateEngine(P):
124
125 colorCrank = graphics.color.grey
126 colorConrod = graphics.color.dodgerblue
127 colorPiston = graphics.color.brown[0:3]+[0.5]
128 showJoints = True
129
130 gravity = [0,-9.81*0,0]
131 eL = P.Length()
132 oGround=mbs.AddObject(ObjectGround(referencePosition= [0,0,zOffAdd], visualization=VObjectGround(graphicsData= [])))
133 nGround=mbs.AddNode(NodePointGround(referenceCoordinates = [0,0,zOffAdd]))
134
135 # gEngine = [graphics.Brick(centerPoint=[0,0,0], size=[P.MaxDimX()*2, P.MaxDimX(), eL*1.2],
136 # color=[0.6,0.6,0.6,0.1], addEdges=True,
137 # edgeColor = [0.8,0.8,0.8,0.3], addFaces=False)]
138
139 gEngine = [] #no block
140 dictEngine = mbs.CreateRigidBody(
141 inertia=InertiaCuboid(1000, sideLengths=[1, 1, 1]), # dummy engine inertia
142 nodeType=nodeType,
143 referencePosition=[0, 0, zOffAdd],
144 graphicsDataList=gEngine,
145 returnDict=True,
146 show=False)
147
148 [nEngine, oEngine] = [dictEngine['nodeNumber'], dictEngine['bodyNumber']]
149
150 mGround = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oGround))
151 mEngine = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oEngine))
152 sEngineForce = 0
153 oEngineJoint = 0
154 sEngineTorque = 0
155 oEngineJoint = mbs.AddObject(GenericJoint(markerNumbers=[mEngine, mGround], constrainedAxes=[1,1,1, 1,1,1],
156 visualization=VGenericJoint(show=False)))
157 sEngineForce = mbs.AddSensor(SensorObject(objectNumber=oEngineJoint, storeInternal=True,
158 outputVariableType=exu.OutputVariableType.ForceLocal))
159 sEngineTorque = mbs.AddSensor(SensorObject(objectNumber=oEngineJoint, storeInternal=True,
160 outputVariableType=exu.OutputVariableType.TorqueLocal))
161
162 bConrodList = []
163 bPistonList = []
164 gCrank = []
165 for cnt, angleCrank in enumerate(P.crankAngles):
166 anglePiston = P.pistonAngles[cnt]
167 Ac = RotationMatrixZ(angleCrank)
168 Ap = RotationMatrixZ(anglePiston)
169 [phi1,phi2, angleConrod, Acr, dp] = ComputeSliderCrank(angleCrank, anglePiston, P.crankArmLength, P.conrodLength)
170
171 zOff = -0.5*eL + cnt*P.pistonDistance + zOffAdd
172 #zOff = 0
173 #crank bearing
174 zAdd = 0
175 if cnt>0: zAdd = P.crankArmWidth
176 gCrank += [graphics.Cylinder(pAxis=[0,0,zOff-zAdd], vAxis=[0,0,P.crankBearingWidth+P.crankArmWidth+zAdd],
177 radius=P.crankBearingRadius, color=graphics.color.red)]
178 #arm1
179 arm1 = graphics.Brick([P.crankArmLength*0.5,0,zOff+P.crankArmWidth*0.5+P.crankBearingWidth],
180 size=[P.crankArmLength,P.crankArmHeight,P.crankArmWidth], color=colorCrank)
181 gCrank += [graphics.Move(arm1, [0,0,0], Ac)]
182 #conrod bearing
183 gCrank += [graphics.Cylinder(pAxis=Ac@[P.crankArmLength,0,zOff+P.crankBearingWidth+P.crankArmWidth*0],
184 vAxis=[0,0,P.conrodCrankCylLength+2*P.crankArmWidth], radius=P.conrodCrankCylRadius, color=colorCrank)]
185
186 #arm2
187 arm2 = graphics.Brick([P.crankArmLength*0.5,0,zOff+P.crankArmWidth*1.5+P.crankBearingWidth+P.conrodCrankCylLength],
188 size=[P.crankArmLength,P.crankArmHeight,P.crankArmWidth],
189 color=colorCrank)
190 gCrank += [graphics.Move(arm2, [0,0,0], Ac)]
191
192 if cnt == len(P.crankAngles)-1:
193 gCrank += [graphics.Cylinder(pAxis=[0,0,zOff+P.crankArmWidth+P.crankBearingWidth+P.conrodCrankCylLength], vAxis=[0,0,P.crankBearingWidth+P.crankArmWidth],
194 radius=P.crankBearingRadius, color=graphics.color.red)]
195
196 #++++++++++++++++++++++++++++++++++++++
197 #conrod
198 gConrod = [ graphics.RigidLink(p0=[-0.5*P.conrodLength, 0, 0], p1=[0.5*P.conrodLength,0,0], axis0= [0,0,1], axis1= [0,0,1],
199 radius= [P.conrodRadius]*2,
200 thickness= P.conrodHeight, width=[P.conrodWidth]*2, color= colorConrod, nTiles= 16)]
201
202 bConrod = mbs.CreateRigidBody(
203 inertia=P.inertiaConrod,
204 nodeType=nodeType,
205 referencePosition=Ac @ [P.crankArmLength, 0, 0] + Acr @ [0.5 * P.conrodLength, 0,
206 zOff + P.crankArmWidth + P.crankBearingWidth + 0.5 * P.conrodCrankCylLength],
207 referenceRotationMatrix=Acr,
208 gravity=gravity,
209 graphicsDataList=gConrod)
210 bConrodList += [bConrod]
211
212 #++++++++++++++++++++++++++++++++++++++
213 #gPiston setup
214 gPiston = [graphics.Cylinder(pAxis=[-P.conrodRadius*0.5, 0, 0],
215 vAxis=[P.pistonLength, 0, 0], radius=P.pistonRadius, color=colorPiston)]
216
217 bPiston = mbs.CreateRigidBody(
218 inertia=P.inertiaPiston,
219 nodeType=nodeType,
220 referencePosition=Ap @ [dp, 0,
221 zOff + P.crankArmWidth + P.crankBearingWidth + 0.5 * P.conrodCrankCylLength],
222 referenceRotationMatrix=Ap,
223 gravity=gravity,
224 graphicsDataList=gPiston)
225 bPistonList += [bPiston]
226
227 dictCrank = mbs.CreateRigidBody(
228 inertia=P.inertiaCrank,
229 nodeType=nodeType,
230 referencePosition=[0, 0, 0],
231 gravity=gravity,
232 graphicsDataList=gCrank,
233 returnDict=True)
234 [nCrank, bCrank] = [dictCrank['nodeNumber'], dictCrank['bodyNumber']]
235
236 sCrankAngVel = mbs.AddSensor(SensorNode(nodeNumber=nCrank, storeInternal=True,
237 outputVariableType=exu.OutputVariableType.AngularVelocity))
238
239 #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
240 #JOINTS:
241 mbs.CreateRevoluteJoint(bodyNumbers=[oEngine, bCrank], position=[0,0,-0.5*eL], axis=[0,0,1],
242 axisRadius=P.crankBearingRadius*1.2, axisLength=P.crankBearingWidth*0.8)
243 # [oJointCrank, mBody0Crank, mBody1Crank] = AddRevolute*Joint(mbs, oEngine, bCrank, point=[0,0,-0.5*eL], axis=[0,0,1], showJoint=showJoints,
244 # axisRadius=P.crankBearingRadius*1.2, axisLength=P.crankBearingWidth*0.8)
245
246
247 for cnt, angleCrank in enumerate(P.crankAngles):
248 anglePiston = P.pistonAngles[cnt]
249 Ac = RotationMatrixZ(angleCrank)
250 Ap = RotationMatrixZ(anglePiston)
251 [phi1,phi2, angleConrod, Acr, dp] = ComputeSliderCrank(angleCrank, anglePiston, P.crankArmLength, P.conrodLength)
252
253 zOff = -0.5*eL + cnt*P.pistonDistance
254 #zOff = 0
255
256 mbs.CreateRevoluteJoint(bodyNumbers=[bCrank, bConrodList[cnt]],
257 position=Ac@[P.crankArmLength,0,zOff + P.crankBearingWidth+P.crankArmWidth+0.5*P.conrodCrankCylLength],
258 axis=[0,0,1],
259 axisRadius=P.crankBearingRadius*1.3, axisLength=P.crankBearingWidth*0.8)
260 # [oJointCC, mBody0CC, mBody1CC] = AddRevoluteJoint(mbs, bCrank, bConrodList[cnt],
261 # point=Ac@[P.crankArmLength,0,zOff + P.crankBearingWidth+P.crankArmWidth+0.5*P.conrodCrankCylLength],
262 # axis=[0,0,1], showJoint=showJoints,
263 # axisRadius=P.crankBearingRadius*1.3, axisLength=P.crankBearingWidth*0.8)
264
265 #pPiston = A@[P.crankArmLength+P.conrodLength,0,zOff + P.crankBearingWidth+P.crankArmWidth+0.5*P.conrodCrankCylLength]
266 pPiston = Ap@[dp,0,zOff + P.crankBearingWidth+P.crankArmWidth+0.5*P.conrodCrankCylLength]
267 mbs.CreateRevoluteJoint(bodyNumbers=[bConrodList[cnt], bPistonList[cnt]],
268 position=pPiston,
269 axis=[0,0,1],
270 axisRadius=P.crankBearingRadius*1.3, axisLength=P.crankBearingWidth*0.8)
271 # [oJointCP, mBody0CP, mBody1CP] = AddRevoluteJoint(mbs, bConrodList[cnt], bPistonList[cnt],
272 # point=pPiston,
273 # axis=[0,0,1], showJoint=showJoints,
274 # axisRadius=P.crankBearingRadius*1.3, axisLength=P.crankBearingWidth*0.8)
275
276 # AddPrismaticJoint(mbs, oEngine, bPistonList[cnt],
277 # point=pPiston,
278 # axis=A@[1,0,0], showJoint=showJoints,
279 # axisRadius=P.crankBearingRadius*1.3, axisLength=P.crankBearingWidth*0.8)
280 mEngine = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oEngine, localPosition=pPiston))
281 mPiston = mbs.AddMarker(MarkerBodyRigid(bodyNumber=bPistonList[cnt], localPosition=[0,0,0]))
282 mbs.AddObject(GenericJoint(markerNumbers=[mPiston, mEngine], constrainedAxes=[0,1,0, 0,0,1],
283 # rotationMarker0=A.T,
284 rotationMarker1=Ap,
285 visualization=VGenericJoint(show=False, axesRadius=P.conrodRadius*1.4,axesLength=0.05)))
286
287 #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
288 #DRIVE:
289 def UFoffset(mbs, t, itemNumber, lOffset):
290 return 0
291
292 def UFoffset_t(mbs, t, itemNumber, lOffset): #time derivative of UFoffset
293 return SmoothStep(t, 0, 0.5, 0, omegaDrive)
294
295 mCrankRotation = mbs.AddMarker(MarkerNodeRotationCoordinate(nodeNumber=nCrank, rotationCoordinate=2))
296 mNodeEngine = mbs.AddMarker(MarkerNodeRotationCoordinate(nodeNumber=nEngine, rotationCoordinate=2))
297 oRotationConstraint = mbs.AddObject(CoordinateConstraint(markerNumbers=[mNodeEngine, mCrankRotation], velocityLevel=True,
298 offsetUserFunction=UFoffset,
299 offsetUserFunction_t=UFoffset_t,
300 visualization=VCoordinateConstraint(show=False)))
301
302 return [oEngine, oEngineJoint, sEngineForce, sEngineTorque, sCrankAngVel, oRotationConstraint, nCrank, bCrank]
303
304engines = []
305engines+=[EngineParameters([0])] #R1
306engines+=[EngineParameters([0,180])] #R2
307engines+=[EngineParameters([0,180,180,0])] #R4 straight-four engine, Reihen-4-Zylinder
308engines+=[EngineParameters([0,90,270,180])] #R4 in different configuration
309engines+=[EngineParameters([0,180,180,0],[0,180,180,0])] #Boxer 4-piston perfect mass balancing
310
311engines+=[EngineParameters([0,120,240])] #R3
312engines+=[EngineParameters(list(np.arange(0,5)*144))] #R5
313engines+=[EngineParameters([0,120,240,240,120,0])] #R6
314engines+=[EngineParameters([0,0,120,120,240,240],[-30,30,-30,30,-30,30])] #V6
315engines+=[EngineParameters([0,0,120,120,240,240,240,240,120,120,0,0],[-30,30,-30,30,-30,30,30,-30,30,-30,30,-30])] #V12
316
317engines+=[EngineParameters([0,90,180,270,270,180,90,360])] #R8
318engines+=[EngineParameters([0,0,90,90,270,270,180,180], [-45,45,-45,45, 45,-45,45,-45])] #V8
319
320# n=12
321# a=list(np.arange(0,n)*30)
322# b=list(np.arange(n-1,-1,-1)*30)
323# #engines+=[EngineParameters(a+a,b+b)
324
325#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
326#
327engines=[EngineParameters([0,90,270,180], [90]*4)]
328#engines=[EngineParameters([0,0,120,120,240,240,240,240,120,120,0,0],[60,120,60,120,60,120,120,60,120,60,120,60])] #V12
329
330for engine in engines:
331
332 SC = exu.SystemContainer()
333 mbs = SC.AddSystem()
334
335 [oEngine, oEngineJoint, sEngineForce, sEngineTorque, sCrankAngVel, oRotationConstraint,
336 nCrank, bCrank] = CreateEngine(engine)
337
338 d = 2.4 #box size
339 h = 0.5*d #box half size
340 w = d
341 gDataList = []
342 gDataList += [graphics.CheckerBoard(point=[0,0,-h], normal=[0,0,1], size=2*d, size2=d, nTiles=12*2, nTiles2=12, color=graphics.color.grey)]
343 gDataList += [graphics.CheckerBoard(point=[-w,0,0], normal=[ 1,0,0], size=d, nTiles=12, color=graphics.color.lightgrey)]
344 gDataList += [graphics.CheckerBoard(point=[ w,0,0], normal=[-1,0,0], size=d, nTiles=12, color=graphics.color.lightgrey)]
345 gDataList += [graphics.CheckerBoard(point=[0,-h,0], normal=[0,-1,0], size=2*d, size2=d, nTiles=12*2, nTiles2=12, color=graphics.color.dodgerblue)]
346 gDataList += [graphics.CheckerBoard(point=[0, h,0], normal=[0, 1,0], size=2*d, size2=d, nTiles=1, color=[0.8,0.8,1,1])]#, alternatingColor=[0.8,0.8,1,1])]
347 # gDataList += [graphics.CheckerBoard(point=[0, 0,h], normal=[0, 0,-1], size=d, nTiles=1, color=[0.8,0.8,0.8,0.9])]
348
349 oGround=mbs.AddObject(ObjectGround(referencePosition= [0,0,0],
350 visualization=VObjectGround(graphicsData=gDataList)))
351
352
353 def PreStepUF(mbs, t):
354 u = mbs.systemData.GetODE2Coordinates()
355
356 if not fixedSpeed and t >= 1: #at this point, the mechanism runs freely
357 mbs.SetObjectParameter(oRotationConstraint, 'activeConnector', False)
358
359 #mbs.systemData.SetODE2Coordinates(u)
360 return True
361
362 mbs.SetPreStepUserFunction(PreStepUF)
363
364
365 mbs.Assemble()
366
367 stepSize = 0.002
368 simulationSettings = exu.SimulationSettings() #takes currently set values or default values
369
370 simulationSettings.timeIntegration.numberOfSteps = int(tEnd/stepSize)
371 simulationSettings.timeIntegration.endTime = tEnd
372 # simulationSettings.timeIntegration.newton.relativeTolerance = 1e-8*0.01
373 # simulationSettings.timeIntegration.newton.absoluteTolerance = 1e-10*0.01
374 simulationSettings.timeIntegration.verboseMode = 1
375
376 # simulationSettings.timeIntegration.simulateInRealtime = True
377
378 simulationSettings.solutionSettings.solutionWritePeriod=0.01
379 simulationSettings.solutionSettings.sensorsWritePeriod = stepSize*10
380 simulationSettings.solutionSettings.writeSolutionToFile = False
381 #simulationSettings.solutionSettings.writeInitialValues = False #otherwise values are duplicated
382 #simulationSettings.solutionSettings.coordinatesSolutionFileName = 'solution/coordinatesSolution.txt'
383
384 simulationSettings.timeIntegration.generalizedAlpha.computeInitialAccelerations = False
385
386 simulationSettings.timeIntegration.generalizedAlpha.lieGroupAddTangentOperator = False
387 #simulationSettings.displayStatistics = True
388 # simulationSettings.displayComputationTime = True
389 simulationSettings.linearSolverType=exu.LinearSolverType.EigenSparse
390
391 #SC.visualizationSettings.nodes.defaultSize = 0.05
392
393 simulationSettings.solutionSettings.solutionInformation = "Engine"
394
395 SC.visualizationSettings.general.graphicsUpdateInterval = 0.01
396 #SC.visualizationSettings.general.drawWorldBasis = True
397 #SC.visualizationSettings.general.worldBasisSize = 0.1
398
399 SC.visualizationSettings.markers.show = False
400 SC.visualizationSettings.loads.show = False
401 SC.visualizationSettings.nodes.show = False
402 SC.visualizationSettings.connectors.show = False
403
404 SC.visualizationSettings.openGL.multiSampling = 4
405 SC.visualizationSettings.openGL.shadow = 0.3 #set to 0, if your graphics card cannot handle this!
406 SC.visualizationSettings.openGL.lineWidth = 3
407 SC.visualizationSettings.openGL.light0position = [0.25,1,3,0]
408
409 #++++++++++++++++++++++++++++++++
410 #openVR:
411 SC.visualizationSettings.general.drawCoordinateSystem = False
412 #good for openVR
413 SC.visualizationSettings.general.graphicsUpdateInterval = 0.005 #small enough to get large enough fps
414 simulationSettings.timeIntegration.simulateInRealtime = True
415
416 useOpenVR = False #set this true for openVR to run!!!
417 SC.visualizationSettings.window.renderWindowSize=[1176, 1320] # this needs to fit to your VR HMD (Head Mounted Display) settings (will show in console when openVR is started and openVR.logLevel is large enough!)
418 if useOpenVR:
419 SC.visualizationSettings.openGL.initialZoom = 1# 0.4*20 #0.4*max scene size
420 #SC.visualizationSettings.openGL.initialCenterPoint = [0,0,2]
421 SC.visualizationSettings.general.autoFitScene = False
422 SC.visualizationSettings.window.limitWindowToScreenSize = False #this allows a larger window size than your monitor can display in case!
423 SC.visualizationSettings.window.startupTimeout = 100000 #if steam / VRidge, etc. not found
424 SC.visualizationSettings.interactive.openVR.enable = True
425 SC.visualizationSettings.interactive.lockModelView = True #lock rotation/translation/zoom of model
426 SC.visualizationSettings.interactive.openVR.logLevel = 3
427 SC.visualizationSettings.interactive.openVR.actionManifestFileName = "C:/DATA/cpp/DocumentationAndInformation/openVR/hellovr_actions.json"
428
429 #%%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
430
431
432 SC.visualizationSettings.general.autoFitScene = False #use loaded render state
433 SC.renderer.Start()
434 SC.renderer.DoIdleTasks()
435 cws = SC.renderer.GetState()['currentWindowSize']
436 print('window size=', cws, '(check that this is according to needs of Head Mounted Display)')
437 # if 'renderState' in exu.sys:
438 # SC.renderer.SetState(exu.sys[ 'renderState' ])
439
440 mbs.SolveDynamic(simulationSettings)
441
442 SC.renderer.Stop() #safely close rendering window!