// Check the times of the lunar eclipses in LunarEclipseTest. TEST_F(TimeScalesTest, LunarEclipses) { EXPECT_THAT(AbsoluteError("1950-04-02T20:44:34.0"_TT, "1950-04-02T20:44:04.8"_UT1), Lt(14 * Milli(Second))); EXPECT_THAT(AbsoluteError("1950-04-02T20:49:16.7"_TT, "1950-04-02T20:48:47.5"_UT1), Lt(14 * Milli(Second))); EXPECT_THAT(AbsoluteError("1950-09-26T04:17:11.4"_TT, "1950-09-26T04:16:42.1"_UT1), Lt(86 * Milli(Second))); EXPECT_THAT(AbsoluteError("1950-09-26T04:21:55.5"_TT, "1950-09-26T04:21:26.1"_UT1), Lt(15 * Milli(Second))); EXPECT_THAT(AbsoluteError("1951-03-23T10:37:33.2"_TT, "1951-03-23T10:37:03.7"_UT1), Lt(92 * Milli(Second))); EXPECT_THAT(AbsoluteError("1951-03-23T10:50:16.8"_TT, "1951-03-23T10:49:47.3"_UT1), Lt(92 * Milli(Second))); EXPECT_THAT(AbsoluteError("1951-09-15T12:27:06.3"_TT, "1951-09-15T12:26:36.6"_UT1), Lt(99 * Milli(Second))); EXPECT_THAT(AbsoluteError("1951-09-15T12:38:51.5"_TT, "1951-09-15T12:38:21.8"_UT1), Lt(99 * Milli(Second))); EXPECT_THAT(AbsoluteError("1952-02-11T00:28:39.9"_TT, "1952-02-11T00:28:10.0"_UT1), Lt(69 * Milli(Second))); EXPECT_THAT(AbsoluteError("1952-02-11T00:39:47.6"_TT, "1952-02-11T00:39:17.7"_UT1), Lt(69 * Milli(Second))); EXPECT_THAT(AbsoluteError("1952-08-05T19:40:29.4"_TT, "1952-08-05T19:39:59.3"_UT1), Lt(57 * Milli(Second))); EXPECT_THAT(AbsoluteError("1952-08-05T19:47:54.8"_TT, "1952-08-05T19:47:24.7"_UT1), Lt(57 * Milli(Second))); EXPECT_THAT(AbsoluteError("2000-01-21T04:41:30.5"_TT, "2000-01-21T04:40:26.7"_UT1), Lt(45 * Milli(Second))); EXPECT_THAT(AbsoluteError("2000-01-21T04:44:34.5"_TT, "2000-01-21T04:43:30.6"_UT1), Lt(56 * Milli(Second))); EXPECT_THAT("2048-01-01T06:53:54.8"_TT - "2048-01-01T06:52:23.6"_TT, AlmostEquals(91.2 * Second, 3e6, 4e6)); EXPECT_THAT("2048-01-01T06:58:19.8"_TT - "2048-01-01T06:56:48.6"_TT, AlmostEquals(91.2 * Second, 3e6, 4e6)); }
TEST_F(JacobiCoordinatesTest, Jacobi) { auto const x_positions = [](JacobiCoordinates<Frame> const& system) { std::vector<Length> result; auto const barycentric_dof = system.BarycentricDegreesOfFreedom(); std::transform(barycentric_dof.begin(), barycentric_dof.end(), std::back_inserter(result), [](RelativeDegreesOfFreedom<Frame> const& dof) { return dof.displacement().coordinates().x; }); return result; }; // i, and Ω are 0 by default. KeplerianElements<Frame> elements; elements.eccentricity = 0; elements.argument_of_periapsis = 0 * Radian; elements.mean_anomaly = 0 * Radian; JacobiCoordinates<Frame> system(m2_); EXPECT_EQ(2 * Kilogram, system.System().mass()); EXPECT_THAT(x_positions(system), ElementsAre(0 * Metre)); elements.semimajor_axis = 1 * Metre; system.Add(m1_, elements); // The system now consists of a 2 kg mass and a 1 kg mass, with the barycentre // one third of the way, as shown. // 2 1 // ^ barycentre EXPECT_EQ(3 * Kilogram, system.System().mass()); EXPECT_THAT( x_positions(system), ElementsAre(AlmostEquals(-1.0 / 3.0 * Metre, 1), AlmostEquals(2.0 / 3.0 * Metre, 0))); elements.semimajor_axis = 5.0 / 3.0 * Metre; system.Add(m2_, elements); // 2 1 2 // ^ barycentre EXPECT_EQ(5 * Kilogram, system.System().mass()); EXPECT_THAT(x_positions(system), ElementsAre(-1 * Metre, 0 * Metre, 1 * Metre)); elements.semimajor_axis = 6 * Metre; system.Add(m1_, elements); // 2 1 2 . . . . 1 // ^ barycentre EXPECT_THAT(x_positions(system), ElementsAre(AlmostEquals(-2 * Metre, 0), AlmostEquals(-1 * Metre, 0), VanishesBefore(1 * Metre, 0), 5 * Metre)); }
TEST_F(BodyCentredNonRotatingDynamicFrameTest, Inverse) { int const steps = 100; for (Instant t = t0_; t < t0_ + 1 * period_; t += period_ / steps) { auto const from_big_frame_at_t = big_frame_->FromThisFrameAtTime(t); auto const to_big_frame_at_t = big_frame_->ToThisFrameAtTime(t); auto const small_initial_state_transformed_and_back = from_big_frame_at_t(to_big_frame_at_t(small_initial_state_)); EXPECT_THAT(small_initial_state_transformed_and_back.position(), AlmostEquals(small_initial_state_.position(), 0, 1)); EXPECT_THAT(small_initial_state_transformed_and_back.velocity(), AlmostEquals(small_initial_state_.velocity(), 0, 1)); } }
TEST_F(TimeScalesTest, ReferenceDates) { EXPECT_THAT("1858-11-17T00:00:00"_TT, Eq(ModifiedJulianDate(0))); EXPECT_THAT(j2000_week, Eq(J2000)); EXPECT_THAT(j2000_from_tt, Eq(J2000)); EXPECT_THAT(j2000_from_tai, Eq(J2000)); EXPECT_THAT(j2000_from_utc, Eq(J2000)); EXPECT_THAT(j2000_tai, Eq(j2000_tai_from_tt)); EXPECT_THAT(j2000_tai - J2000, Eq(32.184 * Second)); // Besselian epochs. constexpr Instant B1900 = "1899-12-31T00:00:00"_TT + 0.8135 * Day; Instant const JD2415020_3135 = JulianDate(2415020.3135); EXPECT_THAT(B1900, AlmostEquals(JD2415020_3135, 51)); EXPECT_THAT(testing_utilities::AbsoluteError(JD2415020_3135, B1900), AllOf(Ge(10 * Micro(Second)), Lt(100 * Micro(Second)))); constexpr Instant B1950 = "1949-12-31T00:00:00"_TT + 0.9235 * Day; Instant const JD2433282_4235 = JulianDate(2433282.4235); EXPECT_THAT(B1950, AlmostEquals(JD2433282_4235, 26)); EXPECT_THAT(testing_utilities::AbsoluteError(JD2433282_4235, B1950), AllOf(Ge(1 * Micro(Second)), Lt(10 * Micro(Second)))); }
TEST_F(TimeScalesTest, StretchyRates) { // Check that cancellations aren't destroying the test. EXPECT_NE("1961-01-01T00:00:00"_UTC + 1 * Minute / (1 - 150e-10), "1961-01-01T00:00:00"_UTC + 1 * Minute / (1 - 130e-10)); quantities::Time utc_minute; utc_minute = 1 * Minute / (1 - 150e-10); EXPECT_THAT("1961-01-01T00:00:00"_UTC + utc_minute, Eq("1961-01-01T00:01:00"_UTC)); EXPECT_THAT("1961-12-31T23:59:00"_UTC + utc_minute, Eq("1961-12-31T24:00:00"_UTC)); utc_minute = 1 * Minute / (1 - 130e-10); EXPECT_THAT("1962-01-01T00:00:00"_UTC + utc_minute, Eq("1962-01-01T00:01:00"_UTC)); EXPECT_THAT("1963-12-31T23:59:00"_UTC + utc_minute, Eq("1963-12-31T24:00:00"_UTC)); utc_minute = 1 * Minute / (1 - 150e-10); EXPECT_THAT("1964-01-01T00:00:00"_UTC + utc_minute, Eq("1964-01-01T00:01:00"_UTC)); EXPECT_THAT("1965-12-31T23:59:00"_UTC + utc_minute, AlmostEquals("1965-12-31T24:00:00"_UTC, 1)); utc_minute = 1 * Minute / (1 - 300e-10); EXPECT_THAT("1966-01-01T00:00:00"_UTC + utc_minute, Eq("1966-01-01T00:01:00"_UTC)); EXPECT_THAT("1971-12-31T23:58:00"_UTC + utc_minute, Eq("1971-12-31T23:59:00"_UTC)); utc_minute = 1 * Minute; EXPECT_THAT("1972-01-01T00:00:00"_UTC + utc_minute, Eq("1972-01-01T00:01:00"_UTC)); EXPECT_THAT("2000-01-01T00:00:00"_UTC + utc_minute, Eq("2000-01-01T00:01:00"_UTC)); }
TEST_F(KeplerOrbitTest, EarthMoon) { SolarSystem<ICRFJ2000Equator> solar_system; solar_system.Initialize( SOLUTION_DIR / "astronomy" / "gravity_model.proto.txt", SOLUTION_DIR / "astronomy" / "initial_state_jd_2433282_500000000.proto.txt"); auto const earth = SolarSystem<ICRFJ2000Equator>::MakeMassiveBody( solar_system.gravity_model_message("Earth")); auto const moon = SolarSystem<ICRFJ2000Equator>::MakeMassiveBody( solar_system.gravity_model_message("Moon")); // The numbers in the gravity models and those from the query above both come // from DE431, so the sums are the same up to round-off. EXPECT_THAT( earth->gravitational_parameter() + moon->gravitational_parameter(), AlmostEquals( 4.0350323550225975e+05 * (Pow<3>(Kilo(Metre)) / Pow<2>(Second)), 1)); Instant const date = JulianDate(2457397.500000000); KeplerianElements<ICRFJ2000Equator> elements; elements.eccentricity = 4.772161502830355e-02; elements.semimajor_axis = 3.870051955415476e+05 * Kilo(Metre); elements.inclination = 1.842335956339145e+01 * Degree; elements.longitude_of_ascending_node = 1.752118723367974e+00 * Degree; elements.argument_of_periapsis = 3.551364385683149e+02 * Degree; elements.mean_anomaly = 2.963020996150547e+02 * Degree; KeplerOrbit<ICRFJ2000Equator> moon_orbit(*earth, *moon, elements, date); Displacement<ICRFJ2000Equator> const expected_displacement( { 1.177367562036580e+05 * Kilo(Metre), -3.419908628150604e+05 * Kilo(Metre), -1.150659799281941e+05 * Kilo(Metre)}); Velocity<ICRFJ2000Equator> const expected_velocity( {9.745048087261129e-01 * (Kilo(Metre) / Second), 3.500672337210811e-01 * (Kilo(Metre) / Second), 1.066306010215636e-01 * (Kilo(Metre) / Second)}); EXPECT_THAT(moon_orbit.StateVectors(date).displacement(), AlmostEquals(expected_displacement, 13)); EXPECT_THAT(moon_orbit.StateVectors(date).velocity(), AlmostEquals(expected_velocity, 12)); EXPECT_THAT(*moon_orbit.elements_at_epoch().mean_motion, AlmostEquals(1.511718576836574e-04 * (Degree / Second), 2)); elements.semimajor_axis = std::experimental::nullopt; elements.mean_motion = 1.511718576836574e-04 * (Degree / Second); KeplerOrbit<ICRFJ2000Equator> moon_orbit_n(*earth, *moon, elements, date); EXPECT_THAT(moon_orbit_n.StateVectors(date).displacement(), AlmostEquals(expected_displacement, 13, 15)); EXPECT_THAT(moon_orbit_n.StateVectors(date).velocity(), AlmostEquals(expected_velocity, 12)); KeplerOrbit<ICRFJ2000Equator> moon_orbit_from_state_vectors( *earth, *moon, {expected_displacement, expected_velocity}, date); EXPECT_THAT(moon_orbit_from_state_vectors.elements_at_epoch().eccentricity, AlmostEquals(moon_orbit.elements_at_epoch().eccentricity, 8)); EXPECT_THAT(*moon_orbit_from_state_vectors.elements_at_epoch().semimajor_axis, AlmostEquals(*moon_orbit.elements_at_epoch().semimajor_axis, 1)); EXPECT_THAT(*moon_orbit_from_state_vectors.elements_at_epoch().mean_motion, AlmostEquals(*moon_orbit.elements_at_epoch().mean_motion, 1)); EXPECT_THAT(moon_orbit_from_state_vectors.elements_at_epoch().inclination, AlmostEquals(moon_orbit.elements_at_epoch().inclination, 1)); EXPECT_THAT( moon_orbit_from_state_vectors.elements_at_epoch() .longitude_of_ascending_node, AlmostEquals(moon_orbit.elements_at_epoch().longitude_of_ascending_node, 28)); EXPECT_THAT( moon_orbit_from_state_vectors.elements_at_epoch().argument_of_periapsis, AlmostEquals(moon_orbit.elements_at_epoch().argument_of_periapsis, 6)); EXPECT_THAT(moon_orbit_from_state_vectors.elements_at_epoch().mean_anomaly, AlmostEquals(moon_orbit.elements_at_epoch().mean_anomaly, 6)); }