-
Notifications
You must be signed in to change notification settings - Fork 69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use the RKNG #1930
The head ref may contain hidden characters: "man\u0153uvre-rkng"
Use the RKNG #1930
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,7 @@ using base::Status; | |
using geometry::Instant; | ||
using geometry::Position; | ||
using geometry::Vector; | ||
using geometry::Velocity; | ||
using integrators::AdaptiveStepSizeIntegrator; | ||
using integrators::FixedStepSizeIntegrator; | ||
using integrators::Integrator; | ||
|
@@ -54,6 +55,11 @@ class Ephemeris { | |
using IntrinsicAcceleration = | ||
std::function<Vector<Acceleration, Frame>(Instant const& time)>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we still need the old intrinsic acceleration somewhere? If not, mention that we need to clean up in the issue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We still use it for the non-guided path, which uses a non-RKNG RKN. |
||
static std::nullptr_t constexpr NoIntrinsicAcceleration = nullptr; | ||
using GeneralIntrinsicAcceleration = | ||
std::function<Vector<Acceleration, Frame>( | ||
Instant const& time, | ||
Position<Frame> const& position, | ||
Velocity<Frame> const& velocity)>; | ||
using IntrinsicAccelerations = std::vector<IntrinsicAcceleration>; | ||
static IntrinsicAccelerations const NoIntrinsicAccelerations; | ||
static std::int64_t constexpr unlimited_max_ephemeris_steps = | ||
|
@@ -184,6 +190,23 @@ class Ephemeris { | |
std::int64_t max_ephemeris_steps, | ||
bool last_point_only); | ||
|
||
// Integrates, until exactly |t| (except for timeouts or singularities), the | ||
// |trajectory| followed by a massless body in the gravitational potential | ||
// described by |*this|. If |t > t_max()|, calls |Prolong(t)| beforehand. | ||
// Prolongs the ephemeris by at most |max_ephemeris_steps|. If | ||
// |last_point_only| is true, only the last point is appended to the | ||
// trajectory. Returns OK if and only if |*trajectory| was integrated until | ||
// |t|. | ||
// TODO(phl): the |parameters| are used, but |parameters.integrator_| is | ||
// ignored and a hard-coded RKNG is used instead. | ||
virtual Status FlowWithAdaptiveStepGeneralized( | ||
not_null<DiscreteTrajectory<Frame>*> trajectory, | ||
GeneralIntrinsicAcceleration intrinsic_acceleration, | ||
Instant const& t, | ||
AdaptiveStepParameters const& parameters, | ||
std::int64_t max_ephemeris_steps, | ||
bool last_point_only); | ||
|
||
// Integrates, until at most |t|, the trajectories followed by massless | ||
// bodies in the gravitational potential described by |*this|. If | ||
// |t > t_max()|, calls |Prolong(t)| beforehand. The trajectories and | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,8 +43,11 @@ using geometry::Position; | |
using geometry::R3Element; | ||
using geometry::Sign; | ||
using geometry::Velocity; | ||
using integrators::EmbeddedExplicitGeneralizedRungeKuttaNyströmIntegrator; | ||
using integrators::ExplicitSecondOrderOrdinaryDifferentialEquation; | ||
using integrators::Integrator; | ||
using integrators::IntegrationProblem; | ||
using integrators::methods::Fine1987RKNG34; | ||
using numerics::Bisect; | ||
using numerics::DoublePrecision; | ||
using numerics::Hermite3; | ||
|
@@ -552,6 +555,117 @@ Status Ephemeris<Frame>::FlowWithAdaptiveStep( | |
} | ||
} | ||
|
||
template<typename Frame> | ||
Status Ephemeris<Frame>::FlowWithAdaptiveStepGeneralized( | ||
not_null<DiscreteTrajectory<Frame>*> trajectory, | ||
GeneralIntrinsicAcceleration intrinsic_acceleration, | ||
Instant const& t, | ||
AdaptiveStepParameters const& parameters, | ||
std::int64_t max_ephemeris_steps, | ||
bool last_point_only) { | ||
// TODO(phl): FlowWithAdaptiveStepGeneralized and FlowWithAdaptiveStep are | ||
// very similar. Factor that which can be factored. | ||
using ODE = ExplicitSecondOrderOrdinaryDifferentialEquation<Position<Frame>>; | ||
Instant const& trajectory_last_time = trajectory->last().time(); | ||
if (trajectory_last_time == t) { | ||
return Status::OK; | ||
} | ||
|
||
std::vector<not_null<DiscreteTrajectory<Frame>*>> const trajectories = | ||
{trajectory}; | ||
// The |min| is here to prevent us from spending too much time computing the | ||
// ephemeris. The |max| is here to ensure that we always try to integrate | ||
// forward. We use |last_state_.time.value| because this is always finite, | ||
// contrary to |t_max()|, which is -∞ when |empty()|. | ||
Instant const t_final = | ||
std::min(std::max(instance_time() + | ||
max_ephemeris_steps * parameters_.step(), | ||
trajectory_last_time + parameters_.step()), | ||
t); | ||
Prolong(t_final); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am sure that I have seen most of this code elsewhere. Please factor it out. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More TODOs for #1931. |
||
|
||
IntegrationProblem<ODE> problem; | ||
problem.equation.compute_acceleration = | ||
[this, &intrinsic_acceleration]( | ||
Instant const& t, | ||
std::vector<Position<Frame>> const& positions, | ||
std::vector<Velocity<Frame>> const& velocities, | ||
std::vector<Vector<Acceleration, Frame>>& accelerations) { | ||
if (!ComputeMasslessBodiesGravitationalAccelerations( | ||
t, positions, accelerations)) { | ||
return Status(Error::OUT_OF_RANGE, "Collision detected"); | ||
} | ||
accelerations[0] += | ||
intrinsic_acceleration(t, positions[0], velocities[0]); | ||
return Status::OK; | ||
}; | ||
|
||
auto const trajectory_last = trajectory->last(); | ||
auto const last_degrees_of_freedom = trajectory_last.degrees_of_freedom(); | ||
problem.initial_state = {{last_degrees_of_freedom.position()}, | ||
{last_degrees_of_freedom.velocity()}, | ||
trajectory_last.time()}; | ||
|
||
typename AdaptiveStepSizeIntegrator<ODE>::Parameters const | ||
integrator_parameters( | ||
/*first_time_step=*/t_final - problem.initial_state.time.value, | ||
/*safety_factor=*/0.9, | ||
parameters.max_steps_, | ||
/*last_step_is_exact=*/true); | ||
CHECK_GT(integrator_parameters.first_time_step, 0 * Second) | ||
<< "Flow back to the future: " << t_final | ||
<< " <= " << problem.initial_state.time.value; | ||
auto const tolerance_to_error_ratio = | ||
std::bind(&Ephemeris<Frame>::ToleranceToErrorRatio, | ||
std::cref(parameters.length_integration_tolerance_), | ||
std::cref(parameters.speed_integration_tolerance_), | ||
_1, _2); | ||
|
||
typename AdaptiveStepSizeIntegrator<ODE>::AppendState append_state; | ||
typename ODE::SystemState last_state; | ||
if (last_point_only) { | ||
append_state = [&last_state](typename ODE::SystemState const& state) { | ||
last_state = state; | ||
}; | ||
} else { | ||
append_state = std::bind( | ||
&Ephemeris::AppendMasslessBodiesState, _1, std::cref(trajectories)); | ||
} | ||
|
||
auto const instance = | ||
EmbeddedExplicitGeneralizedRungeKuttaNyströmIntegrator< | ||
Fine1987RKNG34, Position<Frame>>().NewInstance( | ||
problem, | ||
append_state, | ||
tolerance_to_error_ratio, | ||
integrator_parameters); | ||
auto status = instance->Solve(t_final); | ||
|
||
// We probably don't care if the vessel gets too close to the singularity, as | ||
// we only use this integrator for the future. So we swallow the error. | ||
// TODO(phl): Is this the right thing to do long term? | ||
if (status.error() == Error::OUT_OF_RANGE) { | ||
status = Status::OK; | ||
} | ||
|
||
if (last_point_only) { | ||
AppendMasslessBodiesState(last_state, trajectories); | ||
} | ||
|
||
// TODO(egg): when we have events in trajectories, we should add a singularity | ||
// event at the end if the outcome indicates a singularity | ||
// (|VanishingStepSize|). We should not have an event on the trajectory if | ||
// |ReachedMaximalStepCount|, since that is not a physical property, but | ||
// rather a self-imposed constraint. | ||
if (!status.ok() || t_final == t) { | ||
return status; | ||
} else { | ||
return Status(Error::DEADLINE_EXCEEDED, | ||
"Couldn't reach " + DebugString(t_final) + ", stopping at " + | ||
DebugString(t)); | ||
} | ||
} | ||
|
||
template<typename Frame> | ||
Status Ephemeris<Frame>::FlowWithFixedStep( | ||
Instant const& t, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please create an issue for all these TODOs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#1931.