Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Dynamics_Thruster(pybind11::module&
Args:
satellite_system (SatelliteSystem): The satellite system.
guidance_law (GuidanceLaw): The guidance law used to compute the acceleration vector.
name (str): The name of the thruster.

name (str, optional): The name of the thruster. Defaults to String.empty().
)doc"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Flight_Maneuver(pybind11::module& aM

using ostk::mathematics::curvefitting::Interpolator;

using ostk::physics::unit::Angle;

using ostk::astrodynamics::flight::Maneuver;

class_<Maneuver>(
Expand Down Expand Up @@ -130,6 +132,43 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Flight_Maneuver(pybind11::module& aM
Tabulated: The tabulated dynamics.
)doc"
)
.def(
"calculate_mean_thrust_direction_and_maximum_angular_offset",
&Maneuver::calculateMeanThrustDirectionAndMaximumAngularOffset,
arg("local_orbital_frame_factory"),
R"doc(
Calculate the mean thrust direction in the Local Orbital Frame and its maximum angular offset w.r.t. the maneuver's thrust acceleration directions.

Args:
local_orbital_frame_factory (LocalOrbitalFrameFactory): The local orbital frame factory.

Returns:
Tuple[LocalOrbitalFrameDirection, Angle]: The mean thrust direction and its maximum angular offset.
)doc"
)
.def(
"to_constant_local_orbital_frame_direction_maneuver",
&Maneuver::toConstantLocalOrbitalFrameDirectionManeuver,
arg("local_orbital_frame_factory"),
arg_v("maximum_allowed_angular_offset", Angle::Undefined(), "Angle.Undefined()"),
R"doc(
Create a maneuver with a constant thrust acceleration direction in the Local Orbital Frame.

The new Maneuver contains the same states as the original Maneuver, but the thrust acceleration direction is
constant in the Local Orbital Frame. Said direction is the mean direction of the thrust acceleration directions
in the Local Orbital Frame of the original Maneuver. The thrust acceleration magnitude profile is the same as the original.

If defined, a runtime error will be thrown if the maximum allowed angular offset between the original thrust acceleration direction
and the mean thrust direction is violated.

Args:
local_orbital_frame_factory (LocalOrbitalFrameFactory): The local orbital frame factory.
maximum_allowed_angular_offset (Angle, optional): The maximum allowed angular offset to consider (if any). Defaults to Undefined.

Returns:
Maneuver: The constant local orbital frame direction maneuver.
)doc"
)
.def_static(
"constant_mass_flow_rate_profile",
&Maneuver::ConstantMassFlowRateProfile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Flight_Profile(pybind11::module& aMo
Constructor.

Args:
orientation_profile (list[Tuple[Instant, Vector3d]]): The orientation profile.
orientation_profile (list[tuple[Instant, Vector3d]]): The orientation profile.
axis (Profile.Axis): The axis.
anti_direction (bool): True if the direction is flipped, False otherwise. Defaults to False.
)doc",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <OpenSpaceToolkit/Astrodynamics/GuidanceLaw.hpp>

#include <OpenSpaceToolkitAstrodynamicsPy/GuidanceLaw/ConstantThrust.cpp>
#include <OpenSpaceToolkitAstrodynamicsPy/GuidanceLaw/HeterogeneousGuidanceLaw.cpp>
#include <OpenSpaceToolkitAstrodynamicsPy/GuidanceLaw/QLaw.cpp>

using namespace pybind11;
Expand Down Expand Up @@ -120,4 +121,5 @@ void OpenSpaceToolkitAstrodynamicsPy_GuidanceLaw(pybind11::module& aModule)
// Add objects to "guidance_law" submodule
OpenSpaceToolkitAstrodynamicsPy_GuidanceLaw_ConstantThrust(guidance_law);
OpenSpaceToolkitAstrodynamicsPy_GuidanceLaw_QLaw(guidance_law);
OpenSpaceToolkitAstrodynamicsPy_GuidanceLaw_HeterogeneousGuidanceLaw(guidance_law);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ inline void OpenSpaceToolkitAstrodynamicsPy_GuidanceLaw_ConstantThrust(pybind11:
aModule,
"ConstantThrust",
R"doc(
Constant Thrust, Constant Direction dynamics.
Constant Thrust, Constant Direction guidance law.

)doc"
)
Expand Down Expand Up @@ -78,17 +78,40 @@ inline void OpenSpaceToolkitAstrodynamicsPy_GuidanceLaw_ConstantThrust(pybind11:
"intrack",
&ConstantThrust::Intrack,
R"doc(
Create a constant thrust in the in-track direction.
Create a constant thrust guidance law in the in-track direction.

Args:
satellite_system (SatelliteSystem): The satellite system.
velocity_direction (bool, optional): If True, the thrust is applied in the velocity direction. Otherwise, it is applied in the opposite direction.
frame (Frame, optional): The reference frame.
velocity_direction (bool, optional): If True, the thrust is applied in the velocity direction. Otherwise, it is applied in the opposite direction. Defaults to True.

Returns:
ConstantThrust: The constant thrust.
ConstantThrust: The constant thrust guidance law in the in-track direction.
)doc",
arg("velocity_direction") = true
arg_v("velocity_direction", true, "True")
)

.def_static(
"from_maneuver",
&ConstantThrust::FromManeuver,
R"doc(
Create a constant thrust guidance law from a maneuver.

The local orbital frame maneuver's mean thrust direction is calculated and used to create a
constant thrust guidance law in said direction.

If defined, a runtime error will be thrown if the maximum allowed angular offset between the original thrust acceleration
direction and the mean thrust direction is violated.

Args:
maneuver (Maneuver): The maneuver.
local_orbital_frame_factory (LocalOrbitalFrameFactory): The local orbital frame factory.
maximum_allowed_angular_offset (Angle, optional): The maximum allowed angular offset to consider (if any). Defaults to Undefined.

Returns:
ConstantThrust: The constant thrust guidance law.
)doc",
arg("maneuver"),
arg("local_orbital_frame_factory"),
arg_v("maximum_allowed_angular_offset", Angle::Undefined(), "Angle.Undefined()")
)

;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/// Apache License 2.0

#include <OpenSpaceToolkit/Astrodynamics/GuidanceLaw/HeterogeneousGuidanceLaw.hpp>

using namespace pybind11;

using ostk::core::container::Array;
using ostk::core::container::Pair;
using ostk::core::type::Shared;

using ostk::mathematics::object::Vector3d;

using ostk::physics::coordinate::Frame;
using ostk::physics::time::Instant;
using ostk::physics::time::Interval;

using ostk::astrodynamics::GuidanceLaw;
using ostk::astrodynamics::guidancelaw::HeterogeneousGuidanceLaw;

inline void OpenSpaceToolkitAstrodynamicsPy_GuidanceLaw_HeterogeneousGuidanceLaw(pybind11::module& aModule)
{
class_<HeterogeneousGuidanceLaw, GuidanceLaw, Shared<HeterogeneousGuidanceLaw>>(
aModule,
"HeterogeneousGuidanceLaw",
R"doc(
A guidance law that sequences multiple guidance laws over specific time intervals.

At each point in time, the applicable guidance law is selected and used to calculate
the thrust acceleration. Guidance laws don't need to be contiguous, and can be added
in any order. If the instant does not fall within any of the intervals, the thrust
acceleration is zero. The guidance law intervals must not intersect each other.
)doc"
)

.def(
init<const Array<Pair<Shared<GuidanceLaw>, Interval>>&>(),
arg_v("guidance_laws_with_intervals", Array<Pair<Shared<GuidanceLaw>, Interval>>::Empty(), "[]"),
R"doc(
Constructor.

Args:
guidance_laws_with_intervals (list[tuple[GuidanceLaw, Interval]], optional): Array of tuples containing the guidance laws and their corresponding intervals. Defaults to empty array.

Raises:
RuntimeError: If any interval is undefined, if the guidance law is null or if the interval intersects with an existing interval.
)doc"
)

.def(
"get_guidance_laws_with_intervals",
&HeterogeneousGuidanceLaw::getGuidanceLawsWithIntervals,
R"doc(
Get the guidance laws with their corresponding intervals.

Returns:
list[tuple[GuidanceLaw, Interval]]: Array of tuples containing the guidance laws and their corresponding intervals.
)doc"
)

.def(
"add_guidance_law",
&HeterogeneousGuidanceLaw::addGuidanceLaw,
arg("guidance_law"),
arg("interval"),
R"doc(
Add a guidance law with its corresponding interval.

Args:
guidance_law (GuidanceLaw): The guidance law to add.
interval (Interval): The interval during which the guidance law is active.

Raises:
RuntimeError: If the interval is undefined, if the guidance law is null or if the interval intersects with an existing interval.
)doc"
)

.def(
"calculate_thrust_acceleration_at",
&HeterogeneousGuidanceLaw::calculateThrustAccelerationAt,
arg("instant"),
arg("position_coordinates"),
arg("velocity_coordinates"),
arg("thrust_acceleration"),
arg("output_frame"),
R"doc(
Calculate thrust acceleration at a given instant and state.

Args:
instant (Instant): The instant.
position_coordinates (numpy.ndarray): The position coordinates.
velocity_coordinates (numpy.ndarray): The velocity coordinates.
thrust_acceleration (float): The thrust acceleration magnitude.
output_frame (Frame): The frame in which the acceleration is expressed.

Returns:
numpy.ndarray: The acceleration vector at the provided coordinates.
)doc"
)

.def("__str__", &(shiftToString<HeterogeneousGuidanceLaw>))
.def("__repr__", &(shiftToString<HeterogeneousGuidanceLaw>))

;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Trajectory_Segment(pybind11::module&
using ostk::core::type::String;

using ostk::physics::time::Duration;
using ostk::physics::unit::Angle;

using ostk::astrodynamics::Dynamics;
using ostk::astrodynamics::flight::Maneuver;
using ostk::astrodynamics::trajectory::LocalOrbitalFrameFactory;
using ostk::astrodynamics::trajectory::Segment;
using ostk::astrodynamics::trajectory::state::CoordinateSubset;
using ostk::astrodynamics::trajectory::state::NumericalSolver;
Expand Down Expand Up @@ -420,5 +422,39 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Trajectory_Segment(pybind11::module&
)doc"
)

.def_static(
"constant_local_orbital_frame_direction_maneuver",
&Segment::ConstantLocalOrbitalFrameDirectionManeuver,
arg("name"),
arg("event_condition"),
arg("thruster_dynamics"),
arg("dynamics"),
arg("numerical_solver"),
arg("local_orbital_frame_factory"),
arg_v("maximum_allowed_angular_offset", Angle::Undefined(), "Angle.Undefined()"),
R"doc(
Create a maneuvering segment that produces maneuvers with a constant direction in the local orbital frame.

The provided thruster dynamics are used to solve the segment at first. The maneuvers produced by this segement solution
are then used to create a new thruster dynamics with a constant direction in the local orbital frame. This new thruster dynamics
is then used to actually solve the segment.

If defined, a runtime error will be thrown if the maximum allowed angular offset between the original thruster dynamics
and the mean thrust direction is violated.

Args:
name (str): The name of the segment.
event_condition (EventCondition): The event condition.
thruster_dynamics (ThrusterDynamics): The thruster dynamics.
dynamics (Dynamics): The dynamics.
numerical_solver (NumericalSolver): The numerical solver.
local_orbital_frame_factory (LocalOrbitalFrameFactory): The local orbital frame factory.
maximum_allowed_angular_offset (Angle, optional): The maximum allowed angular offset to consider (if any). Defaults to Angle.undefined().

Returns:
Segment: The maneuver segment.
)doc"
)

;
}
27 changes: 21 additions & 6 deletions bindings/python/test/dynamics/test_thruster.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from ostk.astrodynamics.trajectory import State
from ostk.astrodynamics.flight.system import PropulsionSystem
from ostk.astrodynamics.flight.system import SatelliteSystem
from ostk.astrodynamics import Dynamics
from ostk.astrodynamics.dynamics import Thruster
from ostk.astrodynamics.guidance_law import ConstantThrust

Expand Down Expand Up @@ -96,11 +95,27 @@ def state(coordinate_broker: CoordinateBroker) -> State:


class TestThruster:
def test_constructors(self, dynamics: Thruster):
assert dynamics is not None
assert isinstance(dynamics, Thruster)
assert isinstance(dynamics, Dynamics)
assert dynamics.is_defined()
def test_constructors(
self,
guidance_law: ConstantThrust,
satellite_system: SatelliteSystem,
):
thrusters = [
Thruster(
satellite_system=satellite_system,
guidance_law=guidance_law,
),
Thruster(
satellite_system=satellite_system,
guidance_law=guidance_law,
name="A name",
),
]

for thruster in thrusters:
assert thruster is not None
assert isinstance(thruster, Thruster)
assert thruster.is_defined()

def test_getters(self, dynamics: Thruster):
assert dynamics.get_satellite_system() is not None
Expand Down
Loading