Skip to content
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

Crash when switching to Instant Impulse #2781

Open
lpgagnon opened this issue Nov 1, 2020 · 4 comments
Open

Crash when switching to Instant Impulse #2781

lpgagnon opened this issue Nov 1, 2020 · 4 comments
Labels

Comments

@lpgagnon
Copy link

lpgagnon commented Nov 1, 2020

Scenario: in low orbit around the moon, plotting maneuvers for a landing. Had just quickloaded, and noticed plotted trajectory didn't quite match what it was prior to quicksave. Started fiddling with things to see if it was just a refresh issue. Last thing I did was click "instant impulse", game froze, then CTD.

Log file created at: 2020/11/01 13:30:34
Running on machine: LPG-GTX
Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg
    @   00007FFA6C4D6360  	google::LogMessageFatal::~LogMessageFatal [0x00007FFA6C4D635F+47]
    @   00007FFA47623AC3  	principia__VesselVelocity [0x00007FFA47623AC2+314018]
    @   00007FFA476D066E  	principia__VesselVelocity [0x00007FFA476D066D+1021517]
    @   00007FFA47536D9D  	(No symbol) [0x00007FFA47536D9C]
    @   00007FFA4753E879  	(No symbol) [0x00007FFA4753E878]
    @   00007FFA475C0C3F  	principia__FlightPlanReplace [0x00007FFA475C0C3E+494]
    @   0000019AF14E43ED  	(No symbol) [0x0000019AF14E43EC]
F1101 13:30:34.849426 15952 ephemeris_body.hpp:1200] Check failed: integrator_parameters.first_time_step > 0 * Second (-4.32489204406738281e+00 s vs. +0.00000000000000000e+00 s) Flow back to the future: -1.24250836271792316e+09 s <= -1.24250835839303112e+09 s

zipped INFO.log

@pleroy
Copy link
Member

pleroy commented Nov 8, 2020

Decoded stack trace:

int const index) {
journal::Method<journal::FlightPlanReplace> m({plugin,
vessel_guid,
burn,
index});
CHECK_NOTNULL(plugin);
return m.Return(
int const index) {
CHECK_LE(0, index);
CHECK_LT(index, number_of_manœuvres());
NavigationManœuvre const manœuvre(manœuvres_[index].initial_mass(),
burn);
if (manœuvre.IsSingular()) {
return Singular();
}
if (index == number_of_manœuvres() - 1) {
// This is the last manœuvre. If it doesn't fit just because the flight
// plan is too short, extend the flight plan.
if (manœuvre.IsAfter(start_of_previous_coast(index))) {
desired_final_time_ =
std::max(desired_final_time_, manœuvre.final_time());
} else {
return DoesNotFit();
}
} else if (!manœuvre.FitsBetween(start_of_previous_coast(index),
start_of_next_burn(index))) {
return DoesNotFit();
}
// Replace the manœuvre at position |index| and rebuild all the ones that
// follow as they may have a different initial mass. Also pop the segments
// that we'll recompute.
manœuvres_[index] = manœuvre;
UpdateInitialMassOfManœuvresAfter(index);
// TODO(phl): Recompute as late as possible.
PopSegmentsAffectedByManœuvre(index);
return ComputeSegments(manœuvres_.begin() + index, manœuvres_.end());
std::vector<NavigationManœuvre>::iterator const end) {
CHECK(!segments_.empty());
if (anomalous_segments_ == 0) {
anomalous_status_ = Status::OK;
}
Status overall_status = anomalous_status_;
for (auto it = begin; it != end; ++it) {
auto& manœuvre = *it;
auto& coast = segments_.back();
manœuvre.set_coasting_trajectory(coast);
if (anomalous_segments_ == 0) {
Status const status = CoastSegment(manœuvre.initial_time(), coast);
return ephemeris_->FlowWithAdaptiveStep(
std::int64_t const max_ephemeris_steps) {
auto compute_acceleration = [this, &intrinsic_acceleration](
Instant const& t,
std::vector<Position<Frame>> const& positions,
std::vector<Vector<Acceleration, Frame>>& accelerations) {
Error const error =
ComputeMasslessBodiesGravitationalAccelerations(t,
positions,
accelerations);
if (intrinsic_acceleration != nullptr) {
accelerations[0] += intrinsic_acceleration(t);
}
return error == Error::OK ? Status::OK :
CollisionDetected();
};
return FlowODEWithAdaptiveStep<NewtonianMotionEquation>(
std::int64_t max_ephemeris_steps) {
Instant const& trajectory_last_time = trajectory->back().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 * fixed_step_parameters_.step(),
trajectory_last_time + fixed_step_parameters_.step()),
t);
Prolong(t_final);
IntegrationProblem<ODE> problem;
problem.equation.compute_acceleration = std::move(compute_acceleration);
auto const trajectory_back = trajectory->back();
auto const last_degrees_of_freedom = trajectory_back.degrees_of_freedom;
problem.initial_state = {{last_degrees_of_freedom.position()},
{last_degrees_of_freedom.velocity()},
trajectory_back.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)

@pleroy
Copy link
Member

pleroy commented Nov 8, 2020

The log also has suspicious messages like:

I1101 12:07:26.290994  7936 flight_plan.cpp:320] Loading a flight plan with 1 anomalous segments and status FAILED_PRECONDITION: At time -1.24250734787396073e+09 s, step size is effectively zero.  Singularity or stiff system suspected.
E1101 13:29:51.749092 15952 interface_body.hpp:479] At time -1.24250735927222538e+09 s, step size is effectively zero.  Singularity or stiff system suspected.

Sorry, something went wrong.

@pleroy pleroy added the bug label Nov 8, 2020
@pleroy
Copy link
Member

pleroy commented Nov 14, 2020

I believe that the check tells us that Ephemeris::FlowODEWithAdaptiveStep is called with a t that is strictly less than the end time of the trajectory. (Note the word "believe", the logic there is a bit tricky.)

We are called from FlightPlan::Replace, replacing a manœuvre in the flight plan because the user clicked "instant impulse". We do not know exactly the shape of the flight plan at the time of the crash or the manœuvre being replaced, but the last time the flight plan was loaded it was anomalous, and therefore was printed out. It looked like this (times in second since J2000):

initial_time:       -1242512439.579787
desired_final_time: -1242504055.6769223
manœuvre 0:
  initial_time:     -1242510250.6003575
  final_time:       -1242510235.6185611
  duration:                  14.981796301479443
manœuvre 1:
  initial_time:     -1242508622.9597487
  final_time:       -1242508362.7189230
  duration:                 260.24082569420426
manœuvre 2:
  initial_time:     -1242508362.7179232
  final_time:       -1242508262.5189014
  duration:                 100.19902178449944

It is worth noting that the last segment is anomalous. The last time the flight plan is integrated a singularity is encountered at time -1242507359.27226591 so the desired final time is not reached (presumably, the flight plan goes through the centre of a planet). Also interesting is the fact that the last two manœuvres are very close, being separated by 1 ms.

The t_final passed to the integrator is 1242508362.71792316 which matches the initial time of manœuvre 2 to the last digit. This tells us that we are recomputing the coast that ends at the beginning of that manœuvre. However, the end of the trajectory being prolonged (which should be at the fork point of the coast ending at manœuvre 2, i.e., the end of manœuvre 1) is -1242508358.39303112 (4 seconds into manœuvre 2). All of this points at a bug in the replacement of manœuvres, but it's hard to be more specific.

Two questions for @lpgagnon:

  1. Would you remember on which of the manœuvres you were clicking "instant impulse"?
  2. Is this a reproducible bug, i.e., could you give us a journal?

@lpgagnon
Copy link
Author

  1. I don't, and wouldn't even venture a guess; I was clicking "harmless" things more or less at random
  2. Not reproducible; I've only seen it the one time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants