Skip to content

Commit

Permalink
refactor!: Reset navigation state in (C)KF (#846)
Browse files Browse the repository at this point in the history
This PR simplifies the reset of the navigation state to enable the navigation to start from a new surface with provided position and momentum. It requires the Navigator State struct has a method reset.
  • Loading branch information
XiaocongAi committed Jul 14, 2021
1 parent 96f3a3f commit 803bd93
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 113 deletions.
20 changes: 20 additions & 0 deletions Core/include/Acts/Propagator/DirectNavigator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,26 @@ class DirectNavigator {
bool targetReached = false;
/// Navigation state - external interface: a break has been detected
bool navigationBreak = false;

/// Reset state
///
/// @param ssurface is the new starting surface
/// @param tsurface is the target surface
void reset(const GeometryContext& /*geoContext*/, const Vector3& /*pos*/,
const Vector3& /*dir*/, NavigationDirection /*navDir*/,
const Surface* ssurface, const Surface* tsurface) {
// Reset everything except the navSurfaces
State newState = State();
newState.navSurfaces = this->navSurfaces;
*this = newState;

// Reset others
navSurfaceIter =
std::find(navSurfaces.begin(), navSurfaces.end(), ssurface);
startSurface = ssurface;
currentSurface = ssurface;
targetSurface = tsurface;
}
};

/// @brief Navigator status call
Expand Down
36 changes: 36 additions & 0 deletions Core/include/Acts/Propagator/Navigator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,42 @@ class Navigator {
bool navigationBreak = false;
// The navigation stage (@todo: integrate break, target)
Stage navigationStage = Stage::undefined;

/// Reset state
///
/// @param geoContext is the geometry context
/// @param pos is the global position
/// @param dir is the momentum direction
/// @param navDir is the navigation direction
/// @param ssurface is the new starting surface
/// @param tsurface is the target surface
void reset(const GeometryContext& geoContext, const Vector3& pos,
const Vector3& dir, NavigationDirection navDir,
const Surface* ssurface, const Surface* tsurface) {
// Reset everything first
*this = State();

// Set the start, current and target objects
startSurface = ssurface;
if (ssurface->associatedLayer() != nullptr) {
startLayer = ssurface->associatedLayer();
}
if (startLayer->trackingVolume() != nullptr) {
startVolume = startLayer->trackingVolume();
}
currentSurface = startSurface;
currentVolume = startVolume;
targetSurface = tsurface;

// Get the compatible layers (including the current layer)
NavigationOptions<Layer> navOpts(navDir, true, true, true, true, nullptr,
nullptr);
navLayers =
currentVolume->compatibleLayers(geoContext, pos, dir, navOpts);

// Set the iterator to the first
navLayerIter = navLayers.begin();
}
};

/// Constructor with configuration object
Expand Down
43 changes: 7 additions & 36 deletions Core/include/Acts/TrackFinding/CombinatorialKalmanFilter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,6 @@ struct CombinatorialKalmanFilterResult {
// The index for the current smoothing track
size_t iSmoothed = 0;

// Indicator if the propagation state has been reset
bool reset = false;

// Indicator if track finding has been done
bool finished = false;

Expand Down Expand Up @@ -296,23 +293,6 @@ class CombinatorialKalmanFilter {

ACTS_VERBOSE("CombinatorialKalmanFilter step");

// This following is added due to the fact that the navigation
// reinitialization in reset call cannot guarantee the navigator to target
// for extra layers in the reset volume.
// Currently, manually set navigation stage to allow for targeting layers
// after all the surfaces on the reset layer has been processed.
// Otherwise, the navigation stage will be Stage::boundaryTarget after
// navigator status call which means the extra layers on the reset volume
// won't be targeted.
// @Todo: Let the navigator do all the re-initialization
if (result.reset and state.navigation.navSurfaceIter ==
state.navigation.navSurfaces.end()) {
// So the navigator target call will target layers
state.navigation.navigationStage = KalmanNavigator::Stage::layerTarget;
// We only do this after the reset layer has been processed
result.reset = false;
}

// Update:
// - Waiting for a current surface
auto surface = state.navigation.currentSurface;
Expand Down Expand Up @@ -491,33 +471,24 @@ class CombinatorialKalmanFilter {
template <typename propagator_state_t, typename stepper_t>
void reset(propagator_state_t& state, stepper_t& stepper,
result_type& result) const {
// Remember the propagation state has been reset
result.reset = true;
auto currentState =
result.fittedStates.getTrackState(result.activeTips.back().first);

// Reset the navigation state
state.navigation = typename propagator_t::NavigatorState();
state.navigation.startSurface = &currentState.referenceSurface();
if (state.navigation.startSurface->associatedLayer() != nullptr) {
state.navigation.startLayer =
state.navigation.startSurface->associatedLayer();
}
state.navigation.startVolume =
state.navigation.startLayer->trackingVolume();
state.navigation.targetSurface = targetSurface;
state.navigation.currentSurface = state.navigation.startSurface;
state.navigation.currentVolume = state.navigation.startVolume;

// Update the stepping state
stepper.resetState(state.stepping, currentState.filtered(),
currentState.filteredCovariance(),
currentState.referenceSurface(), state.stepping.navDir,
state.options.maxStepSize);

// Reset the navigation state
state.navigation.reset(state.geoContext, stepper.position(state.stepping),
stepper.direction(state.stepping),
state.stepping.navDir,
&currentState.referenceSurface(), targetSurface);

// No Kalman filtering for the starting surface, but still need
// to consider the material effects here
materialInteractor(state.navigation.startSurface, state, stepper);
materialInteractor(state.navigation.currentSurface, state, stepper);
}

/// @brief CombinatorialKalmanFilter actor operation :
Expand Down
107 changes: 40 additions & 67 deletions Core/include/Acts/TrackFitting/KalmanFitter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,6 @@ struct KalmanFitterResult {
// Indicator if smoothing has been done.
bool smoothed = false;

// Indicator if the propagation state has been reset
bool reset = false;

// Indicator if navigation direction has been reversed
bool reversed = false;

Expand Down Expand Up @@ -275,27 +272,6 @@ class KalmanFitter {
}
}

// This following is added due to the fact that the navigation
// reinitialization in reverse call cannot guarantee the navigator to
// target for extra layers in the reversed-propagation starting volume.
// Currently, manually set navigation stage to allow for targeting layers
// after all the surfaces on the reversed-propagation starting layer has
// been processed. Otherwise, the navigation stage will be
// Stage::boundaryTarget after navigator status call which means the extra
// layers on the reversed-propagation starting volume won't be targeted.
// @Todo: Let the navigator do all the re-initialization
if constexpr (not isDirectNavigator) {
if (result.reset and state.navigation.navSurfaceIter ==
state.navigation.navSurfaces.end()) {
// So the navigator target call will target layers
state.navigation.navigationStage =
KalmanNavigator::Stage::layerTarget;
// We only do this after the backward-propagation
// starting layer has been processed
result.reset = false;
}
}

// Update:
// - Waiting for a current surface
auto surface = state.navigation.currentSurface;
Expand Down Expand Up @@ -342,7 +318,11 @@ class KalmanFitter {
// Reverse navigation direction and reset navigation and stepping
// state to last measurement
ACTS_VERBOSE("Reverse navigation direction.");
reverse(state, stepper, result);
auto res = reverse(state, stepper, result);
if (!res.ok()) {
ACTS_ERROR("Error in reversing navigation: " << res.error());
result.result = res.error();
}
} else {
// --> Search the starting state to run the smoothing
// --> Call the smoothing
Expand Down Expand Up @@ -424,12 +404,18 @@ class KalmanFitter {
/// @param stepper The stepper in use
/// @param result is the mutable result state objecte
template <typename propagator_state_t, typename stepper_t>
void reverse(propagator_state_t& state, stepper_t& stepper,
result_type& result) const {
Result<void> reverse(propagator_state_t& state, stepper_t& stepper,
result_type& result) const {
const auto& logger = state.options.logger;

// Check if there is a measurement on track
if (result.lastMeasurementIndex == SIZE_MAX) {
ACTS_ERROR("No point to reverse for a track without measurements.");
return KalmanFitterError::ReverseNavigationFailed;
}

// Remember the navigation direciton has been reversed
result.reversed = true;
// The reset is used for resetting the navigation
result.reset = true;

// Reverse navigation direction
state.stepping.navDir =
Expand All @@ -442,44 +428,31 @@ class KalmanFitter {
state.options.pathLimit =
state.stepping.navDir * std::abs(state.options.pathLimit);

// Reset stepping&navigation state using last measurement track state on
// sensitive surface
state.navigation = typename propagator_t::NavigatorState();
result.fittedStates.applyBackwards(
result.lastMeasurementIndex, [&](auto st) {
if (st.typeFlags().test(Acts::TrackStateFlag::MeasurementFlag)) {
// Set the navigation state
state.navigation.startSurface = &st.referenceSurface();
if (state.navigation.startSurface->associatedLayer() != nullptr) {
state.navigation.startLayer =
state.navigation.startSurface->associatedLayer();
}
state.navigation.startVolume =
state.navigation.startLayer->trackingVolume();
state.navigation.targetSurface = targetSurface;
state.navigation.currentSurface = state.navigation.startSurface;
state.navigation.currentVolume = state.navigation.startVolume;

// Update the stepping state
stepper.resetState(state.stepping, st.filtered(),
st.filteredCovariance(), st.referenceSurface(),
state.stepping.navDir,
state.options.maxStepSize);

// For the last measurement state, smoothed is filtered
st.smoothed() = st.filtered();
st.smoothedCovariance() = st.filteredCovariance();
result.passedAgainSurfaces.push_back(&st.referenceSurface());

// Update material effects for last measurement state in reversed
// direction
materialInteractor(state.navigation.currentSurface, state,
stepper);

return false; // abort execution
}
return true; // continue execution
});
// Get the last measurement state and reset navigation&stepping state
// based on information on this state
auto st = result.fittedStates.getTrackState(result.lastMeasurementIndex);

// Update the stepping state
stepper.resetState(state.stepping, st.filtered(), st.filteredCovariance(),
st.referenceSurface(), state.stepping.navDir,
state.options.maxStepSize);

// For the last measurement state, smoothed is filtered
st.smoothed() = st.filtered();
st.smoothedCovariance() = st.filteredCovariance();
result.passedAgainSurfaces.push_back(&st.referenceSurface());

// Reset navigation state
state.navigation.reset(state.geoContext, stepper.position(state.stepping),
stepper.direction(state.stepping),
state.stepping.navDir, &st.referenceSurface(),
targetSurface);

// Update material effects for last measurement state in reversed
// direction
materialInteractor(state.navigation.currentSurface, state, stepper);

return Result<void>::success();
}

/// @brief Kalman actor operation : update
Expand Down
1 change: 1 addition & 0 deletions Core/include/Acts/TrackFitting/KalmanFitterError.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ enum class KalmanFitterError {
SmoothFailed,
OutputConversionFailed,
NoMeasurementFound,
ReverseNavigationFailed,
};

std::error_code make_error_code(Acts::KalmanFitterError e);
Expand Down
10 changes: 0 additions & 10 deletions Tests/UnitTests/Core/TrackFitting/KalmanFitterTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ BOOST_AUTO_TEST_CASE(ZeroFieldNoSurfaceForward) {
// check the output status flags
BOOST_CHECK(val.smoothed);
BOOST_CHECK(not val.reversed);
BOOST_CHECK(not val.reset);
BOOST_CHECK(val.finished);
BOOST_CHECK_EQUAL(val.missedActiveSurfaces.size(), 0u);
}
Expand Down Expand Up @@ -217,7 +216,6 @@ BOOST_AUTO_TEST_CASE(ZeroFieldWithSurfaceForward) {
// check the output status flags
BOOST_CHECK(val.smoothed);
BOOST_CHECK(not val.reversed);
BOOST_CHECK(not val.reset);
BOOST_CHECK(val.finished);
BOOST_CHECK_EQUAL(val.missedActiveSurfaces.size(), 0u);
}
Expand All @@ -233,7 +231,6 @@ BOOST_AUTO_TEST_CASE(ZeroFieldWithSurfaceForward) {
// check the output status flags
BOOST_CHECK(not val.smoothed);
BOOST_CHECK(val.reversed);
BOOST_CHECK(not val.reset);
BOOST_CHECK(val.finished);
BOOST_CHECK_EQUAL(val.measurementStates, sourceLinks.size());
BOOST_CHECK_EQUAL(val.missedActiveSurfaces.size(), 0u);
Expand Down Expand Up @@ -279,7 +276,6 @@ BOOST_AUTO_TEST_CASE(ZeroFieldWithSurfaceBackward) {
// check the output status flags
BOOST_CHECK(val.smoothed);
BOOST_CHECK(not val.reversed);
BOOST_CHECK(not val.reset);
BOOST_CHECK(val.finished);
BOOST_CHECK_EQUAL(val.missedActiveSurfaces.size(), 0u);
}
Expand All @@ -296,7 +292,6 @@ BOOST_AUTO_TEST_CASE(ZeroFieldWithSurfaceBackward) {
// check the output status flags
BOOST_CHECK(not val.smoothed);
BOOST_CHECK(val.reversed);
BOOST_CHECK(not val.reset);
BOOST_CHECK(val.finished);
BOOST_CHECK_EQUAL(val.missedActiveSurfaces.size(), 0u);
// count the number of `smoothed` states
Expand Down Expand Up @@ -335,7 +330,6 @@ BOOST_AUTO_TEST_CASE(ZeroFieldWithSurfaceAtExit) {
// check the output status flags
BOOST_CHECK(val.smoothed);
BOOST_CHECK(not val.reversed);
BOOST_CHECK(not val.reset);
BOOST_CHECK(val.finished);
BOOST_CHECK_EQUAL(val.missedActiveSurfaces.size(), 0u);
}
Expand Down Expand Up @@ -367,7 +361,6 @@ BOOST_AUTO_TEST_CASE(ZeroFieldShuffled) {
// check the output status flags
BOOST_CHECK(val.smoothed);
BOOST_CHECK(not val.reversed);
BOOST_CHECK(not val.reset);
BOOST_CHECK(val.finished);
BOOST_CHECK_EQUAL(val.missedActiveSurfaces.size(), 0u);
}
Expand All @@ -387,7 +380,6 @@ BOOST_AUTO_TEST_CASE(ZeroFieldShuffled) {
// check the output status flags
BOOST_CHECK(val.smoothed);
BOOST_CHECK(not val.reversed);
BOOST_CHECK(not val.reset);
BOOST_CHECK(val.finished);
BOOST_CHECK_EQUAL(val.missedActiveSurfaces.size(), 0u);
}
Expand Down Expand Up @@ -424,7 +416,6 @@ BOOST_AUTO_TEST_CASE(ZeroFieldWithHole) {
// check the output status flags
BOOST_CHECK(val.smoothed);
BOOST_CHECK(not val.reversed);
BOOST_CHECK(not val.reset);
BOOST_CHECK(val.finished);
BOOST_CHECK_EQUAL(val.missedActiveSurfaces.size(), 1u);
}
Expand Down Expand Up @@ -470,7 +461,6 @@ BOOST_AUTO_TEST_CASE(ZeroFieldWithOutliers) {
// check the output status flags
BOOST_CHECK(val.smoothed);
BOOST_CHECK(not val.reversed);
BOOST_CHECK(not val.reset);
BOOST_CHECK(val.finished);
BOOST_CHECK_EQUAL(val.missedActiveSurfaces.size(), 0u);
}
Expand Down

0 comments on commit 803bd93

Please sign in to comment.