|
|
|||
File indexing completed on 2026-08-31 08:19:22
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 #pragma once 0010 0011 #include "Acts/Geometry/GeometryIdentifier.hpp" 0012 #include "Acts/Geometry/Layer.hpp" 0013 #include "Acts/Geometry/TrackingGeometry.hpp" 0014 #include "Acts/Geometry/TrackingVolume.hpp" 0015 #include "Acts/Navigation/INavigationPolicy.hpp" 0016 #include "Acts/Navigation/NavigationStream.hpp" 0017 #include "Acts/Propagator/NavigationTarget.hpp" 0018 #include "Acts/Propagator/NavigatorOptions.hpp" 0019 #include "Acts/Propagator/NavigatorStatistics.hpp" 0020 #include "Acts/Surfaces/BoundaryTolerance.hpp" 0021 #include "Acts/Surfaces/Surface.hpp" 0022 #include "Acts/Utilities/Logger.hpp" 0023 #include "Acts/Utilities/Result.hpp" 0024 0025 #include <limits> 0026 #include <optional> 0027 #include <string> 0028 0029 #include <boost/container/small_vector.hpp> 0030 0031 namespace Acts { 0032 0033 /// @brief The navigation options for the tracking geometry 0034 /// 0035 /// @tparam object_t Type of the object for navigation to check against 0036 template <typename object_t> 0037 struct NavigationOptions final { 0038 /// The boundary check directive 0039 BoundaryTolerance boundaryTolerance = BoundaryTolerance::None(); 0040 0041 // How to resolve the geometry 0042 /// Always look for sensitive 0043 bool resolveSensitive = true; 0044 /// Always look for material 0045 bool resolveMaterial = true; 0046 /// always look for passive 0047 bool resolvePassive = false; 0048 0049 /// Hint for start object 0050 const object_t* startObject = nullptr; 0051 /// Hint for end object 0052 const object_t* endObject = nullptr; 0053 0054 /// External surface identifier for which the boundary check is ignored 0055 std::vector<GeometryIdentifier> externalSurfaces = {}; 0056 0057 /// The minimum distance for a surface to be considered 0058 double nearLimit = 0; 0059 /// The maximum distance for a surface to be considered 0060 double farLimit = std::numeric_limits<double>::max(); 0061 }; 0062 0063 /// @brief Steers the propagation through the geometry by providing the next 0064 /// surface to be targeted. 0065 /// 0066 /// The Navigator is part of the propagation and responsible for steering 0067 /// the surface sequence to encounter all the relevant surfaces which are 0068 /// intersected by the trajectory. 0069 /// 0070 /// The current navigation stage is cached in the state struct and updated 0071 /// when necessary. If any surface in the extrapolation flow is hit, it is 0072 /// set to the navigation state, such that other actors can deal with it. 0073 /// 0074 /// The current target surface is referenced by an index which points into 0075 /// the navigation candidates. The navigation candidates are ordered by the 0076 /// path length to the surface. If a surface is hit, the 0077 /// `state.currentSurface` pointer is set. This actors to observe 0078 /// that we are on a surface. 0079 /// 0080 class Navigator final { 0081 public: 0082 /// Type alias for navigation surface candidates container 0083 using NavigationSurfaces = 0084 boost::container::small_vector<NavigationTarget, 10>; 0085 0086 /// Type alias for navigation layer candidates container 0087 using NavigationLayers = boost::container::small_vector<NavigationTarget, 10>; 0088 0089 /// Type alias for navigation boundary candidates container 0090 using NavigationBoundaries = 0091 boost::container::small_vector<NavigationTarget, 4>; 0092 0093 /// Type alias for geometry version enumeration 0094 using GeometryVersion = TrackingGeometry::GeometryVersion; 0095 0096 /// The navigation stage 0097 enum struct Stage : int { 0098 initial = 0, 0099 surfaceTarget = 1, 0100 layerTarget = 2, 0101 boundaryTarget = 3, 0102 }; 0103 0104 /// The navigator configuration 0105 struct Config { 0106 /// Tracking Geometry for this Navigator 0107 std::shared_ptr<const TrackingGeometry> trackingGeometry{nullptr}; 0108 0109 /// stop at every sensitive surface (whether it has material or not) 0110 bool resolveSensitive = true; 0111 /// stop at every material surface (whether it is passive or not) 0112 bool resolveMaterial = true; 0113 /// stop at every surface regardless what it is 0114 bool resolvePassive = false; 0115 }; 0116 0117 /// The navigator options 0118 struct Options : public NavigatorPlainOptions { 0119 /// Constructor with geometry context 0120 /// @param gctx The geometry context for the navigation 0121 explicit Options(const GeometryContext& gctx) 0122 : NavigatorPlainOptions(gctx) {} 0123 0124 /// Set the plain navigation options 0125 /// @param options The plain navigator options to set 0126 void setPlainOptions(const NavigatorPlainOptions& options) { 0127 static_cast<NavigatorPlainOptions&>(*this) = options; 0128 } 0129 }; 0130 0131 /// @brief Nested State struct 0132 /// 0133 /// It acts as an internal state which is created for every propagation and 0134 /// meant to keep thread-local navigation information. 0135 struct State { 0136 /// Constructor with navigation options 0137 /// @param options_ The navigation options for this state 0138 explicit State(const Options& options_) : options(options_) {} 0139 0140 /// Navigation options configuration 0141 Options options; 0142 0143 /// Management of policy state allocation and deallocation 0144 NavigationPolicyStateManager policyStateManager; 0145 0146 /// Whether the current volume's policy state carries no validity 0147 /// constraint. Sourced from INavigationPolicy::isStateless() (probed once 0148 /// at construction, fixed thereafter) and cached at each volume transition, 0149 /// so the per-step checks read this local bool instead of chasing the 0150 /// policy pointer or re-deriving defaultness from the type-erased state. 0151 bool policyStateIsDefault = true; 0152 0153 // Navigation on surface level 0154 /// the vector of navigation surfaces to work through 0155 NavigationSurfaces navSurfaces = {}; 0156 /// the current surface index of the navigation state 0157 std::optional<std::size_t> navSurfaceIndex; 0158 0159 // Navigation on layer level 0160 /// the vector of navigation layers to work through 0161 NavigationLayers navLayers = {}; 0162 /// the current layer index of the navigation state 0163 std::optional<std::size_t> navLayerIndex; 0164 0165 // Navigation on volume level 0166 /// the vector of boundary surfaces to work through 0167 NavigationBoundaries navBoundaries = {}; 0168 /// the current boundary index of the navigation state 0169 std::optional<std::size_t> navBoundaryIndex; 0170 0171 // Navigation candidates (portals and surfaces together). The candidates 0172 // live in `stream` (sorted by path length); the navigator works through 0173 // them by index without copying them out. 0174 /// the current candidate index into the stream's candidates 0175 std::optional<std::size_t> navCandidateIndex; 0176 /// far limit applied to the stream candidates, set during candidate 0177 /// resolution (options.farLimit, or tightened to the last portal when 0178 /// free candidates were appended without a selector) 0179 double navCandidatesFarLimit = std::numeric_limits<double>::max(); 0180 0181 /// Free candidates not part of the tracking geometry. 0182 // They are stored as a pair of surface pointer 0183 /// and a boolean indicating whether the surface has already been 0184 /// reached during propagation 0185 std::vector<std::pair<const Surface*, bool>> freeCandidates{}; 0186 0187 /// Get reference to current navigation surface 0188 /// @return Reference to current navigation target 0189 NavigationTarget& navSurface() { 0190 return navSurfaces.at(navSurfaceIndex.value()); 0191 } 0192 0193 /// Get reference to current navigation layer 0194 /// @return Reference to current layer intersection 0195 NavigationTarget& navLayer() { return navLayers.at(navLayerIndex.value()); } 0196 0197 /// Get reference to current navigation boundary 0198 /// @return Reference to current boundary intersection 0199 NavigationTarget& navBoundary() { 0200 return navBoundaries.at(navBoundaryIndex.value()); 0201 } 0202 0203 /// Get reference to current navigation candidate 0204 /// @return Reference to current boundary intersection 0205 NavigationTarget& navCandidate() { 0206 return stream.candidates().at(navCandidateIndex.value()); 0207 } 0208 0209 /// Volume where the navigation started 0210 const TrackingVolume* startVolume = nullptr; 0211 /// Layer where the navigation started 0212 const Layer* startLayer = nullptr; 0213 /// Surface where the navigation started 0214 const Surface* startSurface = nullptr; 0215 /// Current volume during navigation 0216 const TrackingVolume* currentVolume = nullptr; 0217 /// Current layer during navigation 0218 const Layer* currentLayer = nullptr; 0219 /// Current surface during navigation 0220 const Surface* currentSurface = nullptr; 0221 /// Target surface for navigation 0222 const Surface* targetSurface = nullptr; 0223 0224 /// Flag to break navigation loop 0225 bool navigationBreak = false; 0226 /// Current navigation stage in the state machine 0227 Stage navigationStage = Stage::initial; 0228 0229 /// Statistics collection for navigation performance 0230 NavigatorStatistics statistics; 0231 0232 /// Stream for navigation debugging and monitoring 0233 NavigationStream stream; 0234 0235 /// Surfaces that are not part of the tracking geometry 0236 std::vector<const Surface*> freeSurfaces; 0237 0238 /// Reset navigation state after switching layers 0239 void resetAfterLayerSwitch() { 0240 navSurfaces.clear(); 0241 navSurfaceIndex.reset(); 0242 } 0243 0244 /// Reset navigation state after switching volumes 0245 void resetAfterVolumeSwitch() { 0246 resetAfterLayerSwitch(); 0247 0248 navLayers.clear(); 0249 navLayerIndex.reset(); 0250 navBoundaries.clear(); 0251 navBoundaryIndex.reset(); 0252 navCandidateIndex.reset(); 0253 0254 currentLayer = nullptr; 0255 0256 policyStateManager.reset(); 0257 policyStateIsDefault = true; 0258 } 0259 0260 /// Completely reset navigation state to initial conditions 0261 void resetForRenavigation() { 0262 resetAfterVolumeSwitch(); 0263 0264 currentVolume = nullptr; 0265 currentSurface = nullptr; 0266 0267 navigationBreak = false; 0268 navigationStage = Stage::initial; 0269 0270 // Set the surface reached switches back to false 0271 std::ranges::for_each(freeCandidates, 0272 [](std::pair<const Surface*, bool>& freeSurface) { 0273 freeSurface.second = false; 0274 }); 0275 0276 stream.reset(); 0277 } 0278 }; 0279 0280 /// Constructor with configuration object 0281 /// 0282 /// @param cfg The navigator configuration 0283 /// @param _logger a logger instance 0284 explicit Navigator(Config cfg, 0285 std::shared_ptr<const Logger> _logger = 0286 getDefaultLogger("Navigator", Logging::Level::INFO)); 0287 0288 /// Create a navigation state from options 0289 /// @param options The navigation options 0290 /// @return A new navigation state 0291 State makeState(const Options& options) const; 0292 0293 /// Get the current surface from navigation state 0294 /// @param state The navigation state 0295 /// @return Pointer to current surface, or nullptr if none 0296 const Surface* currentSurface(const State& state) const; 0297 0298 /// Get the current volume from navigation state 0299 /// @param state The navigation state 0300 /// @return Pointer to current volume, or nullptr if none 0301 const TrackingVolume* currentVolume(const State& state) const; 0302 0303 /// Get material properties of the current volume 0304 /// @param state The navigation state 0305 /// @return Pointer to volume material, or nullptr if no volume or material 0306 const IVolumeMaterial* currentVolumeMaterial(const State& state) const; 0307 0308 /// Get the starting surface from navigation state 0309 /// @param state The navigation state 0310 /// @return Pointer to start surface, or nullptr if none 0311 const Surface* startSurface(const State& state) const; 0312 0313 /// Get the target surface from navigation state 0314 /// @param state The navigation state 0315 /// @return Pointer to target surface, or nullptr if none 0316 const Surface* targetSurface(const State& state) const; 0317 0318 /// Check if navigation has reached the end of the world (no current volume) 0319 /// @param state The navigation state 0320 /// @return True if end of world is reached 0321 bool endOfWorldReached(const State& state) const; 0322 0323 /// Check if navigation should be interrupted 0324 /// @param state The navigation state 0325 /// @return True if navigation break flag is set 0326 bool navigationBreak(const State& state) const; 0327 0328 /// @brief Initialize the navigator state 0329 /// 0330 /// This function initializes the navigator state for a new propagation. 0331 /// 0332 /// @param state The navigation state 0333 /// @param position The start position 0334 /// @param direction The start direction 0335 /// @param propagationDirection The propagation direction 0336 /// 0337 /// @return Indication if the initialization was successful 0338 [[nodiscard]] Result<void> initialize(State& state, const Vector3& position, 0339 const Vector3& direction, 0340 Direction propagationDirection) const; 0341 0342 /// @brief Get the next target surface 0343 /// 0344 /// This function gets the next target surface for the propagation. 0345 /// 0346 /// @param state The navigation state 0347 /// @param position The current position 0348 /// @param direction The current direction 0349 /// 0350 /// @return The next target surface 0351 NavigationTarget nextTarget(State& state, const Vector3& position, 0352 const Vector3& direction) const; 0353 0354 /// @brief Check if the current target is still valid 0355 /// 0356 /// This function checks if the target is valid. 0357 /// 0358 /// @param state The navigation state 0359 /// @param position The current position 0360 /// @param direction The current direction 0361 /// 0362 /// @return True if the target is valid 0363 bool checkTargetValid(State& state, const Vector3& position, 0364 const Vector3& direction) const; 0365 0366 /// @brief Handle the surface reached 0367 /// 0368 /// This function handles the surface reached. 0369 /// 0370 /// @param state The navigation state 0371 /// @param position The current position 0372 /// @param direction The current direction 0373 /// @param surface The surface reached 0374 void handleSurfaceReached(State& state, const Vector3& position, 0375 const Vector3& direction, 0376 const Surface& surface) const; 0377 0378 private: 0379 /// @brief NextTarget helper function for Gen1 geometry configuration 0380 /// 0381 /// @param state The navigation state 0382 /// @param position The current position 0383 /// @param direction The current direction 0384 NavigationTarget getNextTargetGen1(State& state, const Vector3& position, 0385 const Vector3& direction) const; 0386 0387 /// @brief NextTarget helper function for Gen3 geometry configuration 0388 /// 0389 /// @param state The navigation state 0390 /// @param position The current position 0391 /// @param direction The current direction 0392 NavigationTarget getNextTargetGen3(State& state, const Vector3& position, 0393 const Vector3& direction) const; 0394 0395 /// @brief NextTarget helper function 0396 /// This function is called for returning the next target 0397 /// and checks gen1/gen3 case in order to sub-call the proper functions 0398 /// 0399 /// @param state The navigation state 0400 /// @param position The current position 0401 /// @param direction The current direction 0402 NavigationTarget tryGetNextTarget(State& state, const Vector3& position, 0403 const Vector3& direction) const; 0404 0405 /// @brief Resolve compatible candidates (surfaces or portals) for gen3 0406 /// navigation 0407 /// 0408 /// This function is called when gen3 configuration is found and it resolves 0409 /// at the same time for portals and surfaces 0410 /// @param state The navigation state 0411 /// @param position The current position 0412 /// @param direction The current direction 0413 void resolveCandidates(State& state, const Vector3& position, 0414 const Vector3& direction) const; 0415 0416 /// @brief Create the navigation policy state for the current volume 0417 /// 0418 /// Volumes whose navigation policy is known to push only default states 0419 /// (probed at geometry construction) skip the state creation entirely; the 0420 /// matching popState on volume exit is skipped under the same condition. 0421 /// The caller must ensure the current volume has a navigation policy. 0422 /// 0423 /// @param state The navigation state 0424 /// @param position The current position 0425 /// @param direction The current direction 0426 void createPolicyState(State& state, const Vector3& position, 0427 const Vector3& direction) const; 0428 0429 /// @brief Resolve compatible surfaces 0430 /// 0431 /// This function resolves the compatible surfaces for the navigation. 0432 /// 0433 /// @param state The navigation state 0434 /// @param position The current position 0435 /// @param direction The current direction 0436 void resolveSurfaces(State& state, const Vector3& position, 0437 const Vector3& direction) const; 0438 0439 /// @brief Resolve compatible layers 0440 /// 0441 /// This function resolves the compatible layers for the navigation. 0442 /// 0443 /// @param state The navigation state 0444 /// @param position The current position 0445 /// @param direction The current direction 0446 void resolveLayers(State& state, const Vector3& position, 0447 const Vector3& direction) const; 0448 0449 /// @brief Resolve compatible boundaries 0450 /// 0451 /// This function resolves the compatible boundaries for the navigation. 0452 /// 0453 /// @param state The navigation state 0454 /// @param position The current position 0455 /// @param direction The current direction 0456 void resolveBoundaries(State& state, const Vector3& position, 0457 const Vector3& direction) const; 0458 0459 /// @brief Check if the navigator is inactive 0460 /// 0461 /// This function checks if the navigator is inactive. 0462 /// 0463 /// @param state The navigation state 0464 /// 0465 /// @return True if the navigator is inactive 0466 bool inactive(const State& state) const; 0467 0468 /// @brief Get volume info string for logging 0469 /// 0470 /// @tparam propagator_state_t The propagator state type 0471 /// @param state The state containing current volume info 0472 /// @return String with volume name for logging 0473 std::string volInfo(const State& state) const; 0474 0475 const Logger& logger() const { return *m_logger; } 0476 0477 Config m_cfg; 0478 0479 // Cached so we don't have to query the TrackingGeometry constantly. 0480 TrackingGeometry::GeometryVersion m_geometryVersion{}; 0481 0482 std::shared_ptr<const Logger> m_logger; 0483 }; 0484 0485 } // namespace Acts
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|