Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 05281ea21caf
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f56457cd700e
Choose a head ref
  • 6 commits
  • 4 files changed
  • 2 contributors

Commits on May 10, 2020

  1. 2542

    eggrobin committed May 10, 2020
    Copy the full SHA
    4db8c4c View commit details
  2. Copy the full SHA
    01d68c2 View commit details
  3. degrees

    eggrobin committed May 10, 2020
    Copy the full SHA
    d480333 View commit details

Commits on May 15, 2020

  1. Changes from my review.

    pleroy authored May 15, 2020
    Copy the full SHA
    426dd1e View commit details
  2. Fix compilation errors.

    pleroy authored May 15, 2020
    Copy the full SHA
    c14cb10 View commit details

Commits on May 16, 2020

  1. Merge pull request #2566 from eggrobin/api

    Three new API functions
    eggrobin authored May 16, 2020
    Copy the full SHA
    f56457c View commit details
Showing with 226 additions and 2 deletions.
  1. +130 −0 ksp_plugin/interface_external.cpp
  2. +27 −0 ksp_plugin_adapter/external_interface.cs
  3. +1 −1 ksp_plugin_adapter/interface.cs
  4. +68 −1 serialization/journal.proto
130 changes: 130 additions & 0 deletions ksp_plugin/interface_external.cpp
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
#include "base/status_or.hpp"
#include "journal/method.hpp"
#include "journal/profiles.hpp"
#include "ksp_plugin/frames.hpp"
#include "physics/apsides.hpp"

namespace principia {
@@ -19,9 +20,12 @@ using base::Error;
using base::StatusOr;
using base::UniqueArray;
using geometry::AngularVelocity;
using geometry::Frame;
using geometry::RadiusLatitudeLongitude;
using ksp_plugin::FlightPlan;
using ksp_plugin::Navigation;
using ksp_plugin::Vessel;
using ksp_plugin::WorldSun;
using physics::BodyCentredNonRotatingDynamicFrame;
using physics::ComputeApsides;
using physics::DiscreteTrajectory;
@@ -43,6 +47,95 @@ Status OK() {

} // namespace

Status __cdecl principia__ExternalCelestialGetPosition(
Plugin const* const plugin,
int const body_index,
double const time,
XYZ* const position) {
journal::Method<journal::ExternalCelestialGetPosition> m{
{plugin,
body_index,
time},
{position}};
if (plugin == nullptr) {
return m.Return(
MakeStatus(Error::INVALID_ARGUMENT, "|plugin| must not be null"));
}
if (!plugin->HasCelestial(body_index)) {
return m.Return(MakeStatus(
Error::NOT_FOUND,
absl::StrCat("No celestial with index ", body_index)));
}
auto const& celestial = plugin->GetCelestial(body_index);
auto const& trajectory = celestial.trajectory();
Instant const t = FromGameTime(*plugin, time);
if (t < trajectory.t_min() || t > trajectory.t_max()) {
return m.Return(
MakeStatus(Error::OUT_OF_RANGE,
(std::stringstream{}
<< "|time| " << t << " does not lie within the domain ["
<< trajectory.t_min() << ", " << trajectory.t_max()
<< "] of the trajectory of " << celestial.body()->name())
.str()));
}
auto const from_solar_system_barycentre =
plugin->renderer().BarycentricToWorldSun(plugin->PlanetariumRotation())(
trajectory.EvaluatePosition(t) - Barycentric::origin);
*position = ToXYZ(from_solar_system_barycentre.coordinates() / Metre);
return m.Return(OK());
}

Status __cdecl principia__ExternalCelestialGetSurfacePosition(
Plugin const* const plugin,
int const body_index,
double const planetocentric_latitude_in_degrees,
double const planetocentric_longitude_in_degrees,
double const radius,
double const time,
XYZ* const position) {
journal::Method<journal::ExternalCelestialGetSurfacePosition> m{
{plugin,
body_index,
planetocentric_latitude_in_degrees,
planetocentric_longitude_in_degrees,
radius,
time},
{position}};
if (plugin == nullptr) {
return m.Return(
MakeStatus(Error::INVALID_ARGUMENT, "|plugin| must not be null"));
}
if (!plugin->HasCelestial(body_index)) {
return m.Return(MakeStatus(
Error::NOT_FOUND,
absl::StrCat("No celestial with index ", body_index)));
}
auto const& celestial = plugin->GetCelestial(body_index);
auto const& trajectory = celestial.trajectory();
Instant const t = FromGameTime(*plugin, time);
if (t < trajectory.t_min() || t > trajectory.t_max()) {
return m.Return(
MakeStatus(Error::OUT_OF_RANGE,
(std::stringstream{}
<< "|time| " << t << " does not lie within the domain ["
<< trajectory.t_min() << ", " << trajectory.t_max()
<< "] of the trajectory of " << celestial.body()->name())
.str()));
}
using Surface = Frame<enum class SurfaceTag>;
OrthogonalMap<Surface, WorldSun> const to_world_axes =
plugin->renderer().BarycentricToWorldSun(plugin->PlanetariumRotation()) *
celestial.body()->FromSurfaceFrame<Surface>(t).Forget<OrthogonalMap>();
auto const planetocentric_displacement = Displacement<Surface>(
RadiusLatitudeLongitude(radius * Metre,
planetocentric_latitude_in_degrees * Degree,
planetocentric_longitude_in_degrees * Degree)
.ToCartesian());
*position =
ToXYZ(to_world_axes(planetocentric_displacement).coordinates() / Metre);
return m.Return(OK());
}

Status __cdecl principia__ExternalFlowFreefall(
Plugin const* const plugin,
int const central_body_index,
@@ -260,5 +353,42 @@ Status __cdecl principia__ExternalGetNearestPlannedCoastDegreesOfFreedom(
return m.Return(OK());
}

Status __cdecl principia__ExternalVesselGetPosition(
Plugin const* const plugin,
char const* const vessel_guid,
double const time,
XYZ* const position) {
journal::Method<journal::ExternalVesselGetPosition> m{
{plugin,
vessel_guid,
time},
{position}};
if (plugin == nullptr) {
return m.Return(
MakeStatus(Error::INVALID_ARGUMENT, "|plugin| must not be null"));
}
if (!plugin->HasVessel(vessel_guid)) {
return m.Return(MakeStatus(
Error::NOT_FOUND,
absl::StrCat("No vessel with GUID ", vessel_guid)));
}
auto const& vessel = *plugin->GetVessel(vessel_guid);
auto const& trajectory = vessel.psychohistory();
Instant const t = FromGameTime(*plugin, time);
if (t < trajectory.t_min() || t > trajectory.t_max()) {
return m.Return(MakeStatus(
Error::OUT_OF_RANGE,
(std::stringstream{}
<< "|time| " << t << " does not lie within the domain ["
<< trajectory.t_min() << ", " << trajectory.t_max()
<< "] of the psychohistory of " << vessel.ShortDebugString()).str()));
}
auto const from_solar_system_barycentre =
plugin->renderer().BarycentricToWorldSun(plugin->PlanetariumRotation())(
trajectory.EvaluatePosition(t) - Barycentric::origin);
*position = ToXYZ(from_solar_system_barycentre.coordinates() / Metre);
return m.Return(OK());
}

} // namespace interface
} // namespace principia
27 changes: 27 additions & 0 deletions ksp_plugin_adapter/external_interface.cs
Original file line number Diff line number Diff line change
@@ -6,6 +6,26 @@ namespace principia {
namespace ksp_plugin_adapter {

public class ExternalInterface {
public XYZ CelestialGetPosition(int body_index, double time) {
ThrowOnError(
adapter_.Plugin().ExternalCelestialGetPosition(
body_index, time, out XYZ result));
return result;
}

public XYZ CelestialGetSurfacePosition(
int body_index,
double planetocentric_latitude_in_degrees,
double planetocentric_longitude_in_degrees,
double radius,
double time) {
ThrowOnError(
adapter_.Plugin().ExternalCelestialGetSurfacePosition(
body_index, planetocentric_latitude_in_degrees,
planetocentric_longitude_in_degrees, radius, time, out XYZ result));
return result;
}

public XY GeopotentialGetCoefficient(int body_index, int degree, int order) {
ThrowOnError(
adapter_.Plugin().ExternalGeopotentialGetCoefficient(
@@ -20,6 +40,13 @@ public double GeopotentialGetReferenceRadius(int body_index) {
return result;
}

public XYZ VesselGetPosition(string vessel_guid, double time) {
ThrowOnError(
adapter_.Plugin().ExternalVesselGetPosition(
vessel_guid, time, out XYZ result));
return result;
}

public static ExternalInterface Get() {
List<ScenarioModule> modules;
try {
2 changes: 1 addition & 1 deletion ksp_plugin_adapter/interface.cs
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ public void Update(Status s) {
}
}

internal partial struct XYZ {
public partial struct XYZ {
public static explicit operator XYZ(Vector3d v) {
return new XYZ{x = v.x, y = v.y, z = v.z};
}
69 changes: 68 additions & 1 deletion serialization/journal.proto
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ message NavigationFrameParameters {
}

message XYZ {
option (is_public) = true;
required double x = 1;
required double y = 2;
required double z = 3;
@@ -210,7 +211,7 @@ message OrbitAnalysis {
}

message Method {
extensions 5000 to 5999; // Last used: 5169.
extensions 5000 to 5999; // Last used: 5172.
}

message SetAngularMomentumConservation {
@@ -518,6 +519,51 @@ message EndInitialization {
// These functions form the external API of Principia; announce deprecation one
// lunation ahead, then make them return UNIMPLEMENTED.

message ExternalCelestialGetPosition {
extend Method {
optional ExternalCelestialGetPosition extension = 5170;
}
message In {
required fixed64 plugin = 1 [(pointer_to) = "Plugin const",
(is_subject) = true];
required int32 body_index = 2;
required double time = 3;
}
message Out {
required XYZ position = 1;
}
message Return {
required Status result = 1;
}
optional In in = 1;
optional Out out = 2;
optional Return return = 3;
}

message ExternalCelestialGetSurfacePosition {
extend Method {
optional ExternalCelestialGetSurfacePosition extension = 5171;
}
message In {
required fixed64 plugin = 1 [(pointer_to) = "Plugin const",
(is_subject) = true];
required int32 body_index = 2;
required double planetocentric_latitude_in_degrees = 3;
required double planetocentric_longitude_in_degrees = 4;
required double radius = 5;
required double time = 6;
}
message Out {
required XYZ position = 1;
}
message Return {
required Status result = 1;
}
optional In in = 1;
optional Out out = 2;
optional Return return = 3;
}

// Not yet implemented.
// Solves a free-fall initial value problem, where the initial degrees of
// freedom and those of the result are given in world coordinates in the
@@ -594,6 +640,27 @@ message ExternalGeopotentialGetReferenceRadius {
optional Return return = 3;
}

message ExternalVesselGetPosition {
extend Method {
optional ExternalVesselGetPosition extension = 5172;
}
message In {
required fixed64 plugin = 1 [(pointer_to) = "Plugin const",
(is_subject) = true];
required string vessel_guid = 2;
required double time = 3;
}
message Out {
required XYZ position = 1;
}
message Return {
required Status result = 1;
}
optional In in = 1;
optional Out out = 2;
optional Return return = 3;
}

// Returns the first point of the coast phase following the given manoeuvre
// which is locally nearest to the reference position, or the nearest endpoint
// if there is no local minimum.