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

Three new API functions #2566

Merged
merged 5 commits into from
May 16, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions ksp_plugin/interface_external.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ 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;
Expand All @@ -43,6 +45,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"));
}
Instant const t = FromGameTime(*plugin, time);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move down, closer to the place where you need it.

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();
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"));
}
Instant const t = FromGameTime(*plugin, time);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move down, closer to the place where you need it.

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();
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>;
auto const to_world_axes =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use a real type instead of auto.

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 +351,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"));
}
Instant const t = FromGameTime(*plugin, time);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move down, closer to the place where you need it.

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();
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