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 during flight planning #2640

Closed
lpgagnon opened this issue Jul 12, 2020 · 12 comments · Fixed by #2779
Closed

Crash during flight planning #2640

lpgagnon opened this issue Jul 12, 2020 · 12 comments · Fixed by #2779
Labels

Comments

@lpgagnon
Copy link

lpgagnon commented Jul 12, 2020

Using build test-2626, on Windows.

While fiddling with a LEO rendez-vous flight plan, got a crash to desktop. Happened twice in a row in same situation. In both cases I was in the middle of typing a new number in an input box - flight plan duration in one case, burn time start in the other.

FATAL.log:
F0712 00:59:31.438285 14304 discrete_trajectory_body.hpp:644] Check failed: t_min() <= time (-1.28353034162678909e+09 s vs. -nan(ind) s)

ERROR.log and INFO.log

@pleroy
Copy link
Member

pleroy commented Jul 12, 2020

Can I get the INFO log? I need it to decode the stack.

@lpgagnon
Copy link
Author

sorry about that, I evidently read the instructions diagonally. INFO.log added to same gist

@lpgagnon
Copy link
Author

Seen again; this time in Galileo, and with no flight plan involved. Just one vessel slowly approaching another in LEO, tuning trajectory with RCS. Additional INFO.log added to same gist.

I'm presuming it's the same issue based on the identical "check failed" message

@pleroy
Copy link
Member

pleroy commented Jul 13, 2020

Decoded stack trace. This is going to be really hard without a journal:

Iterator** const closest_approaches) {
journal::Method<journal::RenderedPredictionClosestApproaches> m(
{plugin, vessel_guid, sun_world_position, max_points},
{closest_approaches});
CHECK_NOTNULL(plugin);
auto const& prediction = plugin->GetVessel(vessel_guid)->prediction();
std::unique_ptr<DiscreteTrajectory<World>> rendered_closest_approaches;
plugin->ComputeAndRenderClosestApproaches(
std::unique_ptr<DiscreteTrajectory<World>>& closest_approaches) const {
CHECK(renderer_->HasTargetVessel());
DiscreteTrajectory<Barycentric> apoapsides_trajectory;
DiscreteTrajectory<Barycentric> periapsides_trajectory;
ComputeApsides(renderer_->GetTargetVessel().prediction(),
DiscreteTrajectory<Frame>& periapsides) {
std::optional<Instant> previous_time;
std::optional<DegreesOfFreedom<Frame>> previous_degrees_of_freedom;
std::optional<Square<Length>> previous_squared_distance;
std::optional<Variation<Square<Length>>>
previous_squared_distance_derivative;
Instant const t_min = reference.t_min();
Instant const t_max = reference.t_max();
for (auto it = begin; it != end; ++it) {
auto const& [time, degrees_of_freedom] = *it;
if (time < t_min) {
continue;
}
if (time > t_max) {
break;
}
DegreesOfFreedom<Frame> const body_degrees_of_freedom =
reference.EvaluateDegreesOfFreedom(time);
RelativeDegreesOfFreedom<Frame> const relative =
degrees_of_freedom - body_degrees_of_freedom;
Square<Length> const squared_distance = relative.displacement().Norm²();
// This is the derivative of |squared_distance|.
Variation<Square<Length>> const squared_distance_derivative =
2.0 * InnerProduct(relative.displacement(), relative.velocity());
if (previous_squared_distance_derivative &&
Sign(squared_distance_derivative) !=
Sign(*previous_squared_distance_derivative)) {
CHECK(previous_time &&
previous_degrees_of_freedom &&
previous_squared_distance);
// The derivative of |squared_distance| changed sign. Construct a Hermite
// approximation of |squared_distance| and find its extrema.
Hermite3<Instant, Square<Length>> const
squared_distance_approximation(
{*previous_time, time},
{*previous_squared_distance, squared_distance},
{*previous_squared_distance_derivative,
squared_distance_derivative});
BoundedArray<Instant, 2> const extrema =
squared_distance_approximation.FindExtrema();
// Now look at the extrema and check that exactly one is in the required
// time interval. This is normally the case, but it can fail due to
// ill-conditioning.
Instant apsis_time;
int valid_extrema = 0;
for (auto const& extremum : extrema) {
if (extremum >= *previous_time && extremum <= time) {
apsis_time = extremum;
++valid_extrema;
}
}
if (valid_extrema != 1) {
// Something went wrong when finding the extrema of
// |squared_distance_approximation|. Use a linear interpolation of
// |squared_distance_derivative| instead.
apsis_time = Barycentre<Instant, Variation<Square<Length>>>(
{time, *previous_time},
{*previous_squared_distance_derivative,
-squared_distance_derivative});
}
// Now that we know the time of the apsis, use a Hermite approximation to
// derive its degrees of freedom. Note that an extremum of
// |squared_distance_approximation| is in general not an extremum for
// |position_approximation|: the distance computed using the latter is a
// 6th-degree polynomial. However, approximating this polynomial using a
// 3rd-degree polynomial would yield |squared_distance_approximation|, so
// we shouldn't be far from the truth.
DegreesOfFreedom<Frame> const apsis_degrees_of_freedom =
Instant const& time) const {
auto const interpolation = GetInterpolation(time);
Instant const& time) const {
CHECK_LE(t_min(), time);

@pleroy pleroy added the bug label Jul 13, 2020
@lpgagnon
Copy link
Author

lpgagnon commented Jul 17, 2020

You're (I'm?) in luck, got a semi-reproducible case. 3 crashes in a row, the last 2 with as close to the same steps as I could recall, the last with a journal. link

Steps: (I may have got some of these in the wrong order)

  • turn on journaling in tracking station, jump to vessel in LEO (station in LEO was already set as its target)
  • decouple spent stage (was hoping to hit the other crash, no luck)
  • create flight plan. add maneuver, add 60m/s prograde
  • change plan duration from default to 1d
  • change navball to target mode
  • focus on target
  • select the 001 in plan duration input box, TRY to change it to 2
  • crash

[edit: added corresponding INFO.20200716-230953.8156.log to gist)

@lpgagnon
Copy link
Author

Got 2 or 3 more crashes trying to do things differently; in every case, the crash trigger was trying to do keyboard input in a numerical field (at least plan duration and prograde dv; might also have happened with time-until-burn). I seem to be having better luck sticking to the sliders.

There's more to it than that, given my 2nd report of getting "the same" crash without a flight plan; but that's now the odd one out.

@lpgagnon
Copy link
Author

Haven't seen this happen again since upgrading from Galileo to Gallai

@lpgagnon
Copy link
Author

lpgagnon commented Oct 8, 2020

now seen in gateaux. trigger was again 'type in flight plan duration box'

@pleroy
Copy link
Member

pleroy commented Oct 31, 2020

Confirming the stack for the INFO log posted on July 17 (apologies for the delay).

Iterator** const closest_approaches) {
journal::Method<journal::RenderedPredictionClosestApproaches> m(
{plugin, vessel_guid, sun_world_position, max_points},
{closest_approaches});
CHECK_NOTNULL(plugin);
auto const& prediction = plugin->GetVessel(vessel_guid)->prediction();
std::unique_ptr<DiscreteTrajectory<World>> rendered_closest_approaches;
plugin->ComputeAndRenderClosestApproaches(
std::unique_ptr<DiscreteTrajectory<World>>& closest_approaches) const {
CHECK(renderer_->HasTargetVessel());
DiscreteTrajectory<Barycentric> apoapsides_trajectory;
DiscreteTrajectory<Barycentric> periapsides_trajectory;
ComputeApsides(renderer_->GetTargetVessel().prediction(),
DiscreteTrajectory<Frame>& periapsides) {
std::optional<Instant> previous_time;
std::optional<DegreesOfFreedom<Frame>> previous_degrees_of_freedom;
std::optional<Square<Length>> previous_squared_distance;
std::optional<Variation<Square<Length>>>
previous_squared_distance_derivative;
Instant const t_min = reference.t_min();
Instant const t_max = reference.t_max();
for (auto it = begin; it != end; ++it) {
auto const& [time, degrees_of_freedom] = *it;
if (time < t_min) {
continue;
}
if (time > t_max) {
break;
}
DegreesOfFreedom<Frame> const body_degrees_of_freedom =
reference.EvaluateDegreesOfFreedom(time);
RelativeDegreesOfFreedom<Frame> const relative =
degrees_of_freedom - body_degrees_of_freedom;
Square<Length> const squared_distance = relative.displacement().Norm²();
// This is the derivative of |squared_distance|.
Variation<Square<Length>> const squared_distance_derivative =
2.0 * InnerProduct(relative.displacement(), relative.velocity());
if (previous_squared_distance_derivative &&
Sign(squared_distance_derivative) !=
Sign(*previous_squared_distance_derivative)) {
CHECK(previous_time &&
previous_degrees_of_freedom &&
previous_squared_distance);
// The derivative of |squared_distance| changed sign. Construct a Hermite
// approximation of |squared_distance| and find its extrema.
Hermite3<Instant, Square<Length>> const
squared_distance_approximation(
{*previous_time, time},
{*previous_squared_distance, squared_distance},
{*previous_squared_distance_derivative,
squared_distance_derivative});
BoundedArray<Instant, 2> const extrema =
squared_distance_approximation.FindExtrema();
// Now look at the extrema and check that exactly one is in the required
// time interval. This is normally the case, but it can fail due to
// ill-conditioning.
Instant apsis_time;
int valid_extrema = 0;
for (auto const& extremum : extrema) {
if (extremum >= *previous_time && extremum <= time) {
apsis_time = extremum;
++valid_extrema;
}
}
if (valid_extrema != 1) {
// Something went wrong when finding the extrema of
// |squared_distance_approximation|. Use a linear interpolation of
// |squared_distance_derivative| instead.
apsis_time = Barycentre<Instant, Variation<Square<Length>>>(
{time, *previous_time},
{*previous_squared_distance_derivative,
-squared_distance_derivative});
}
// Now that we know the time of the apsis, use a Hermite approximation to
// derive its degrees of freedom. Note that an extremum of
// |squared_distance_approximation| is in general not an extremum for
// |position_approximation|: the distance computed using the latter is a
// 6th-degree polynomial. However, approximating this polynomial using a
// 3rd-degree polynomial would yield |squared_distance_approximation|, so
// we shouldn't be far from the truth.
DegreesOfFreedom<Frame> const apsis_degrees_of_freedom =
Instant const& time) const {
auto const interpolation = GetInterpolation(time);
Instant const& time) const {
CHECK_LE(t_min(), time);

@pleroy
Copy link
Member

pleroy commented Oct 31, 2020

Groan, running into #2778 when trying to replay the journal.

@pleroy
Copy link
Member

pleroy commented Oct 31, 2020

Replaying this journal was a bit of a pain because, due to #2778, the journal was incorrectly constructed so I had to hack around the corruptions.

Anyway, what is happening is that we are trying to compute the closest approaches between one vessel and itself (name 0133 station crew 2, guid db9cd970-10f6-4d4e-945a-90da6c172235). It seems that this vessel became its own target.

I am going to fix the numerical libraries, but we should also understand how that situation can happen, because I wouldn't be surprised if it caused crashes elsewhere.

@lpgagnon
Copy link
Author

re: became its own target: now idea how that might happen, but speculating:

select the 001 in plan duration input box, TRY to change it to 2

There's a good chance "select the 001" was done via double-clicking. I'm unclear on principia's click-through behavior, but double-click is one way to set/unset targets...

@pleroy pleroy added this to the Гельфанд milestone Nov 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants