nyx_space/md/opti/multipleshooting/
ctrlnodes.rsuse anise::prelude::Frame;
use crate::md::prelude::{Objective, StateParameter};
use crate::time::Epoch;
use crate::NyxError;
use serde_derive::{Deserialize, Serialize};
use std::convert::Into;
use std::str::FromStr;
use super::multishoot::MultishootNode;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct NodesSerde {
pub nodes: Vec<NodeSerde>,
}
impl NodesSerde {
pub fn to_node_vec(&self) -> Result<Vec<Node>, NyxError> {
let mut rtn = Vec::with_capacity(self.nodes.len());
for n in &self.nodes {
rtn.push(n.to_node()?)
}
Ok(rtn)
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct NodeSerde {
pub x: f64,
pub y: f64,
pub z: f64,
pub vmag: Option<f64>,
pub epoch: String,
pub frame: Frame,
}
impl NodeSerde {
pub fn to_node(&self) -> Result<Node, NyxError> {
let epoch = Epoch::from_str(&self.epoch).unwrap();
Ok(Node {
x: self.x,
y: self.y,
z: self.z,
vmag: self.vmag.unwrap_or(0.0),
frame: self.frame,
epoch,
})
}
}
#[derive(Copy, Clone, Debug)]
pub struct Node {
pub x: f64,
pub y: f64,
pub z: f64,
pub vmag: f64,
pub epoch: Epoch,
pub frame: Frame,
}
impl Node {
pub fn rmag(&self) -> f64 {
(self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).sqrt()
}
}
impl MultishootNode<3> for Node {
fn epoch(&self) -> Epoch {
self.epoch
}
fn update_component(&mut self, component: usize, add_val: f64) {
match component {
0 => self.x += add_val,
1 => self.y += add_val,
2 => self.z += add_val,
3 => self.vmag += add_val,
_ => unreachable!(),
}
}
}
#[allow(clippy::from_over_into)]
impl Into<[Objective; 3]> for Node {
fn into(self) -> [Objective; 3] {
[
Objective::new(StateParameter::X, self.x),
Objective::new(StateParameter::Y, self.y),
Objective::new(StateParameter::Z, self.z),
]
}
}
impl MultishootNode<4> for Node {
fn epoch(&self) -> Epoch {
self.epoch
}
fn update_component(&mut self, component: usize, add_val: f64) {
match component {
0 => self.x += add_val,
1 => self.y += add_val,
2 => self.z += add_val,
3 => self.vmag += add_val,
_ => unreachable!(),
}
}
}
#[allow(clippy::from_over_into)]
impl Into<[Objective; 4]> for Node {
fn into(self) -> [Objective; 4] {
[
Objective::new(StateParameter::X, self.x),
Objective::new(StateParameter::Y, self.y),
Objective::new(StateParameter::Z, self.z),
Objective::new(StateParameter::Vmag, self.vmag),
]
}
}
#[allow(clippy::from_over_into)]
impl Into<NodeSerde> for Node {
fn into(self) -> NodeSerde {
NodeSerde {
x: self.x,
y: self.y,
z: self.z,
vmag: Some(self.vmag),
frame: self.frame,
epoch: self.epoch.to_string(),
}
}
}
#[allow(clippy::from_over_into)]
impl Into<NodeSerde> for &Node {
fn into(self) -> NodeSerde {
NodeSerde {
x: self.x,
y: self.y,
z: self.z,
vmag: Some(self.vmag),
frame: self.frame,
epoch: self.epoch.to_string(),
}
}
}
#[test]
fn test_nodeserde() {
use toml;
let str_nodes = r#"[[nodes]]
x = -394.37164017582654
y = -80.02184491079583
z = -1702.1160791417442
vmag = 0.0
epoch = "2023-11-25T14:11:46.789000034 UTC"
[nodes.frame]
ephemeris_id = 301
orientation_id = 1
[[nodes]]
x = -381.68254116206856
y = -48.21573534985666
z = -1705.829637126235
vmag = 0.0
epoch = "2023-11-25T14:12:06.789000034 UTC"
[nodes.frame]
ephemeris_id = 301
orientation_id = 1
[[nodes]]
x = -368.8474537620047
y = -16.401929604226403
z = -1708.8692139449731
vmag = 0.0
epoch = "2023-11-25T14:12:26.789000034 UTC"
[nodes.frame]
ephemeris_id = 301
orientation_id = 1
"#;
let toml_nodes: NodesSerde = toml::from_str(str_nodes).unwrap();
let nodes = toml_nodes.to_node_vec().unwrap();
dbg!(&nodes);
let v = NodesSerde {
nodes: nodes.iter().map(|n| n.into()).collect::<Vec<NodeSerde>>(),
};
let toml_ser = toml::to_string(&v).unwrap();
println!("GOT\n{}\n\nWANTED:{}", toml_ser, str_nodes);
assert_eq!(toml_ser, str_nodes);
}