Skip to content

Commit

Permalink
feat: Trajectory constructor based on a ground strip (#441)
Browse files Browse the repository at this point in the history
* feat: Trajectory constructor based on a ground strip

* Apply suggestions from code review

Co-authored-by: Pau Hebrero <65550121+phc1990@users.noreply.github.com>

* feat: address feedback

---------

Co-authored-by: Pau Hebrero <65550121+phc1990@users.noreply.github.com>
  • Loading branch information
vishwa2710 and phc1990 authored Oct 3, 2024
1 parent 96fc4a0 commit 57f7d7c
Show file tree
Hide file tree
Showing 11 changed files with 564 additions and 54 deletions.
2 changes: 1 addition & 1 deletion bindings/python/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
open-space-toolkit-core~=4.0
open-space-toolkit-io~=4.0
open-space-toolkit-mathematics~=4.1
open-space-toolkit-physics~=9.1
open-space-toolkit-physics~=9.2
69 changes: 69 additions & 0 deletions bindings/python/src/OpenSpaceToolkitAstrodynamicsPy/Trajectory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Trajectory(pybind11::module& aModule
using ostk::core::container::Array;
using ostk::core::type::Shared;

using ostk::physics::coordinate::spherical::LLA;
using ostk::physics::environment::object::Celestial;
using ostk::physics::environment::object::celestial::Earth;
using ostk::physics::time::Duration;
using ostk::physics::unit::Derived;

using ostk::astrodynamics::Trajectory;
using ostk::astrodynamics::trajectory::State;

Expand Down Expand Up @@ -77,6 +83,18 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Trajectory(pybind11::module& aModule
)doc"
)

.def(
"access_model",
&Trajectory::accessModel,
return_value_policy::reference_internal,
R"doc(
Access the model of the trajectory.
Returns:
Model: The model of the trajectory.
)doc"
)

.def(
"get_state_at",
&Trajectory::getStateAt,
Expand Down Expand Up @@ -132,6 +150,57 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Trajectory(pybind11::module& aModule
)doc",
arg("position")
)
.def_static(
"ground_strip",
overload_cast<const LLA&, const LLA&, const Derived&, const Instant&, const Celestial&, const Duration&>(
&Trajectory::GroundStrip
),
R"doc(
Create a `Trajectory` object representing a ground strip.
Computes the duration as the geodetic distance / ground speed.
Instants are generated at a 1 second interval.
Args:
start_lla (LLA): The start LLA.
end_lla (LLA): The end LLA.
ground_speed (Derived): The ground speed.
start_instant (Instant): The start instant.
celestial_object (Celestial): The celestial object. Defaults to Earth.WGS84().
step_size (Duration): The step size. Defaults to 1 second.
Returns:
Trajectory: The `Trajectory` object representing the ground strip.
)doc",
arg("start_lla"),
arg("end_lla"),
arg("ground_speed"),
arg("start_instant"),
arg_v("celestial_object", Earth::WGS84(), "Earth.WGS84()"),
arg_v("step_size", Duration::Seconds(1.0), "Duration.Seconds(1.0)")
)
.def_static(
"ground_strip",
overload_cast<const LLA&, const LLA&, const Array<Instant>&, const Celestial&>(&Trajectory::GroundStrip),
R"doc(
Create a `Trajectory` object representing a ground strip.
This method computes the duration as the geodetic distance / ground speed.
Args:
start_lla (LLA): The start LLA.
end_lla (LLA): The end LLA.
instants (list[Instant]): The instants.
celestial_object (Celestial): The celestial object. Defaults to Earth.WGS84().
Returns:
Trajectory: The `Trajectory` object representing the ground strip.
)doc",
arg("start_lla"),
arg("end_lla"),
arg("instants"),
arg_v("celestial_object", Earth::WGS84(), "Earth.WGS84()")
)

;

Expand Down
154 changes: 116 additions & 38 deletions bindings/python/test/test_trajectory.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,118 @@
# Apache License 2.0

import ostk.mathematics as mathematics

import ostk.physics as physics

import ostk.astrodynamics as astrodynamics

RealInterval = mathematics.object.RealInterval
Quaternion = mathematics.geometry.d3.transformation.rotation.Quaternion
Length = physics.unit.Length
Angle = physics.unit.Angle
DateTime = physics.time.DateTime
Scale = physics.time.Scale
Duration = physics.time.Duration
Instant = physics.time.Instant
Transform = physics.coordinate.Transform
Frame = physics.coordinate.Frame
Axes = physics.coordinate.Axes
DynamicProvider = physics.coordinate.frame.provider.Dynamic
Environment = physics.Environment
Earth = physics.environment.object.celestial.Earth
Trajectory = astrodynamics.Trajectory
Profile = astrodynamics.flight.Profile
SatelliteSystem = astrodynamics.flight.system.SatelliteSystem
Orbit = astrodynamics.trajectory.Orbit
State = astrodynamics.trajectory.State
Pass = astrodynamics.trajectory.orbit.Pass
Kepler = astrodynamics.trajectory.orbit.model.Kepler
COE = astrodynamics.trajectory.orbit.model.kepler.COE
SGP4 = astrodynamics.trajectory.orbit.model.sgp4
Access = astrodynamics.Access


def test_trajectory_undefined():
trajectory: Trajectory = Trajectory.undefined()

assert trajectory is not None
assert isinstance(trajectory, Trajectory)
assert trajectory.is_defined() is False
import pytest

from ostk.physics.environment.object.celestial import Earth
from ostk.physics.coordinate.spherical import LLA
from ostk.physics.coordinate import Position
from ostk.physics.coordinate import Frame
from ostk.physics.time import Instant
from ostk.physics.time import Duration
from ostk.physics.unit import Derived

from ostk.astrodynamics import Trajectory
from ostk.astrodynamics.trajectory import State


@pytest.fixture
def start_lla() -> LLA:
return LLA.vector([0.0, 0.0, 0.0])


@pytest.fixture
def end_lla() -> LLA:
return LLA.vector([1.0, 0.0, 0.0])


@pytest.fixture
def start_instant() -> Instant:
return Instant.J2000()


@pytest.fixture
def ground_speed() -> Derived:
return Derived(7000.0, Derived.Unit.meter_per_second())


@pytest.fixture
def earth() -> Earth:
return Earth.WGS84()


@pytest.fixture
def instants() -> list[Instant]:
return [Instant.J2000(), Instant.J2000() + Duration.seconds(10.0)]


@pytest.fixture
def position() -> Position:
return Position.meters([0.0, 0.0, 0.0], Frame.ITRF())


@pytest.fixture
def trajectory(position: Position) -> Trajectory:
return Trajectory.position(position)


@pytest.fixture
def states(trajectory: Trajectory) -> list[State]:
return trajectory.get_states_at(
[Instant.J2000(), Instant.J2000() + Duration.seconds(10.0)]
)


class TestTrajectory:
def test_trajectory(self, states: list[State]):
assert Trajectory(states) is not None

def test_is_defined(self, trajectory: Trajectory):
assert trajectory.is_defined()

def test_access_model(self, trajectory: Trajectory):
assert trajectory.access_model() is not None

def test_get_state_at(self, trajectory: Trajectory):
assert trajectory.get_state_at(Instant.J2000()) is not None

def test_get_states_at(self, trajectory: Trajectory):
assert (
trajectory.get_states_at(
[Instant.J2000(), Instant.J2000() + Duration.seconds(10.0)]
)
is not None
)

def test_trajectory_undefined(self):
trajectory: Trajectory = Trajectory.undefined()

assert trajectory is not None
assert isinstance(trajectory, Trajectory)
assert trajectory.is_defined() is False

def test_trajectory_position(self, position: Position):
trajectory: Trajectory = Trajectory.position(position)

assert trajectory is not None

def test_ground_strip(
self,
start_lla: LLA,
end_lla: LLA,
ground_speed: Derived,
start_instant: Instant,
earth: Earth,
instants: list[Instant],
):
assert (
Trajectory.ground_strip(
start_lla, end_lla, ground_speed, start_instant, earth
)
is not None
)
assert (
Trajectory.ground_strip(start_lla, end_lla, ground_speed, start_instant)
is not None
)

assert Trajectory.ground_strip(start_lla, end_lla, instants, earth) is not None
assert Trajectory.ground_strip(start_lla, end_lla, instants) is not None
64 changes: 64 additions & 0 deletions include/OpenSpaceToolkit/Astrodynamics/Trajectory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@
#include <OpenSpaceToolkit/Core/Type/Unique.hpp>

#include <OpenSpaceToolkit/Physics/Coordinate/Position.hpp>
#include <OpenSpaceToolkit/Physics/Coordinate/Spherical/LLA.hpp>
#include <OpenSpaceToolkit/Physics/Environment/Object/Celestial.hpp>
#include <OpenSpaceToolkit/Physics/Environment/Object/Celestial/Earth.hpp>
#include <OpenSpaceToolkit/Physics/Time/Duration.hpp>
#include <OpenSpaceToolkit/Physics/Time/Instant.hpp>
#include <OpenSpaceToolkit/Physics/Time/Interval.hpp>
#include <OpenSpaceToolkit/Physics/Unit/Derived.hpp>

#include <OpenSpaceToolkit/Astrodynamics/Trajectory/Model.hpp>
#include <OpenSpaceToolkit/Astrodynamics/Trajectory/State.hpp>
Expand All @@ -22,11 +27,17 @@ namespace astrodynamics

using ostk::core::container::Array;
using ostk::core::type::Index;
using ostk::core::type::Real;
using ostk::core::type::String;
using ostk::core::type::Unique;

using ostk::physics::coordinate::spherical::LLA;
using ostk::physics::environment::object::Celestial;
using ostk::physics::environment::object::celestial::Earth;
using ostk::physics::time::Duration;
using ostk::physics::time::Instant;
using ostk::physics::time::Interval;
using ostk::physics::unit::Derived;

using ostk::astrodynamics::trajectory::Model;
using ostk::astrodynamics::trajectory::State;
Expand Down Expand Up @@ -165,6 +176,59 @@ class Trajectory
/// @return Static trajectory
static Trajectory Position(const physics::coordinate::Position& aPosition);

/// @brief Constructs a trajectory for a given strip, specified ground speed and start instant
///
/// @code{.cpp}
/// LLA startLLA = { 0.0, 0.0, 0.0 };
/// LLA endLLA = { 1.0, 0.0, 0.0 };
/// Derived groundSpeed = Derived(1000.0, Derived::Unit::MeterPerSecond());
/// Instant startInstant = Instant::DateTime(DateTime::Parse("2020-01-01 00:00:00"), Scale::UTC);
/// Earth earth = Earth::WGS84();
/// Duration stepSize = Duration::Seconds(1.0);
/// Trajectory trajectory = Trajectory::GroundStrip(startLLA, endLLA, groundSpeed, startInstant, earth,
/// duration);
/// @endcode
///
/// @param aStartLLA A start LLA
/// @param anEndLLA An end LLA
/// @param aGroundSpeed A ground speed
/// @param aStartInstant A start instant
/// @param aCelestial Celestial body
/// @return GroundStrip trajectory
static Trajectory GroundStrip(
const LLA& aStartLLA,
const LLA& anEndLLA,
const Derived& aGroundSpeed,
const Instant& aStartInstant,
const Celestial& aCelestial = Earth::WGS84(),
const Duration& aStepSize = Duration::Seconds(1.0)
);

/// @brief Constructs a trajectory for a given strip, assuming a constant ground speed and start instant
///
/// @code{.cpp}
/// LLA startLLA = LLA::FromVector({ 0.0, 0.0, 0.0 });
/// LLA endLLA = LLA::FromVector({ 1.0, 0.0, 0.0 });
/// Instant startInstant = Instant::DateTime(DateTime::Parse("2020-01-01 00:00:00"), Scale::UTC);
/// Instant endInstant = Instant::DateTime(DateTime::Parse("2020-01-01 00:10:00"), Scale::UTC);
/// Interval interval = Interval::Closed(startInstant, endInstant);
/// Array<Instant> instants = interval.generateGrid(Duration::Seconds(1.0));
/// Earth earth = Earth::WGS84();
/// Trajectory trajectory = Trajectory::GroundStrip(startLLA, endLLA, instants, earth);
/// @endcode
///
/// @param aStartLLA A start LLA
/// @param anEndLLA An end LLA
/// @param anInstantArray An array of instants
/// @param aCelestial Celestial body
/// @return GroundStrip trajectory
static Trajectory GroundStrip(
const LLA& aStartLLA,
const LLA& anEndLLA,
const Array<Instant>& anInstantArray,
const Celestial& aCelestial = Earth::WGS84()
);

private:
Unique<Model> modelUPtr_;

Expand Down
2 changes: 1 addition & 1 deletion src/OpenSpaceToolkit/Astrodynamics/GuidanceLaw/QLaw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ QLaw::QLaw(
)
: GuidanceLaw("Q-Law"),
parameters_(aParameterSet),
mu_(aGravitationalParameter.in(aGravitationalParameter.getUnit())),
mu_(aGravitationalParameter.in(Derived::Unit::MeterCubedPerSecondSquared())),
targetCOEVector_(aCOE.getSIVector(COE::AnomalyType::True)),
gravitationalParameter_(aGravitationalParameter),
gradientStrategy_(aGradientStrategy),
Expand Down
Loading

0 comments on commit 57f7d7c

Please sign in to comment.