Skip to main content

nyx_space/od/groundpnt/
ground_dynamics.rs

1/*
2    Nyx, blazing fast astrodynamics
3    Copyright (C) 2018-onwards Christopher Rabotin <christopher.rabotin@gmail.com>
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU Affero General Public License as published
7    by the Free Software Foundation, either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU Affero General Public License for more details.
14
15    You should have received a copy of the GNU Affero General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.
17*/
18
19use crate::dynamics::{Dynamics, DynamicsError};
20use crate::od::groundpnt::GroundAsset;
21use anise::prelude::Almanac;
22use nalgebra::allocator::Allocator;
23use nalgebra::{Const, DefaultAllocator, Matrix6, OMatrix, OVector, Vector6};
24
25#[derive(Clone)]
26pub struct GroundDynamics {}
27
28impl Dynamics for GroundDynamics {
29    type StateType = GroundAsset;
30    type HyperdualSize = Const<6>;
31
32    fn eom(
33        &self,
34        _delta_t: f64,
35        _state_vec: &OVector<f64, <Self::StateType as crate::State>::VecLength>,
36        state_ctx: &Self::StateType,
37        _almanac: &Almanac,
38    ) -> Result<OVector<f64, <Self::StateType as crate::State>::VecLength>, DynamicsError>
39    where
40        DefaultAllocator: Allocator<<Self::StateType as crate::State>::VecLength>,
41    {
42        let d_x = Vector6::from_iterator([
43            state_ctx.latitude_rate_deg_s,
44            state_ctx.longitude_rate_deg_s,
45            state_ctx.height_rate_km_s,
46            0.0,
47            0.0,
48            0.0,
49        ]);
50
51        Ok(OVector::<f64, Const<42>>::from_iterator(
52            d_x.iter()
53                .chain(OVector::<f64, Const<36>>::zeros().iter())
54                .cloned(),
55        ))
56    }
57
58    fn dual_eom(
59        &self,
60        _delta_t: f64,
61        osc: &Self::StateType,
62        _almanac: &Almanac,
63    ) -> Result<
64        (
65            OVector<f64, <Self::StateType as crate::State>::Size>,
66            OMatrix<
67                f64,
68                <Self::StateType as crate::State>::Size,
69                <Self::StateType as crate::State>::Size,
70            >,
71        ),
72        DynamicsError,
73    >
74    where
75        DefaultAllocator: Allocator<Self::HyperdualSize>
76            + Allocator<<Self::StateType as crate::State>::Size>
77            + Allocator<
78                <Self::StateType as crate::State>::Size,
79                <Self::StateType as crate::State>::Size,
80            >,
81        nalgebra::Owned<f64, Self::HyperdualSize>: Copy,
82    {
83        // The math is very simple here, so we're skipping the hyperdual represenation.
84        let dx = Vector6::new(
85            osc.latitude_rate_deg_s,
86            osc.longitude_rate_deg_s,
87            osc.height_rate_km_s,
88            0.0,
89            0.0,
90            0.0,
91        );
92
93        // A-matrix for kinematic (no acceleration) model:
94        // d/dt[pos] = vel  →  ∂(pos_dot)/∂vel = I₃
95        // d/dt[vel] = 0    →  all velocity partials are zero
96        let mut grad = Matrix6::zeros();
97        grad[(0, 3)] = 1.0;
98        grad[(1, 4)] = 1.0;
99        grad[(2, 5)] = 1.0;
100
101        Ok((dx, grad))
102    }
103}