File indexing completed on 2026-11-15 09:25:53
0001
0002
0003
0004
0005
0006
0007
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
0033
0034 BOOST_AUTO_TEST_CASE(alignment_helper_test) {
0035
0036
0037 const double alpha = std::numbers::pi;
0038 const double beta = 0.;
0039 const double gamma = std::numbers::pi / 2.;
0040
0041 AngleAxis3 rotX(alpha, Vector3(1., 0., 0.));
0042
0043 AngleAxis3 rotY(beta, Vector3(0., 1., 0.));
0044
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
0054
0055
0056
0057
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
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
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
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
0084 Translation3 translation(Vector3(0., 0., 0.));
0085 Transform3 transform(translation);
0086
0087 transform *= rotZ;
0088 transform *= rotY;
0089 transform *= rotX;
0090
0091 const auto rotation = transform.rotation();
0092
0093
0094 CHECK_CLOSE_ABS(rotation, expRot, 1e-15);
0095
0096
0097
0098 const auto& [rotToLocalXAxis, rotToLocalYAxis, rotToLocalZAxis] =
0099 detail::rotationToLocalAxesDerivative(rotation);
0100
0101
0102 CHECK_CLOSE_ABS(rotToLocalXAxis, expRotToXAxis, 1e-15);
0103
0104
0105 CHECK_CLOSE_ABS(rotToLocalYAxis, expRotToYAxis, 1e-15);
0106
0107
0108 CHECK_CLOSE_ABS(rotToLocalZAxis, expRotToZAxis, 1e-15);
0109
0110
0111 RotationMatrix3 iRotation = RotationMatrix3::Identity();
0112
0113
0114
0115 const auto& [irotToLocalXAxis, irotToLocalYAxis, irotToLocalZAxis] =
0116 detail::rotationToLocalAxesDerivative(iRotation);
0117
0118
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
0124 CHECK_CLOSE_ABS(irotToLocalXAxis, expRotToXAxis, 1e-15);
0125
0126
0127 CHECK_CLOSE_ABS(irotToLocalYAxis, expRotToYAxis, 1e-15);
0128
0129
0130 CHECK_CLOSE_ABS(irotToLocalZAxis, expRotToZAxis, 1e-15);
0131 }
0132
0133 namespace {
0134
0135
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
0148
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
0161
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
0169 Transform3 movedComponent(const AlignmentVector& compositeParams) const {
0170 return moveInLocalFrame(composite, compositeParams) * composite.inverse() *
0171 component;
0172 }
0173 };
0174
0175 }
0176
0177
0178
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
0200 CHECK_CLOSE_ABS(numLocal, jacobianActs.col(iPar), 1e-6);
0201 }
0202 }
0203
0204
0205
0206
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
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 }