(testmodels-homogeneoustransformationtest)= # homogeneousTransformationTest.py You can view and download this file on Github: [homogeneousTransformationTest.py](https://github.com/jgerstmayr/EXUDYN/tree/master/python/TestModels/homogeneousTransformationTest.py) ```{code-block} python :linenos: #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # This is an EXUDYN example # # Details: exudyn.HT, the homogeneous transformation of Exudyn's C++ core (#2780), against the 4x4 numpy matrices # of exudyn.rigidBodyUtilities: for random rotations and translations, the composition H1*H2, the # transformed point H*v, the inverse, the 4x4 matrix in both directions, and the transformations set # without rotation (identity, SetTranslation), whose products skip the rotation. The output variable # HomogeneousTransformation of a node, a body point, a marker and a sensor: an exu.HT of the rotation matrix # and the position; a sensor stores its 16 values row by row, exu.HT(values). # # Author: Johannes Gerstmayr # Date: 2026-10-02 # # 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. # #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ import exudyn as exu from exudyn.utilities import * #includes itemInterface and rigidBodyUtilities import numpy as np testIsActive = exu.sys.get('testIsActive', False) rng = np.random.default_rng(1) errors = [] total = 0. for i in range(20): A1 = RotXYZ2RotationMatrix(rng.standard_normal(3)) A2 = RotXYZ2RotationMatrix(rng.standard_normal(3)) p1 = rng.standard_normal(3) p2 = rng.standard_normal(3) v = rng.standard_normal(3) H1 = exu.HT(rotation=A1, translation=p1) H2 = exu.HT(rotation=A2, translation=p2) T1 = HomogeneousTransformation(A1, p1) #4x4 numpy matrices T2 = HomogeneousTransformation(A2, p2) errors += [np.abs((H1*H2).HT44() - T1 @ T2).max(), #composition np.abs(H1*v - (T1 @ np.append(v, 1))[0:3]).max(), #transformed point np.abs(H1.Inverse().HT44() - InverseHT(T1)).max(), #inverse np.abs(exu.HT(T1).HT44() - T1).max(), #from and to 4x4 np.abs(H1.RotateVectorTransposed(H1.RotateVector(v)) - v).max()] total += np.abs((H1*H2).HT44()).sum() #transformations without rotation: the flag, and the same results as with a unit matrix HT0 = exu.HT() Htranslation = exu.HT(translation=[1, 2, 3]) Hrotation = exu.HT(rotation=RotationMatrixZ(0.3)) exu.Print('without rotation:', HT0.HasNoRotation(), Htranslation.HasNoRotation(), Hrotation.HasNoRotation(), (Htranslation*HT0).HasNoRotation(), (Htranslation*Hrotation).HasNoRotation()) errors += [np.abs((Htranslation*Hrotation).HT44() - HTtranslate([1, 2, 3]) @ HTrotateZ(0.3)).max(), np.abs((Hrotation*Htranslation).HT44() - HTrotateZ(0.3) @ HTtranslate([1, 2, 3])).max(), np.abs(Htranslation.Inverse().HT44() - HTtranslate([-1, -2, -3])).max()] flags = [HT0.HasNoRotation(), Htranslation.HasNoRotation(), not Hrotation.HasNoRotation(), (Htranslation*HT0).HasNoRotation(), not (Htranslation*Hrotation).HasNoRotation()] #the output variable HomogeneousTransformation of a rotating rigid body, after a few steps SC = exu.SystemContainer() mbs = SC.AddSystem() body = mbs.CreateRigidBody(inertia=InertiaCuboid(1000, [0.1, 0.2, 0.3]), referencePosition=[1, 2, 3], referenceRotationMatrix=RotationMatrixZ(0.4), initialAngularVelocity=[0.3, 0.2, 1], initialVelocity=[0.1, 0, 0], returnDict=True) pLocal = [0.1, 0.05, 0] marker = mbs.AddMarker(MarkerBodyRigid(bodyNumber=body['bodyNumber'], localPosition=pLocal)) OVHT = exu.OutputVariableType.HomogeneousTransformation sensor = mbs.AddSensor(SensorBody(bodyNumber=body['bodyNumber'], localPosition=pLocal, outputVariableType=OVHT, storeInternal=True)) mbs.Assemble() simulationSettings = exu.SimulationSettings() simulationSettings.timeIntegration.newton.useModifiedNewton = False #Just for the test; modified Newton is usually faster simulationSettings.timeIntegration.numberOfSteps = 100 simulationSettings.timeIntegration.endTime = 0.5 simulationSettings.solution.file.write = False mbs.SolveDynamic(simulationSettings) A = mbs.GetObjectOutputBody(body['bodyNumber'], exu.OutputVariableType.RotationMatrix, localPosition=pLocal).reshape(3, 3) p = mbs.GetObjectOutputBody(body['bodyNumber'], exu.OutputVariableType.Position, localPosition=pLocal) HTbody = mbs.GetObjectOutputBody(body['bodyNumber'], OVHT, localPosition=pLocal) #an exu.HT errors += [np.abs(HTbody.HT44() - HomogeneousTransformation(A, p)).max(), np.abs(mbs.GetMarkerOutput(marker, OVHT).HT44() - HTbody.HT44()).max(), np.abs(exu.HT(mbs.GetSensorValues(sensor)).HT44() - HTbody.HT44()).max(), np.abs(mbs.GetNodeOutput(body['nodeNumber'], OVHT) * pLocal - p).max()] total += np.abs(HTbody.HT44()).sum() exu.Print('largest difference to rigidBodyUtilities:', max(errors), ', flags as expected:', all(flags)) testResult = total + (max(errors) < 1e-12) + sum(flags) exu.Print('solution of homogeneousTransformationTest=', testResult) exu.sys['testResult'] = testResult ```