slidercrankWithMassSpring.py

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

  1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2# This is an EXUDYN example
  3#
  4# Details:  Slider crank with additional mass and spring (flexible slidercrank);
  5#           Example of paper Arnold, Brüls, 2007, Convergence of the generalized-[alpha] scheme for constrained mechanical systems, Multibody System Dynamics
  6#
  7# Author:   Johannes Gerstmayr
  8# Date:     2019-12-28
  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
 15#a local run must not open a plot window when windows are suppressed (#2477)
 16if exu.special.userInterface.suppressPlots: import matplotlib; matplotlib.use('Agg')
 17from exudyn.itemInterface import *
 18from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities
 19import exudyn.graphics as graphics
 20
 21import numpy as np
 22import matplotlib.pyplot as plt
 23import matplotlib.ticker as ticker
 24
 25SC = exu.SystemContainer()
 26mbs = SC.AddSystem()
 27
 28
 29useGraphics = True
 30
 31nGround = mbs.AddNode(NodePointGround(referenceCoordinates=[0,0,0])) #ground node for coordinate constraint
 32mGround = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber = nGround, coordinate=0)) #Ground node ==> no action
 33
 34
 35#++++++++++++++++++++++++++++++++
 36#floating body to mount slider-crank mechanism
 37#constrainGroundBody = True #use this flag to fix ground body
 38
 39#graphics for floating frame:
 40gFloating = graphics.Lines([[-0.25,-0.25,0], [0.8,-0.25,0], [0.8,0.25,0], [-0.25,0.25,0], [-0.25,-0.25,0]], color=[0.95,0.95,0.95,1.]) 
 41#gFloating = graphics.BrickXYZ(-0.25, -0.25, -0.1, 0.8, 0.25, -0.05, color=[0.3,0.3,0.3,1.]) 
 42
 43oGround = mbs.AddObject(ObjectGround(referencePosition=[0,0,0], visualization=VObjectGround(graphicsData=[gFloating])))    
 44mG0 = mbs.AddMarker(MarkerBodyPosition(bodyNumber = oGround, localPosition=[0,0,0]))
 45#mFloatingN = mbs.AddMarker(MarkerBodyPosition(bodyNumber = floatingRB, localPosition=[0,0,0]))
 46
 47
 48#++++++++++++++++++++++++++++++++
 49#nodes and bodies
 50omega=2*pi/60*300 #3000 rpm
 51L1=0.3
 52L2=0.6
 53L3=0.2
 54s1=L1*0.5
 55s2=L2*0.5
 56m1=0.36
 57m2=0.15
 58m3=0.1
 59m4=0.7
 60M=1 #torque (default: 0.1)
 61#lambda=L1/L2
 62J1=(m1/12.)*L1**2*1e-10 #inertia w.r.t. center of mass
 63J2=(m2/12.)*L2**2*1e-10 #inertia w.r.t. center of mass
 64
 65ty = 0.05    #thickness
 66tz = 0.05    #thickness
 67#graphics1 = GraphicsDataRectangle(-0.5*L1,-0.5*ty,0.5*L1,0.5*ty,graphics.color.steelblue)
 68#graphics1 = graphics.BrickXYZ(-0.5*L1,-0.5*ty,-tz,0.5*L1,0.5*ty,0,graphics.color.steelblue)
 69graphics1 = graphics.RigidLink(p0=[-0.5*L1,0,-0.5*tz],p1=[0.5*L1,0,-0.5*tz], 
 70                                  axis0=[0,0,1], axis1=[0,0,1],radius=[0.5*ty,0.5*ty],
 71                                  thickness=0.8*ty, width=[tz,tz], color=graphics.color.steelblue,nTiles=16)
 72
 73#graphics2 = GraphicsDataRectangle(-0.5*L2,-0.5*ty,0.5*L2,0.5*ty,graphics.color.lightred)
 74#graphics2 = graphics.BrickXYZ(-0.5*L2,-0.5*ty,0,0.5*L2,0.5*ty,tz,graphics.color.lightred)
 75graphics2 = graphics.RigidLink(p0=[-0.5*L2,0,0.5*tz],p1=[0.5*L2,0,0.5*tz], 
 76                                  axis0=[0,0,1], axis1=[0,0,1],radius=[0.5*ty,0.5*ty],
 77                                  thickness=0.8*ty, width=[tz,tz], color=graphics.color.lightred,nTiles=16)
 78
 79#crank:
 80nRigid1 = mbs.AddNode(Rigid2D(referenceCoordinates=[s1,0,0], 
 81                              initialVelocities=[0,0,0]));
 82oRigid1 = mbs.AddObject(RigidBody2D(mass=m1, 
 83                                    inertia=J1,
 84                                    nodeNumber=nRigid1,
 85                                    visualization=VObjectRigidBody2D(graphicsData= [graphics1])))
 86
 87#connecting rod:
 88nRigid2 = mbs.AddNode(Rigid2D(referenceCoordinates=[L1+s2,0,0], 
 89                              initialVelocities=[0,0,0]));
 90oRigid2 = mbs.AddObject(RigidBody2D(mass=m2, 
 91                                    inertia=J2,
 92                                    nodeNumber=nRigid2,
 93                                    visualization=VObjectRigidBody2D(graphicsData= [graphics2])))
 94
 95
 96#++++++++++++++++++++++++++++++++
 97#slider:
 98c=0.025 #dimension of mass
 99graphics3 = graphics.Brick(centerPoint=[0, 0, -c], size=[2*c, 2*c, 2*c], color=graphics.color.grey)
100
101nMass3 = mbs.AddNode(Point2D(referenceCoordinates=[L1+L2,0]))
102oMass3 = mbs.AddObject(MassPoint2D(mass=m3, nodeNumber=nMass3,visualization=VObjectRigidBody2D(graphicsData= [graphics3])))
103
104nMass4 = mbs.AddNode(Point2D(referenceCoordinates=[L1+L2+L3,0]))
105oMass4 = mbs.AddObject(MassPoint2D(mass=m4, nodeNumber=nMass4,visualization=VObjectRigidBody2D(graphicsData= [graphics3])))
106
107#++++++++++++++++++++++++++++++++
108#markers for joints:
109mR1Left = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid1, localPosition=[-s1,0.,0.])) #support point # MUST be a rigidBodyMarker, because a torque is applied
110mR1Right = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid1, localPosition=[ s1,0.,0.])) #end point; connection to connecting rod
111
112mR2Left = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid2, localPosition=[-s2,0.,0.])) #connection to crank
113mR2Right = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oRigid2, localPosition=[ s2,0.,0.])) #end point; connection to slider
114
115mMass3 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oMass3, localPosition=[ 0.,0.,0.]))
116
117mMass4 = mbs.AddMarker(MarkerBodyPosition(bodyNumber=oMass4, localPosition=[ 0.,0.,0.]))
118
119
120#++++++++++++++++++++++++++++++++
121#joints:
122mbs.AddObject(RevoluteJoint2D(markerNumbers=[mG0,mR1Left]))
123mbs.AddObject(RevoluteJoint2D(markerNumbers=[mR1Right,mR2Left]))
124mbs.AddObject(RevoluteJoint2D(markerNumbers=[mR2Right,mMass3]))
125
126#++++++++++++++++++++++++++++++++
127#markers for node constraints:
128mNodeSliderX = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber = nMass3, coordinate=0)) #y-coordinate is constrained
129mNodeSliderY = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber = nMass3, coordinate=1)) #y-coordinate is constrained
130mNodeSliderX2= mbs.AddMarker(MarkerNodeCoordinate(nodeNumber = nMass4, coordinate=0)) #y-coordinate is constrained
131mNodeSliderY2= mbs.AddMarker(MarkerNodeCoordinate(nodeNumber = nMass4, coordinate=1)) #y-coordinate is constrained
132#coordinate constraints for slider (free motion in x-direction)
133mbs.AddObject(CoordinateConstraint(markerNumbers=[mGround,mNodeSliderY]))
134mbs.AddObject(CoordinateConstraint(markerNumbers=[mGround,mNodeSliderY2]))
135
136#add spring between mass 3 and 4
137mbs.AddObject(ObjectConnectorCoordinateSpringDamper(markerNumbers = [mNodeSliderX, mNodeSliderX2], 
138                                                    stiffness = 1000))
139
140#+++++++++++++++++++++++++++++++++++++++++
141#loads and driving forces:
142
143mRigid1CoordinateTheta = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber = nRigid1, coordinate=2)) #angle coordinate is constrained
144constraintCrankAngle = mbs.AddObject(CoordinateConstraint(markerNumbers=[mRigid1CoordinateTheta, mGround], offset = -1.*np.pi/2.))
145
146mbs.AddLoad(LoadCoordinate(markerNumber=mRigid1CoordinateTheta, load = M)) #torque at crank
147
148
149
150#++++++++++++++++++++++++++++++++
151#assemble, adjust settings and start time integration
152mbs.Assemble()
153if useGraphics: 
154    SC.renderer.Start()
155    #SC.renderer.DoIdleTasks()
156
157simulationSettings = exu.SimulationSettings() #takes currently set values or default values
158
159initCrank = True
160if initCrank:
161    #turn crank to 90° as enforced by constraintCrankAngle
162    mbs.SolveStatic(simulationSettings)
163    
164    #use static solution as initial conditions for dynamic solution
165    currentState = mbs.systemData.GetSystemState()
166    mbs.systemData.SetSystemState(currentState, configuration=exu.ConfigurationType.Initial)
167
168    mbs.SetObjectParameter(constraintCrankAngle, 'activeConnector', False)
169    #SC.renderer.DoIdleTasks()
170
171h = 5e-3   #5e-3 in paper of Arnold and Bruls
172T = 1
173simulationSettings.timeIntegration.endTime = T               #1s for test suite / error
174simulationSettings.timeIntegration.numberOfSteps = int(T/h)  #1000 steps for test suite/error
175
176#simulationSettings.timeIntegration.newton.relativeTolerance = 1e-8 #10000
177simulationSettings.timeIntegration.verboseMode = 1 #10000
178
179simulationSettings.solution.file.writePeriod = 1e-3
180#simulationSettings.timeIntegration.newton.useModifiedNewton = False
181simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 0.6 #0.7 in paper of Arnold and Bruls
182
183#++++++++++++++++++++++++++++++++++++++++++
184#solve index 2 / trapezoidal rule:
185simulationSettings.timeIntegration.generalizedAlpha.useNewmark = False
186simulationSettings.timeIntegration.generalizedAlpha.useIndex2Constraints = False
187
188dSize = 0.02
189SC.visualizationSettings.nodes.defaultSize = dSize
190SC.visualizationSettings.markers.defaultSize = dSize
191SC.visualizationSettings.bodies.defaultSize = [dSize]*3
192SC.visualizationSettings.connectors.defaultSize = dSize
193
194mbs.SolveDynamic(simulationSettings)
195    
196if useGraphics: 
197    #+++++++++++++++++++++++++++++++++++++
198    #animate solution
199#        mbs.WaitForUserToContinue
200#        fileName = 'solution/coordinatesSolution.txt'
201#        solution = LoadSolutionFile(OutputFilePath('solution/coordinatesSolution.txt'))
202#        AnimateSolution(mbs, solution, 10, 0.025, True)
203    #+++++++++++++++++++++++++++++++++++++
204
205    #SC.renderer.DoIdleTasks()
206    SC.renderer.Stop() #safely close rendering window!
207
208u = mbs.GetNodeOutput(nMass4, exu.OutputVariableType.Position) #tip node
209print('sol =', abs(u[0]))
210solutionSliderCrank = abs(u[0]) #x-position of slider
211
212
213print('solutionSliderCrankIndex2=',solutionSliderCrank)
214
215
216plotResults = useGraphics#constrainGroundBody #comparison only works in case of fixed ground
217if plotResults:
218    data = np.loadtxt(OutputFilePath('solution/coordinatesSolution.txt'), comments='#', delimiter=',')
219                            
220    vODE2=mbs.systemData.GetODE2Coordinates()
221    nODE2=len(vODE2) #number of ODE2 coordinates
222
223    nAngle = mbs.systemData.GetObjectLTGODE2(oRigid1)[2] #get coordinate index of angle
224    nM3 = mbs.systemData.GetObjectLTGODE2(oMass3)[0] #get X-coordinate of mass 4
225    nM4 = mbs.systemData.GetObjectLTGODE2(oMass4)[0] #get X-coordinate of mass 4
226    print("nAngle=", nAngle)
227    print("nM3=", nM3)
228    print("nM4=", nM4)
229    
230    plt.plot(data[:,0], data[:,1+nAngle], 'b-') #plot angle of crank;
231    #plt.plot(data[:,0], data[:,1+nM3], 'g-')    #Y position of mass 3
232    plt.plot(data[:,0], data[:,1+nM4], 'r-')    #Y position of mass 4
233    
234    ax=plt.gca() # get current axes
235    ax.grid(True, 'major', 'both')
236    ax.xaxis.set_major_locator(ticker.MaxNLocator(10)) #use maximum of 8 ticks on y-axis
237    ax.yaxis.set_major_locator(ticker.MaxNLocator(10)) #use maximum of 8 ticks on y-axis
238    plt.tight_layout()
239    plt.show()