Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-15 09:25:53

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Alignment.hpp"
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/Geometry/GeometryContext.hpp"
0015 #include "Acts/Surfaces/PlaneSurface.hpp"
0016 #include "Acts/Surfaces/RectangleBounds.hpp"
0017 #include "Acts/Surfaces/Surface.hpp"
0018 #include "Acts/Surfaces/detail/AlignmentHelper.hpp"
0019 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0020 
0021 #include <algorithm>
0022 #include <cmath>
0023 #include <numbers>
0024 #include <utility>
0025 
0026 using namespace Acts;
0027 
0028 namespace ActsTests {
0029 
0030 BOOST_AUTO_TEST_SUITE(SurfacesSuite)
0031 
0032 /// Test for rotation matrix and calculation of derivative of rotated x/y/z axis
0033 /// w.r.t. rotation parameters
0034 BOOST_AUTO_TEST_CASE(alignment_helper_test) {
0035   // (a) Test with non-identity rotation matrix
0036   // Rotation angle parameters
0037   const double alpha = std::numbers::pi;
0038   const double beta = 0.;
0039   const double gamma = std::numbers::pi / 2.;
0040   // rotation around x axis
0041   AngleAxis3 rotX(alpha, Vector3(1., 0., 0.));
0042   // rotation around y axis
0043   AngleAxis3 rotY(beta, Vector3(0., 1., 0.));
0044   // rotation around z axis
0045   AngleAxis3 rotZ(gamma, Vector3(0., 0., 1.));
0046   double sz = std::sin(gamma);
0047   double cz = std::cos(gamma);
0048   double sy = std::sin(beta);
0049   double cy = std::cos(beta);
0050   double sx = std::sin(alpha);
0051   double cx = std::cos(alpha);
0052 
0053   // Calculate the expected rotation matrix for rotZ * rotY * rotX,
0054   // (i.e. first rotation around x axis, then y axis, last z axis):
0055   // [ cz*cy  cz*sy*sx-cx*sz  sz*sx+cz*cx*sy ]
0056   // [ cy*sz  cz*cx+sz*sy*sx  cx*sz*sy-cz*sx ]
0057   // [ -sy    cy*sx           cy*cx          ]
0058   RotationMatrix3 expRot = RotationMatrix3::Zero();
0059   expRot.col(0) = Vector3(cz * cy, cy * sz, -sy);
0060   expRot.col(1) =
0061       Vector3(cz * sy * sx - cx * sz, cz * cx + sz * sy * sx, cy * sx);
0062   expRot.col(2) =
0063       Vector3(sz * sx + cz * cx * sy, cx * sz * sy - cz * sx, cy * cx);
0064 
0065   // Calculate the expected derivative of local x axis to its rotation
0066   RotationMatrix3 expRotToXAxis = RotationMatrix3::Zero();
0067   expRotToXAxis.col(0) = expRot * Vector3(0, 0, 0);
0068   expRotToXAxis.col(1) = expRot * Vector3(0, 0, -1);
0069   expRotToXAxis.col(2) = expRot * Vector3(0, 1, 0);
0070 
0071   // Calculate the expected derivative of local y axis to its rotation
0072   RotationMatrix3 expRotToYAxis = RotationMatrix3::Zero();
0073   expRotToYAxis.col(0) = expRot * Vector3(0, 0, 1);
0074   expRotToYAxis.col(1) = expRot * Vector3(0, 0, 0);
0075   expRotToYAxis.col(2) = expRot * Vector3(-1, 0, 0);
0076 
0077   // Calculate the expected derivative of local z axis to its rotation
0078   RotationMatrix3 expRotToZAxis = RotationMatrix3::Zero();
0079   expRotToZAxis.col(0) = expRot * Vector3(0, -1, 0);
0080   expRotToZAxis.col(1) = expRot * Vector3(1, 0, 0);
0081   expRotToZAxis.col(2) = expRot * Vector3(0, 0, 0);
0082 
0083   // Construct a transform
0084   Translation3 translation(Vector3(0., 0., 0.));
0085   Transform3 transform(translation);
0086   // Rotation with rotZ * rotY * rotX
0087   transform *= rotZ;
0088   transform *= rotY;
0089   transform *= rotX;
0090   // Get the rotation of the transform
0091   const auto rotation = transform.rotation();
0092 
0093   // Check if the rotation matrix is as expected
0094   CHECK_CLOSE_ABS(rotation, expRot, 1e-15);
0095 
0096   // Call the alignment helper to calculate the derivative of local frame axes
0097   // w.r.t its rotation
0098   const auto& [rotToLocalXAxis, rotToLocalYAxis, rotToLocalZAxis] =
0099       detail::rotationToLocalAxesDerivative(rotation);
0100 
0101   // Check if the derivative for local x axis is as expected
0102   CHECK_CLOSE_ABS(rotToLocalXAxis, expRotToXAxis, 1e-15);
0103 
0104   // Check if the derivative for local y axis is as expected
0105   CHECK_CLOSE_ABS(rotToLocalYAxis, expRotToYAxis, 1e-15);
0106 
0107   // Check if the derivative for local z axis is as expected
0108   CHECK_CLOSE_ABS(rotToLocalZAxis, expRotToZAxis, 1e-15);
0109 
0110   // (b) Test with identity rotation matrix
0111   RotationMatrix3 iRotation = RotationMatrix3::Identity();
0112 
0113   // Call the alignment helper to calculate the derivative of local frame axes
0114   // w.r.t its rotation
0115   const auto& [irotToLocalXAxis, irotToLocalYAxis, irotToLocalZAxis] =
0116       detail::rotationToLocalAxesDerivative(iRotation);
0117 
0118   // The expected derivatives
0119   expRotToXAxis << 0, 0, 0, 0, 0, 1, 0, -1, 0;
0120   expRotToYAxis << 0, 0, -1, 0, 0, 0, 1, 0, 0;
0121   expRotToZAxis << 0, 1, 0, -1, 0, 0, 0, 0, 0;
0122 
0123   // Check if the derivative for local x axis is as expected
0124   CHECK_CLOSE_ABS(irotToLocalXAxis, expRotToXAxis, 1e-15);
0125 
0126   // Check if the derivative for local y axis is as expected
0127   CHECK_CLOSE_ABS(irotToLocalYAxis, expRotToYAxis, 1e-15);
0128 
0129   // Check if the derivative for local z axis is as expected
0130   CHECK_CLOSE_ABS(irotToLocalZAxis, expRotToZAxis, 1e-15);
0131 }
0132 
0133 namespace {
0134 
0135 /// Move an object by local-frame alignment parameters (dt, dw)
0136 Transform3 moveInLocalFrame(const Transform3& transform,
0137                             const AlignmentVector& params) {
0138   Transform3 delta = Transform3::Identity();
0139   delta.linear() = (AngleAxis3(params[eAlignmentRotation2], Vector3::UnitZ()) *
0140                     AngleAxis3(params[eAlignmentRotation1], Vector3::UnitY()) *
0141                     AngleAxis3(params[eAlignmentRotation0], Vector3::UnitX()))
0142                        .toRotationMatrix();
0143   delta.translation() = params.head<3>();
0144   return transform * delta;
0145 }
0146 
0147 /// Local-frame alignment parameters (dt, dw) moving an object from
0148 /// @p nominal to @p moved
0149 AlignmentVector localFrameParameters(const Transform3& nominal,
0150                                      const Transform3& moved) {
0151   const RotationMatrix3 rotation = nominal.rotation();
0152   const AngleAxis3 deltaRotation(rotation.transpose() * moved.rotation());
0153   AlignmentVector params;
0154   params.head<3>() =
0155       rotation.transpose() * (moved.translation() - nominal.translation());
0156   params.tail<3>() = deltaRotation.angle() * deltaRotation.axis();
0157   return params;
0158 }
0159 
0160 /// A composite structure and one of its components, both tilted and away from
0161 /// the global origin
0162 struct CompositeFixture {
0163   Transform3 composite = Translation3(10., -20., 300.) *
0164                          AngleAxis3(0.3, Vector3(1., 2., 3.).normalized());
0165   Transform3 component = composite * Translation3(50., 30., -40.) *
0166                          AngleAxis3(-1.1, Vector3(-2., 1., 0.5).normalized());
0167 
0168   /// The component transform after moving the composite as a rigid body
0169   Transform3 movedComponent(const AlignmentVector& compositeParams) const {
0170     return moveInLocalFrame(composite, compositeParams) * composite.inverse() *
0171            component;
0172   }
0173 };
0174 
0175 }  // namespace
0176 
0177 /// Check the composite Jacobian against the finite-difference rigid motion of
0178 /// a component, in local-frame and ACTS parameters
0179 BOOST_AUTO_TEST_CASE(composite_jacobian_rigid_motion) {
0180   CompositeFixture fix;
0181   const AlignmentMatrix jacobian =
0182       detail::compositeToComponentJacobian(fix.composite, fix.component);
0183   const AlignmentMatrix jacobianActs =
0184       detail::localFrameToAlignmentParametersJacobian(fix.component) * jacobian;
0185 
0186   const double step = 1e-5;
0187   for (std::size_t iPar = 0; iPar < eAlignmentSize; ++iPar) {
0188     AlignmentVector delta = AlignmentVector::Zero();
0189     delta[iPar] = step;
0190     const Transform3 plus = fix.movedComponent(delta);
0191     const Transform3 minus = fix.movedComponent(-delta);
0192 
0193     const AlignmentVector numLocal =
0194         (localFrameParameters(fix.component, plus) -
0195          localFrameParameters(fix.component, minus)) /
0196         (2. * step);
0197     CHECK_CLOSE_ABS(numLocal, jacobian.col(iPar), 1e-6);
0198 
0199     // ACTS parameters are the local-frame parameters, so this matches numLocal.
0200     CHECK_CLOSE_ABS(numLocal, jacobianActs.col(iPar), 1e-6);
0201   }
0202 }
0203 
0204 /// Check the chained derivative of the bound local position on a component
0205 /// plane w.r.t. the composite parameters, against moving the composite and
0206 /// intersecting a straight track with the moved plane
0207 BOOST_AUTO_TEST_CASE(composite_jacobian_plane_derivative) {
0208   const auto gctx = GeometryContext::dangerouslyDefaultConstruct();
0209   CompositeFixture fix;
0210   auto bounds = std::make_shared<const RectangleBounds>(1000., 1000.);
0211   auto plane = Surface::makeShared<PlaneSurface>(fix.component, bounds);
0212 
0213   // straight track crossing the plane at an angle
0214   const Vector3 direction =
0215       (fix.component.rotation() * Vector3(0.3, -0.2, 1.)).normalized();
0216   const Vector3 position =
0217       plane->localToGlobal(gctx, Vector2(3., -7.), direction);
0218 
0219   FreeVector pathDerivative = FreeVector::Zero();
0220   pathDerivative.head<3>() = direction;
0221   const AlignmentToBoundMatrix alignToBound = plane->alignmentToBoundDerivative(
0222       gctx, position, direction, pathDerivative);
0223   const Matrix<2, eAlignmentSize> expected =
0224       alignToBound.topRows<2>() *
0225       detail::localFrameToAlignmentParametersJacobian(fix.component) *
0226       detail::compositeToComponentJacobian(fix.composite, fix.component);
0227 
0228   auto boundLocal = [&](const AlignmentVector& compositeParams) {
0229     const Transform3 moved = fix.movedComponent(compositeParams);
0230     auto movedPlane = Surface::makeShared<PlaneSurface>(moved, bounds);
0231     const Vector3 normal = moved.rotation().col(2);
0232     const double path =
0233         normal.dot(moved.translation() - position) / normal.dot(direction);
0234     return movedPlane
0235         ->globalToLocal(gctx, position + path * direction, direction)
0236         .value();
0237   };
0238 
0239   const double step = 1e-5;
0240   for (std::size_t iPar = 0; iPar < eAlignmentSize; ++iPar) {
0241     AlignmentVector delta = AlignmentVector::Zero();
0242     delta[iPar] = step;
0243     const Vector2 numerical =
0244         (boundLocal(delta) - boundLocal(-delta)) / (2. * step);
0245     CHECK_CLOSE_ABS(numerical, expected.col(iPar), 1e-6);
0246   }
0247 }
0248 
0249 BOOST_AUTO_TEST_SUITE_END()
0250 
0251 }  // namespace ActsTests