camFollowerExample.py
You can view and download this file on Github: camFollowerExample.py
1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2# This is an EXUDYN example
3#
4# Details: Test for ObjectContactCurveCircles as Cam-follower
5# We can either Cam with a curve (here; more smooth) and follower with circles, or Cam with circles and follower with the curve
6#
7# Author: Johannes Gerstmayr
8# Date: 2025-05-11
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#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13import exudyn as exu
14from exudyn.utilities import *
15import exudyn.graphics as graphics
16import numpy as np
17from exudyn.beams import CreateReevingCurve
18
19useGraphics = True #without test
20
21SC = exu.SystemContainer()
22mbs = SC.AddSystem()
23
24rDisc = 0.05
25wDisc = 0.02
26rContact = 0.005 #needed for representation of contact points
27lFollower = 0.08
28wFollower = 0.06
29
30oGround = mbs.CreateGround(graphicsDataList=[graphics.CheckerBoard(point=[0.5*lFollower,0,-wFollower], size=0.25)])
31
32contactStiffness = 2e6
33contactDamping = 1e4
34
35#++++++++++++++++++++++++++++++++
36#model Cam
37rCam = 0.7*rDisc
38deltaCam = 0.5*rDisc #center of rCam
39#++++++++++++++++++++++++++++++++
40#create 2D points for contact curve (linear segments)
41
42nMarkers = 2
43
44
45omegaCam=2*pi*4
46pCam = np.array([0,0,0])
47oCam = mbs.CreateRigidBody(
48 referencePosition=pCam,
49 initialAngularVelocity=[0,0,omegaCam],
50 inertia=InertiaCylinder(2800, wDisc, rDisc, axis=2),
51 gravity = [0,-g,0],
52 graphicsDataList=[graphics.Cylinder(pAxis=[0,0,-0.5*wDisc], vAxis=[0,0,wDisc],radius=rDisc, nTiles=64, color=graphics.color.orange),
53 graphics.Cylinder(pAxis=[deltaCam,0,-0.5*wDisc], vAxis=[0,0,wDisc],radius=rCam, nTiles=64, color=graphics.color.orange),
54 graphics.Basis(length=rDisc*1.5)],
55 create2D=True, #not possible here, as COM must be 0 with 2D
56 )
57
58mCam = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oCam, localPosition=[0,0,0]))
59mbs.CreateCoordinateConstraint(bodyNumbers=[None, oCam], coordinates=[None,0], show=False)
60mbs.CreateCoordinateConstraint(bodyNumbers=[None, oCam], coordinates=[None,1], show=False)
61oCCtorqueCam = mbs.CreateCoordinateConstraint(bodyNumbers=[None, oCam], coordinates=[None,2],
62 velocityLevel=True, offset=omegaCam, show=False)
63sTorque = mbs.AddSensor(SensorObject(objectNumber=oCCtorqueCam, storeInternal=True,
64 outputVariableType=exu.OutputVariableType.Force))
65
66pLocalList = [[0,0,0],[deltaCam,0,0]]
67circlesRadii = [rDisc, rCam]
68circleMarkers = []
69for p in pLocalList:
70 circleMarkers.append(mbs.AddMarker(MarkerBodyRigid(bodyNumber=oCam, localPosition=p)))
71
72#++++++++++++++++++++++++++++++++
73#follower:
74nPoints = 7
75segmentsData = np.zeros((nPoints,4))
76pList = []
77pList.append([-0.5*lFollower+0.1*lFollower, 0.5*wFollower])
78pList.append([-0.5*lFollower, 0.5*wFollower])
79pList.append([-0.5*lFollower, 0.25*wFollower])
80pList.append([-0.5*lFollower, 0.*wFollower])
81pList.append([-0.5*lFollower,-0.25*wFollower])
82pList.append([-0.5*lFollower,-0.5*wFollower])
83pList.append([-0.5*lFollower+0.1*lFollower, -0.5*wFollower])
84segmentsData[:,0:2] = pList
85segmentsData[:,2:4] = np.roll(pList,2) #roll is element wise on rows and columns, therefore 2>shift one row
86
87
88nMarkers = len(circleMarkers)
89
90vFollower = [deltaCam+rCam+0.5*lFollower+0.,0,0]
91oFollower = mbs.CreateRigidBody(referencePosition=pCam+vFollower,
92 inertia=InertiaCuboid(1000, [lFollower,wFollower,wFollower]),
93 gravity = [0,-g,0],
94 graphicsDataList=[graphics.Brick(centerPoint=[-0.4*lFollower,0,0], size=[0.2*lFollower,wFollower,0.4*wFollower],
95 color=graphics.color.dodgerblue, addEdges=True),
96 graphics.Cylinder(pAxis=[-0.3*lFollower,0,0], vAxis=[0.8*lFollower,0,0],
97 radius=0.15*wFollower, addEdges=True,
98 nTiles=32, color=graphics.color.dodgerblue),
99 ],
100 create2D=True, #not possible here, as COM must be 0 with 2D
101 )
102mFollower = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oFollower, localPosition=[0,0,0]))
103sPosFollower = mbs.AddSensor(SensorBody(bodyNumber=oFollower, storeInternal=True,
104 outputVariableType=exu.OutputVariableType.Position))
105
106mbs.CreateCoordinateConstraint(bodyNumbers=[None, oFollower], coordinates=[None,1], show=False)
107mbs.CreateCoordinateConstraint(bodyNumbers=[None, oFollower], coordinates=[None,2], show=False) #rotation
108
109lSpring = 0.02
110mbs.CreateSpringDamper(bodyNumbers=[oGround, oFollower],
111 localPosition0=pCam+vFollower+[0.5*lFollower+lSpring,0,0],
112 localPosition1=[0.5*lFollower,0,0],
113 referenceLength=lSpring*2,
114 stiffness=1000, damping=20, drawSize = 0.4*wFollower)
115
116
117
118#++++++++++++++++++++++++++++++++
119nGenericData = mbs.AddNode(NodeGenericData(initialCoordinates=[-1,0,0]*nPoints,
120 numberOfDataCoordinates=3*nPoints))
121
122mbs.AddObject(ObjectContactCurveCircles(markerNumbers=[mFollower]+circleMarkers,
123 nodeNumber=nGenericData,
124 circlesRadii=circlesRadii,
125 segmentsData=exu.MatrixContainer(segmentsData),
126 contactStiffness=contactStiffness, contactDamping=contactDamping,
127 visualization=VObjectContactCurveCircles(show=False, color=graphics.color.blue)
128 ))
129
130
131
132mbs.Assemble()
133
134stepSize=2e-4
135tEnd = 2
136simulationSettings = exu.SimulationSettings()
137simulationSettings.solutionSettings.writeSolutionToFile = useGraphics
138simulationSettings.solutionSettings.solutionWritePeriod = 0.005
139simulationSettings.solutionSettings.sensorsWritePeriod = stepSize #output interval
140simulationSettings.timeIntegration.numberOfSteps = int(tEnd/stepSize)
141simulationSettings.timeIntegration.endTime = tEnd
142# simulationSettings.timeIntegration.simulateInRealtime = True
143#simulationSettings.timeIntegration.realtimeFactor = 0.5
144# simulationSettings.timeIntegration.discontinuous.iterationTolerance = 1e-2
145# simulationSettings.timeIntegration.discontinuous.useRecommendedStepSize = False
146
147#simulationSettings.linearSolverType = exu.LinearSolverType.EigenSparse
148simulationSettings.timeIntegration.newton.useModifiedNewton = True
149#simulationSettings.timeIntegration.generalizedAlpha.spectralRadius = 1
150
151simulationSettings.timeIntegration.verboseMode = 1
152SC.visualizationSettings.connectors.contactPointsDefaultSize = 0.0005
153SC.visualizationSettings.connectors.showContact = True
154
155SC.visualizationSettings.general.graphicsUpdateInterval = 0.02
156# SC.visualizationSettings.general.drawWorldBasis = True
157SC.visualizationSettings.window.renderWindowSize=[1600,1200]
158SC.visualizationSettings.openGL.multiSampling=4
159#SC.visualizationSettings.openGL.facesTransparent=True
160SC.visualizationSettings.openGL.shadow=0.3
161SC.visualizationSettings.openGL.lineWidth=2
162SC.visualizationSettings.loads.show = False
163
164
165SC.renderer.Start() #start graphics visualization
166SC.renderer.DoIdleTasks() #wait for pressing SPACE bar to continue
167
168mbs.SolveDynamic(simulationSettings)
169
170SC.renderer.DoIdleTasks()#wait for pressing 'Q' to quit
171SC.renderer.Stop() #safely close rendering window!
172
173mbs.PlotSensor(sensorNumbers=[sTorque], closeAll=True)
174mbs.PlotSensor(sensorNumbers=[sPosFollower])
175
176if useGraphics and True:
177 #%%
178 mbs.SolutionViewer()