inactiveConnectorForceTest.py
You can view and download this file on Github: inactiveConnectorForceTest.py
1#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2# This is an EXUDYN example
3#
4# Details: An inactive connector (activeConnector = False) adds no force, and reports none (#984):
5# each penalty connector and contact between the ground and a rigid body that is displaced,
6# rotated and moving, built once inactive - its Force, ForceLocal, Torque and TorqueLocal
7# output must be zero - and once active, where they are not.
8#
9# Author: Johannes Gerstmayr
10# Date: 2026-10-05
11#
12# 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.
13#
14#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
15
16import exudyn as exu
17from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities
18
19import numpy as np
20
21testIsActive = exu.sys.get('testIsActive', False)
22
23forceTypes = [exu.OutputVariableType.Force, exu.OutputVariableType.ForceLocal,
24 exu.OutputVariableType.Torque, exu.OutputVariableType.TorqueLocal]
25
26
27def DataNode(mbs, n):
28 #the first data coordinate of the contacts is the gap of the last step: negative, in contact
29 return mbs.AddNode(NodeGenericData(numberOfDataCoordinates=n, initialCoordinates=[-0.1]+[0]*(n-1)))
30
31
32#each connector between a ground marker and a body marker (rigid or coordinate), with a force where it is active
33connectors = {
34 'SpringDamper': lambda mbs, mG, mB, cG, cB, active: mbs.AddObject(SpringDamper(markerNumbers=[mG, mB],
35 stiffness=100, damping=1, referenceLength=1, activeConnector=active)),
36 'CartesianSpringDamper': lambda mbs, mG, mB, cG, cB, active: mbs.AddObject(CartesianSpringDamper(
37 markerNumbers=[mG, mB], stiffness=[100]*3, damping=[1]*3, activeConnector=active)),
38 'RigidBodySpringDamper': lambda mbs, mG, mB, cG, cB, active: mbs.AddObject(RigidBodySpringDamper(
39 markerNumbers=[mG, mB], stiffness=100*np.eye(6), damping=np.eye(6), activeConnector=active)),
40 'TorsionalSpringDamper': lambda mbs, mG, mB, cG, cB, active: mbs.AddObject(TorsionalSpringDamper(
41 markerNumbers=[mG, mB], stiffness=100, damping=1, activeConnector=active)),
42 'LinearSpringDamper': lambda mbs, mG, mB, cG, cB, active: mbs.AddObject(LinearSpringDamper(
43 markerNumbers=[mG, mB], stiffness=100, damping=1, activeConnector=active)),
44 'CoordinateSpringDamper': lambda mbs, mG, mB, cG, cB, active: mbs.AddObject(CoordinateSpringDamper(
45 markerNumbers=[cG, cB], stiffness=100, damping=1, activeConnector=active)),
46 'ConnectorGravity': lambda mbs, mG, mB, cG, cB, active: mbs.AddObject(ObjectConnectorGravity(
47 markerNumbers=[mG, mB], mass0=1e10, mass1=1, activeConnector=active)),
48 'ContactSphereSphere': lambda mbs, mG, mB, cG, cB, active: mbs.AddObject(ObjectContactSphereSphere(
49 markerNumbers=[mG, mB], nodeNumber=DataNode(mbs, 4), spheresRadii=[1, 1], contactStiffness=100,
50 contactDamping=1, dynamicFriction=0.2, activeConnector=active)),
51 'ContactSphereTriangle': lambda mbs, mG, mB, cG, cB, active: mbs.AddObject(ObjectContactSphereTriangle(
52 markerNumbers=[mB, mG], nodeNumber=DataNode(mbs, 4), sphereRadius=1,
53 trianglePoints=exu.Vector3DList([[0, -2, 0], [3, -2, 0], [0, 2, 0]]), contactStiffness=100,
54 contactDamping=1, dynamicFriction=0.2, activeConnector=active)),
55 }
56
57
58def ForceOutputs(build, active):
59 """the norms of the force and torque outputs a connector has, as a dict"""
60 SC = exu.SystemContainer()
61 mbs = SC.AddSystem()
62 oGround = mbs.AddObject(ObjectGround())
63 node = mbs.AddNode(NodeRigidBodyEP(referenceCoordinates=[1.2, 0.1, -0.05] + list(RotXYZ2EulerParameters([0.1, 0.2, 0.3])),
64 initialVelocities=[0.3, 0.2, 0.1, 0, 0, 0, 0]))
65 body = mbs.AddObject(ObjectRigidBody(nodeNumber=node, mass=1, inertia=[1, 1, 1, 0, 0, 0]))
66 mG = mbs.AddMarker(MarkerBodyRigid(bodyNumber=oGround))
67 mB = mbs.AddMarker(MarkerBodyRigid(bodyNumber=body))
68 cG = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber=mbs.AddNode(NodePointGround()), coordinate=0))
69 cB = mbs.AddMarker(MarkerNodeCoordinate(nodeNumber=node, coordinate=0))
70 connector = build(mbs, mG, mB, cG, cB, active)
71 mbs.Assemble()
72 outputs = {}
73 for variableType in forceTypes:
74 try:
75 outputs[variableType] = np.linalg.norm(mbs.GetObjectOutput(connector, variableType))
76 except Exception:
77 pass #the connector does not have this output variable
78 return outputs
79
80
81testResult = 0
82for (name, build) in connectors.items():
83 inactive = ForceOutputs(build, False)
84 active = ForceOutputs(build, True)
85 exu.Print(name + ': inactive', sum(inactive.values()), ', active', sum(active.values()))
86 testResult += 1000*sum(inactive.values()) + sum(active.values()) #an inactive force spoils the result
87
88exu.Print('solution of inactiveConnectorForceTest=', testResult)
89exu.sys['testResult'] = testResult