Skip to content

Commit

Permalink
Merge pull request #2566 from eggrobin/api
Browse files Browse the repository at this point in the history
Three new API functions
  • Loading branch information
eggrobin authored May 16, 2020
2 parents 05281ea + c14cb10 commit f56457c
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 2 deletions.
130 changes: 130 additions & 0 deletions ksp_plugin/interface_external.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Up @@ -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(
Expand All @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion ksp_plugin_adapter/interface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
}
Expand Down
69 changes: 68 additions & 1 deletion serialization/journal.proto
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ message NavigationFrameParameters {
}

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

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

message SetAngularMomentumConservation {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit f56457c

Please sign in to comment.