rotationMarkerDeprecationTest.py
You can view and download this file on Github: rotationMarkerDeprecationTest.py
1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2# This is an EXUDYN example
3#
4# Details: The rotation of a joint or connector frame is given to its markers, as localHT (#2745):
5# a body on a GenericJoint and a body on a RigidBodySpringDamper, each turned once by
6# rotationMarker0/1 and once by the localHT of the markers, move the same; the
7# RigidBodySpringDamper applies rotationMarker0 on the same side as all joints (#2801).
8# rotationMarker0/1 are deprecated: setting one other than the unit matrix warns where it is
9# added, once per session and name - every time with exu.special.deprecations.warnOnce = False -
10# and every use is counted in exu.sys['deprecationUse']['items'] (#2804, #2806). GetJointArgs
11# with a rotation for an existing marker uses no deprecated parameter.
12#
13# Author: Johannes Gerstmayr
14# Date: 2026-10-03
15#
16# 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.
17#
18#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
19
20import exudyn as exu
21from exudyn.utilities import *
22import numpy as np
23import warnings
24import os
25
26testIsActive = exu.sys.get('testIsActive', False)
27
28A0 = RotationMatrixX(0.3) @ RotationMatrixY(0.5) #the joint frame on the ground
29A1 = RotationMatrixZ(-0.4) @ RotationMatrixX(0.2) #the joint frame on the body
30Ab = A0 @ A1.T #the body, turned so that both joint frames agree in the reference configuration
31pb = -Ab @ np.array([-0.2, 0, 0]) #and its marker at the origin
32
33def ItemUses():
34 """all recorded uses of deprecated item parameters"""
35 return sum(exu.sys.get('deprecationUse', {}).get('items', {}).values())
36
37def Model(mbs):
38 oGround = mbs.AddObject(ObjectGround())
39 inertia = InertiaCuboid(density=1000, sideLengths=[0.4, 0.1, 0.1])
40 node = mbs.AddNode(NodeRigidBodyEP(referenceCoordinates=list(pb) + list(RotationMatrix2EulerParameters(Ab)),
41 initialVelocities=[0]*7))
42 body = mbs.AddObject(ObjectRigidBody(nodeNumber=node, mass=inertia.Mass(), inertia=inertia.GetInertia6D()))
43 return (oGround, node, body)
44
45def Simulate(useLocalHT, connector):
46 SC = exu.SystemContainer()
47 mbs = SC.AddSystem()
48 (oGround, node, body) = Model(mbs)
49 if useLocalHT:
50 m0 = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oGround, localHT=exu.HT(rotation=A0)))
51 m1 = mbs.AddMarker(MarkerBodyRigid(bodyNumber=body, localHT=exu.HT(rotation=A1, translation=[-0.2, 0, 0])))
52 rotations = {}
53 else:
54 m0 = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oGround, localPosition=[0, 0, 0]))
55 m1 = mbs.AddMarker(MarkerBodyRigid(bodyNumber=body, localPosition=[-0.2, 0, 0]))
56 rotations = {'rotationMarker0': A0, 'rotationMarker1': A1}
57 with warnings.catch_warnings():
58 warnings.simplefilter('ignore', DeprecationWarning)
59 if connector:
60 k = 2000.
61 mbs.AddObject(RigidBodySpringDamper(markerNumbers=[m0, m1], stiffness=np.diag([k, 2*k, 3*k, 0.1*k, 0.2*k, 0.3*k]),
62 damping=np.diag([1, 1, 1, 0.1, 0.1, 0.1]), **rotations))
63 else:
64 mbs.AddObject(GenericJoint(markerNumbers=[m0, m1], constrainedAxes=[1, 1, 1, 1, 1, 0], **rotations))
65 mbs.AddLoad(LoadForceVector(markerNumber=mbs.AddMarker(MarkerBodyPosition(bodyNumber=body, localPosition=[0.2, 0, 0])),
66 loadVector=[0, -10, 5]))
67 mbs.Assemble()
68
69 simulationSettings = exu.SimulationSettings()
70 simulationSettings.timeIntegration.newton.useModifiedNewton = False #Just for the test; modified Newton is usually faster
71 simulationSettings.timeIntegration.numberOfSteps = 200
72 simulationSettings.timeIntegration.endTime = 0.2
73 simulationSettings.timeIntegration.verboseMode = 0
74 simulationSettings.solution.file.write = False
75 mbs.SolveDynamic(simulationSettings)
76 return np.array(mbs.GetNodeOutput(node, exu.OutputVariableType.Coordinates))
77
78errors = 0
79u = 0.
80#the same motion with the rotation in the markers and in the deprecated parameters; only the latter is recorded
81for connector in [False, True]:
82 used = ItemUses()
83 qLocalHT = Simulate(True, connector)
84 if ItemUses() != used:
85 errors += 1
86 qRotationMarker = Simulate(False, connector)
87 if ItemUses() != used + 2: #rotationMarker0 and rotationMarker1
88 errors += 1
89 exu.Print('connector' if connector else 'joint', ': difference localHT - rotationMarker =', np.linalg.norm(qLocalHT - qRotationMarker))
90 if np.linalg.norm(qLocalHT - qRotationMarker) > 1e-10:
91 errors += 1
92 u += np.sum(qLocalHT)
93
94#the warning: at the line that adds the item, once per session and name, or on every use
95deprecations = exu.special.deprecations
96warnOnceStored = deprecations.warnOnce
97SC = exu.SystemContainer()
98mbs = SC.AddSystem()
99(oGround, node, body) = Model(mbs)
100m0 = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oGround))
101m1 = mbs.AddMarker(MarkerBodyRigid(bodyNumber=body, localPosition=[-0.2, 0, 0]))
102nWarnings = []
103for warnOnce in [True, False]:
104 deprecations.warnOnce = warnOnce
105 deprecations.Reset() #as if the session had just started
106 with warnings.catch_warnings(record=True) as caught:
107 warnings.simplefilter('always')
108 for i in range(3):
109 mbs.AddObject(GenericJoint(markerNumbers=[m0, m1], constrainedAxes=[0]*6, rotationMarker0=A0))
110 found = [entry for entry in caught if issubclass(entry.category, DeprecationWarning)]
111 nWarnings.append(len(found))
112 if any('ObjectJointGeneric: the parameter rotationMarker0' not in str(entry.message)
113 or os.sep + 'exudyn' + os.sep in entry.filename for entry in found):
114 errors += 1 #the message names item and parameter, the warning points at this script, not into Exudyn
115deprecations.warnOnce = warnOnceStored
116exu.Print('warnings, once per session and on every use:', nWarnings)
117if nWarnings != [1, 3]:
118 errors += 1
119
120#GetJointArgs turns a copy of the existing marker instead of passing rotationMarker0 on
121used = ItemUses()
122args = GetJointArgs(mbs, markerNumber0=m0, rotationMarker0=A0, bodyNumber1=body)
123mbs.AddObject(RevoluteJointZ(**args))
124if ItemUses() != used or 'rotationMarker0' in args:
125 errors += 1
126
127exu.Print('rotationMarkerDeprecationTest: errors', errors)
128u += errors
129exu.Print('solution of rotationMarkerDeprecationTest=', u)
130
131exu.sys['testResult'] = u