scissorPrismaticRevolute2D.py

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

  1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2# This is an EXUDYN example
  3#
  4# Details:  Create scissor-like chain of bodies and prismatic joints to test functionality
  5#
  6# Author:   Johannes Gerstmayr
  7# Date:     2020-01-14
  8#
  9# 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.
 10#
 11#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 12
 13import exudyn as exu
 14from exudyn.utilities import *
 15
 16useGraphics = True #without test
 17#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 18#you can erase the following lines and all exudynTestGlobals related operations if this is not intended to be used as TestModel:
 19try: #only if called from test suite
 20    from modelUnitTests import exudynTestGlobals #for globally storing test results
 21    useGraphics = exudynTestGlobals.useGraphics
 22except:
 23    class ExudynTestGlobals:
 24        pass
 25    exudynTestGlobals = ExudynTestGlobals()
 26#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 27
 28SC = exu.SystemContainer()
 29mbs = SC.AddSystem()
 30
 31L = 0.8 #distance
 32b=L*0.1
 33mass = 1
 34g = 9.81*0.1
 35
 36#number of scissors:
 37n=3 #run test with n=3
 38
 39r = 0.05 #just for graphics
 40nL = (n+0.5)*L
 41graphicsBackground = GraphicsDataRectangle(-L*1.5,-L*1.5, 1.5*nL, nL, color4lightgrey) #for appropriate zoom
 42graphicscube = GraphicsDataRectangle(-L,-0.5*b, L, 0.5*b, color4steelblue) #GraphicsDataSphere(point=[0,0,0], radius=r, color=[1.,0.2,0.2,1], nTiles = 8)
 43graphicscube2 = GraphicsDataRectangle(-L,-0.5*b, n*L*2**0.5, 0.5*b, color4steelblue) #GraphicsDataSphere(point=[0,0,0], radius=r, color=[1.,0.2,0.2,1], nTiles = 8)
 44#add ground object and mass point:
 45
 46pi = 3.1415926535897932384626
 47
 48#prescribed driving function:
 49def springForceUF(mbs, t, itemIndex, u, v, k, d, offset): #changed 2023-01-21:, mu, muPropZone):
 50    f=k*(u+offset)+v*d
 51    return f
 52
 53addPrismaticJoint = True
 54useCartesianSD = True
 55
 56simulationSettings = exu.SimulationSettings()
 57
 58f = 500
 59simulationSettings.timeIntegration.numberOfSteps = int(1*f)
 60simulationSettings.timeIntegration.endTime = 0.02*f #make small steps to see something during simulation
 61simulationSettings.solutionSettings.solutionWritePeriod = simulationSettings.timeIntegration.endTime/5000
 62
 63simulationSettings.solutionSettings.writeSolutionToFile = True
 64simulationSettings.displayComputationTime = True
 65simulationSettings.timeIntegration.verboseMode = 1
 66#simulationSettings.timeIntegration.verboseModeFile = 0
 67
 68simulationSettings.timeIntegration.newton.useModifiedNewton = False
 69simulationSettings.timeIntegration.newton.modifiedNewtonJacUpdatePerStep = True
 70
 71#added JacobianODE2, but example computed with numDiff forODE2connectors, 2022-01-18: 27.202556489044145 :
 72simulationSettings.timeIntegration.newton.numericalDifferentiation.forODE2connectors=True
 73
 74simulationSettings.timeIntegration.generalizedAlpha.useNewmark = True
 75simulationSettings.timeIntegration.generalizedAlpha.useIndex2Constraints = simulationSettings.timeIntegration.generalizedAlpha.useNewmark
 76simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 0.6 #0.61
 77simulationSettings.timeIntegration.adaptiveStep = False
 78simulationSettings.linearSolverType = exu.LinearSolverType.EigenSparse
 79
 80simulationSettings.timeIntegration.generalizedAlpha.computeInitialAccelerations = True
 81simulationSettings.solutionSettings.coordinatesSolutionFileName= "coordinatesSolution.txt"
 82
 83
 84simulationSettings.displayComputationTime = False
 85simulationSettings.displayStatistics = True
 86
 87
 88if useGraphics: #only start graphics once, but after background is set
 89#    SC.visualizationSettings.window.alwaysOnTop = True #must be done before exu.StartRenderer() called
 90#    SC.visualizationSettings.window.maximize = True
 91#    SC.visualizationSettings.window.showWindow = False
 92    exu.StartRenderer()
 93
 94
 95
 96resUy = 0 #add up displacements of selected node
 97resIt = 0 #total iterations
 98nMeasure = 0 #selected node
 99#treat two cases: 0=revolute, 1=ObjectConnectorCartesianSpringDamper
100for case in range(2):
101    mbs.Reset()
102    oGround = mbs.AddObject(ObjectGround(referencePosition = [0,0,0], visualization = VObjectGround(graphicsData = [graphicsBackground])))
103    mGround = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oGround, localPosition = [0,0,0]))
104    #start 3D visualization
105
106    lastMarkerV = mGround
107    lastMarkerH = mGround
108
109    useCartesianSD = True
110    if case == 0: useCartesianSD = False
111    oBodyD = 0
112    mBodyDCOM = 0
113
114    #create several scissor elements if wanted
115    for i in range(n):
116        #stiffness and damping for CartesianSpringDamper
117        k=1e4
118        d=1e-2*k
119
120        #horizontal body:
121        nBodyH = mbs.AddNode(NodeRigidBody2D(referenceCoordinates=[L*i,L*i,0]))
122        oBodyH = mbs.AddObject(RigidBody2D(physicsMass = mass, physicsInertia=mass, nodeNumber = nBodyH, visualization = VObjectRigidBody2D(graphicsData = [graphicscube])))
123
124        mBodyH0 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oBodyH, localPosition=[-L,0,0]))
125        mBodyH1 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oBodyH, localPosition=[ L,0,0]))
126        mBodyHCOM = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oBodyH, localPosition=[ 0,0,0]))
127
128        #vertical body:
129        nBodyV = mbs.AddNode(NodeRigidBody2D(referenceCoordinates=[L*i,L*i,0.5*pi]))
130        oBodyV = mbs.AddObject(RigidBody2D(physicsMass = mass, physicsInertia=mass, nodeNumber = nBodyV, visualization = VObjectRigidBody2D(graphicsData = [graphicscube])))
131        nMeasure = nBodyV
132
133        mBodyV0 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oBodyV, localPosition=[-L,0,0]))
134        mBodyV1 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oBodyV, localPosition=[ L,0,0]))
135        mBodyVCOM = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oBodyV, localPosition=[ 0,0,0]))
136
137        #diagonal body:
138        if i==0 and addPrismaticJoint:
139            nBodyD = mbs.AddNode(NodeRigidBody2D(referenceCoordinates=[0,0,0.25*pi]))
140            oBodyD = mbs.AddObject(RigidBody2D(physicsMass = mass, physicsInertia=mass, nodeNumber = nBodyD, visualization = VObjectRigidBody2D(graphicsData = [graphicscube2])))
141
142            #mBodyD0 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oBodyD, localPosition=[-L,0,0]))
143            #mBodyD1 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oBodyD, localPosition=[ L,0,0]))
144            mBodyDCOM = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oBodyD, localPosition=[ 0,0,0]))
145            mbs.AddLoad(Force(markerNumber = mBodyDCOM, loadVector = [0, -mass*g, 0]))
146            #keep this as Cartesian spring damper, as revolute joint may overconstrain system?
147            mbs.AddObject(ObjectConnectorCartesianSpringDamper(markerNumbers=[mBodyDCOM, mGround], stiffness = [k, k, k], damping=[d,d,d]))
148
149        if addPrismaticJoint and i>0:
150            mBodyDact = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oBodyD, localPosition=[ i*L*2**0.5,0,0]))
151            mbs.AddObject(PrismaticJoint2D(markerNumbers=[mBodyVCOM, mBodyDact], axisMarker0=[1,0,0], normalMarker1=[0,1,0], constrainRotation=False))
152
153
154        if i==0:
155            if useCartesianSD:
156                mbs.AddObject(ObjectConnectorCartesianSpringDamper(markerNumbers=[mBodyHCOM, mGround], stiffness = [k, k, k], damping=[d,d,d]))
157                mbs.AddObject(ObjectConnectorCartesianSpringDamper(markerNumbers=[mBodyVCOM, mGround], stiffness = [k, k, k], damping=[d,d,d]))
158            else:
159                mbs.AddObject(RevoluteJoint2D(markerNumbers=[mBodyHCOM, mGround]))
160                mbs.AddObject(RevoluteJoint2D(markerNumbers=[mBodyVCOM, mGround]))
161
162            #fix rotation of H-body
163            nGround = mbs.AddNode(NodePointGround(referenceCoordinates=[L,0,0]))
164            mCoordGround = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber=nGround, coordinate=0)) #ref node
165            mCoordPhiH = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber=nBodyH, coordinate=2)) #rotation
166            mbs.AddObject(CoordinateConstraint(markerNumbers=[mCoordGround, mCoordPhiH]))
167
168            #activate rotation of V-body
169            mCoordPhiV = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber=nBodyV, coordinate=2)) #rotation
170            mbs.AddObject(ObjectConnectorCoordinateSpringDamper(markerNumbers=[mCoordGround, mCoordPhiV], stiffness=1e4, damping=10e3,
171            offset=0.25*pi,springForceUserFunction=springForceUF))
172
173        else:
174            if useCartesianSD:
175                mbs.AddObject(ObjectConnectorCartesianSpringDamper(markerNumbers=[mBodyHCOM, mBodyVCOM], stiffness = [k, k, k], damping=[d,d,d]))
176                mbs.AddObject(ObjectConnectorCartesianSpringDamper(markerNumbers=[mBodyH0, lastMarkerV], stiffness = [k, k, k], damping=[d,d,d]))
177                mbs.AddObject(ObjectConnectorCartesianSpringDamper(markerNumbers=[mBodyV0, lastMarkerH], stiffness = [k, k, k], damping=[d,d,d]))
178            else:
179                mbs.AddObject(RevoluteJoint2D(markerNumbers=[mBodyHCOM, mBodyVCOM]))
180                mbs.AddObject(RevoluteJoint2D(markerNumbers=[mBodyH0, lastMarkerV]))
181                mbs.AddObject(RevoluteJoint2D(markerNumbers=[mBodyV0, lastMarkerH]))
182
183        lastMarkerH = mBodyH1
184        lastMarkerV = mBodyV1
185
186        mbs.AddLoad(Force(markerNumber = mBodyHCOM, loadVector = [0, -mass*g, 0]))
187        mbs.AddLoad(Force(markerNumber = mBodyVCOM, loadVector = [0, -mass*g, 0]))
188
189    #exu.Print(mbs)
190    mbs.Assemble()
191    SC.RenderEngineZoomAll()
192
193    if useGraphics:
194        mbs.WaitForUserToContinue()
195    #solve
196    #exu.InfoStat()
197    solver = exu.MainSolverImplicitSecondOrder()
198    solver.SolveSystem(mbs, simulationSettings)
199    #exu.Print("jac=",solver.GetSystemJacobian())
200    #exu.Print(solver.conv)
201    #exu.Print(solver.it)
202    #exu.InfoStat()
203    uy=mbs.GetNodeOutput(nMeasure,exu.OutputVariableType.Position)[1] #y-coordinate of node point
204    exu.Print("uy=",uy)
205    nit = solver.it.newtonStepsCount
206    exu.Print("solver.it.newtonStepsCount=",nit)
207    resUy += uy #add up displacements of selected node
208    resIt += nit #total iterations
209#    mbs.WaitForUserToContinue()
210
211    #alternative solver command
212    #mbs.SolveDynamic(simulationSettings)
213
214
215
216#stop 3D visualization
217if useGraphics:
218    SC.WaitForRenderEngineStopFlag()
219    exu.StopRenderer() #safely close rendering window!
220
221#factor 1e-2: 32bit version shows larger differences ...
222exudynTestGlobals.testError = 1e-2*(resUy + resIt - (1.131033204186729+1.1246157002409096 + 1501+1217)) #2020-01-16: (1.131033204186729+1.1246157002409096 + 1501+1217)
223exudynTestGlobals.testResult = 1e-2*(resUy + resIt)
224#+++++++++++++++++++++++++++++++++++
225#plot data:
226
227#if simulationSettings.solutionSettings.writeSolutionToFile:
228#    import matplotlib.pyplot as plt
229#    import matplotlib.ticker as ticker
230
231#    data = np.loadtxt('coordinatesSolution.txt', comments='#', delimiter=',')
232#    plt.plot(data[:,0], data[:,1+2*nODE2+1], 'b-')
233#    #plt.plot(data[:,0], data[:,1+1], 'r-') #y-coordinate
234
235#    ax=plt.gca() # get current axes
236#    ax.grid(True, 'major', 'both')
237#    ax.xaxis.set_major_locator(ticker.MaxNLocator(10))
238#    ax.yaxis.set_major_locator(ticker.MaxNLocator(10))
239#    plt.tight_layout()
240#    plt.show()