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: 776b1288ec7f
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0e005a0bd011
Choose a head ref
  • 4 commits
  • 5 files changed
  • 1 contributor

Commits on Jul 12, 2020

  1. Parachute torque

    eggrobin committed Jul 12, 2020
    Copy the full SHA
    f55357e View commit details

Commits on Jul 14, 2020

  1. C++

    eggrobin committed Jul 14, 2020
    Copy the full SHA
    4dbc6fa View commit details
  2. blank line

    eggrobin committed Jul 14, 2020
    Copy the full SHA
    dbf52d9 View commit details
  3. Merge pull request #2644 from eggrobin/ejection

    Parachute torque
    eggrobin authored Jul 14, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0e005a0 View commit details
Showing with 141 additions and 15 deletions.
  1. +45 −6 ksp_plugin/interface.cpp
  2. +3 −0 ksp_plugin/interface.hpp
  3. +24 −6 ksp_plugin/interface_body.hpp
  4. +51 −2 ksp_plugin_adapter/ksp_plugin_adapter.cs
  5. +18 −1 serialization/journal.proto
51 changes: 45 additions & 6 deletions ksp_plugin/interface.cpp
Original file line number Diff line number Diff line change
@@ -334,6 +334,47 @@ void __cdecl principia__ActivateRecorder(bool const activate) {
}
}

XYZ __cdecl principia__AngularMomentumFromAngularVelocity(
XYZ world_angular_velocity,
XYZ moments_of_inertia_in_tonnes,
WXYZ principal_axes_rotation,
WXYZ part_rotation) {
journal::Method<journal::AngularMomentumFromAngularVelocity> m(
{world_angular_velocity,
moments_of_inertia_in_tonnes,
principal_axes_rotation,
part_rotation});
using PartPrincipalAxes = Frame<serialization::Frame::PhysicsTag,
Arbitrary,
Handedness::Left,
serialization::Frame::PRINCIPAL_AXES>;

auto const angular_velocity =
FromXYZ<AngularVelocity<World>>(world_angular_velocity);

static constexpr MomentOfInertia zero;
auto const moments_of_inertia =
FromXYZ<R3Element<MomentOfInertia>>({moments_of_inertia_in_tonnes.x,
moments_of_inertia_in_tonnes.y,
moments_of_inertia_in_tonnes.z});
InertiaTensor<PartPrincipalAxes> const inertia_tensor_in_princial_axes(
R3x3Matrix<MomentOfInertia>({moments_of_inertia.x, zero, zero},
{zero, moments_of_inertia.y, zero},
{zero, zero, moments_of_inertia.z}));

Rotation<PartPrincipalAxes, RigidPart> const principal_axes_to_part(
FromWXYZ(principal_axes_rotation));
Rotation<RigidPart, World> const part_to_world(FromWXYZ(part_rotation));

InertiaTensor<World> const inertia_tensor =
part_to_world(principal_axes_to_part(inertia_tensor_in_princial_axes));

Bivector<AngularMomentum, World> angular_momentum =
inertia_tensor * angular_velocity;

return m.Return(ToXYZ(angular_momentum));
}

void __cdecl principia__AdvanceTime(Plugin* const plugin,
double const t,
double const planetarium_rotation) {
@@ -848,13 +889,11 @@ void __cdecl principia__InsertOrKeepLoadedPart(
serialization::Frame::PRINCIPAL_AXES>;

static constexpr MomentOfInertia zero;
static constexpr double to_si_unit =
Tonne * Pow<2>(Metre) / si::Unit<MomentOfInertia>;

auto const moments_of_inertia = FromXYZ<R3Element<MomentOfInertia>>(
{moments_of_inertia_in_tonnes.x * to_si_unit,
moments_of_inertia_in_tonnes.y * to_si_unit,
moments_of_inertia_in_tonnes.z * to_si_unit});
auto const moments_of_inertia =
FromXYZ<R3Element<MomentOfInertia>>({moments_of_inertia_in_tonnes.x,
moments_of_inertia_in_tonnes.y,
moments_of_inertia_in_tonnes.z});
InertiaTensor<PartPrincipalAxes> const inertia_tensor_in_princial_axes(
R3x3Matrix<MomentOfInertia>({moments_of_inertia.x, zero, zero},
{zero, moments_of_inertia.y, zero},
3 changes: 3 additions & 0 deletions ksp_plugin/interface.hpp
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@ using base::not_null;
using base::PullSerializer;
using base::PushDeserializer;
using geometry::AngularVelocity;
using geometry::Bivector;
using geometry::Displacement;
using geometry::Instant;
using geometry::Position;
@@ -60,6 +61,7 @@ using ksp_plugin::World;
using physics::DegreesOfFreedom;
using physics::Frenet;
using physics::RelativeDegreesOfFreedom;
using quantities::AngularMomentum;
using quantities::Length;
using quantities::MomentOfInertia;

@@ -171,6 +173,7 @@ XYZ ToXYZ(geometry::R3Element<double> const& r3_element);
XYZ ToXYZ(Position<World> const& position);
XYZ ToXYZ(Vector<double, World> const& direction);
XYZ ToXYZ(Velocity<Frenet<NavigationFrame>> const& velocity);
XYZ ToXYZ(Bivector<AngularMomentum, World> const& angular_momentum);

// Conversions between interchange data and typed data that depend on the state
// of the plugin.
30 changes: 24 additions & 6 deletions ksp_plugin/interface_body.hpp
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ using quantities::si::Degree;
using quantities::si::Metre;
using quantities::si::Radian;
using quantities::si::Second;
using quantities::si::Tonne;
namespace si = quantities::si;

// No partial specialization of functions, so we wrap everything into structs.
@@ -110,17 +111,29 @@ struct XYZConverter<AngularVelocity<Frame>> {
}
};

template<typename Frame>
struct XYZConverter<Bivector<AngularMomentum, Frame>> {
static constexpr AngularMomentum mts_unit =
Pow<2>(Metre) * Tonne * Radian / Second;
static Bivector<AngularMomentum, Frame> FromXYZ(XYZ const& xyz) {
return Bivector<AngularMomentum, Frame>(interface::FromXYZ(xyz) * mts_unit);
}
static XYZ ToXYZ(Bivector<AngularMomentum, Frame> const& velocity) {
return interface::ToXYZ(velocity.coordinates() / mts_unit);
}
};

template<>
struct XYZConverter<R3Element<MomentOfInertia>> {
static constexpr MomentOfInertia mts_unit = Pow<2>(Metre) * Tonne;
static R3Element<MomentOfInertia> FromXYZ(XYZ const& xyz) {
return R3Element<MomentOfInertia>(xyz.x * si::Unit<MomentOfInertia>,
xyz.y * si::Unit<MomentOfInertia>,
xyz.z * si::Unit<MomentOfInertia>);
return R3Element<MomentOfInertia>(
xyz.x * mts_unit, xyz.y * mts_unit, xyz.z * mts_unit);
}
static XYZ ToXYZ(R3Element<MomentOfInertia> const& moments_of_inertia) {
return {moments_of_inertia.x / si::Unit<MomentOfInertia>,
moments_of_inertia.y / si::Unit<MomentOfInertia>,
moments_of_inertia.z / si::Unit<MomentOfInertia>};
return {moments_of_inertia.x / mts_unit,
moments_of_inertia.y / mts_unit,
moments_of_inertia.z / mts_unit};
}
};

@@ -509,6 +522,11 @@ inline XYZ ToXYZ(Velocity<World> const& velocity) {
return XYZConverter<Velocity<World>>::ToXYZ(velocity);
}

inline XYZ ToXYZ(Bivector<AngularMomentum, World> const& angular_momentum) {
return XYZConverter<Bivector<AngularMomentum, World>>::ToXYZ(
angular_momentum);
}

template<typename T>
Interval ToInterval(geometry::Interval<T> const& interval) {
return {interval.min / quantities::si::Unit<T>,
53 changes: 51 additions & 2 deletions ksp_plugin_adapter/ksp_plugin_adapter.cs
Original file line number Diff line number Diff line change
@@ -184,6 +184,10 @@ private KSP.UI.Screens.DebugToolbar.Screens.Cheats.HackGravity hack_gravity {
private readonly Dictionary<uint, Vector3d> part_id_to_intrinsic_force_ =
new Dictionary<uint, Vector3d>();

private readonly Dictionary<Vessel, Vector3d>
parachuting_kerbal_angular_velocities_ =
new Dictionary<Vessel, Vector3d>();

// Work around the launch backflip issue encountered while releasing
// Frobenius.
// The issue is that the position of a |ForceHolder| collected in
@@ -486,6 +490,10 @@ private bool is_unready_kerbal(Vessel vessel) {
return vessel.isEVA && vessel.evaController?.Ready == false;
}

private bool is_parachuting_kerbal(Vessel vessel) {
return vessel.isEVA && vessel.evaController.IsChuteState;
}

private bool is_manageable(Vessel vessel) {
return UnmanageabilityReasons(vessel) == null;
}
@@ -974,11 +982,22 @@ private void FixedUpdate() {
previous_display_mode_ = null;
}

parachuting_kerbal_angular_velocities_.Clear();

if (PluginRunning()) {
plugin_.SetMainBody(
(FlightGlobals.currentMainBody
?? FlightGlobals.GetHomeBody()).flightGlobalsIndex);

foreach (Vessel vessel in
FlightGlobals.Vessels.Where(
v => is_manageable(v) && !v.packed &&
is_parachuting_kerbal(v))) {
parachuting_kerbal_angular_velocities_.Add(
vessel,
vessel.rootPart.rb.angularVelocity);
}

// TODO(egg): Set the degrees of freedom of the origin of |World| (by
// toying with Krakensbane and FloatingOrigin) here.

@@ -1494,8 +1513,38 @@ private void FashionablyLate() {
FlightGlobals.Vessels.Where(v => is_manageable(v) &&
!v.packed)) {
foreach (Part part in vessel.parts.Where(PartIsFaithful)) {
if (part.torque != Vector3d.zero) {
part_id_to_intrinsic_torque_.Add(part.flightID, part.torque);
Vector3d parachute_torque = Vector3d.zero;
if (part == vessel.rootPart &&
is_parachuting_kerbal(vessel) &&
parachuting_kerbal_angular_velocities_.TryGetValue(
vessel, out Vector3d old_angular_velocity)) {
// Instead of applying forces some distance from the centre of mass,
// or applying torques, EVA parachutes directly set the angular
// velocity of the Kerbal. We register a torque equivalent to the
// change in angular momentum; failing to do so would cause the
// parachute to act on the linear motion but not the attitude,
// so that Kerbals would keep spinning under their parachute in
// stock, and would orient themselves head-down (and parachute-down)
// with FAR. See #2607.
// To quote ferram4, “consider it all cursed”.
Vector3d Δω_world = part.rb.angularVelocity - old_angular_velocity;
var ΔL_world =
(Vector3d)Interface.AngularMomentumFromAngularVelocity(
world_angular_velocity: (XYZ)Δω_world,
moments_of_inertia_in_tonnes:
(XYZ)(Vector3d)part.rb.inertiaTensor,
principal_axes_rotation: (WXYZ)(UnityEngine.QuaternionD)
part.rb.inertiaTensorRotation,
part_rotation:
(WXYZ)(UnityEngine.QuaternionD)part.rb.rotation);
double Δt =
Planetarium.TimeScale * Planetarium.fetch.fixedDeltaTime;
parachute_torque = ΔL_world / Δt;
}
if (part.torque != Vector3d.zero ||
parachute_torque != Vector3d.zero) {
part_id_to_intrinsic_torque_.Add(
part.flightID, part.torque + parachute_torque);
}
if (part.force != Vector3d.zero) {
part_id_to_intrinsic_force_.Add(part.flightID, part.force);
19 changes: 18 additions & 1 deletion serialization/journal.proto
Original file line number Diff line number Diff line change
@@ -215,7 +215,7 @@ message OrbitAnalysis {
}

message Method {
extensions 5000 to 5999; // Last used: 5173.
extensions 5000 to 5999; // Last used: 5174.
}

message SetAngularMomentumConservation {
@@ -256,6 +256,23 @@ message AdvanceTime {
optional In in = 1;
}

message AngularMomentumFromAngularVelocity {
extend Method {
optional AngularMomentumFromAngularVelocity extension = 5174;
}
message In {
required XYZ world_angular_velocity = 1;
required XYZ moments_of_inertia_in_tonnes = 2;
required WXYZ principal_axes_rotation = 3;
required WXYZ part_rotation = 4;
}
message Return {
required XYZ result = 1;
}
optional In in = 1;
optional Return return = 3;
}

message CameraReferenceRotation {
extend Method {
optional CameraReferenceRotation extension = 5163;