pub use super::CostFunction;
use super::ctrlnodes::Node;
use super::multishoot::MultipleShooting;
use crate::errors::TargetingError;
use crate::md::prelude::*;
use crate::{Orbit, Spacecraft};
use log::error;
impl<'a> MultipleShooting<'a, Node, 3, 3> {
pub fn equidistant_nodes(
x0: Spacecraft,
xf: Orbit,
node_count: usize,
prop: &'a Propagator<SpacecraftDynamics>,
) -> Result<Self, TargetingError> {
if node_count < 3 {
error!("At least three nodes are needed for a multiple shooting optimization");
return Err(TargetingError::UnderdeterminedProblem);
}
let mut direction = xf.radius_km - x0.orbit.radius_km;
if direction.norm() < f64::EPSILON {
return Err(TargetingError::TargetsTooClose);
}
let distance_increment = direction.norm() / (node_count as f64);
let duration_increment = (xf.epoch - x0.epoch()) / (node_count as f64);
direction /= direction.norm();
let mut nodes = Vec::with_capacity(node_count + 1);
let mut prev_node_radius = x0.orbit.radius_km;
let mut prev_node_epoch = x0.epoch();
for _ in 0..node_count {
let this_node = prev_node_radius + distance_increment * direction;
let this_epoch = prev_node_epoch + duration_increment;
nodes.push(Node {
x: this_node[0],
y: this_node[1],
z: this_node[2],
vmag: 0.0,
frame: x0.orbit.frame,
epoch: this_epoch,
});
prev_node_radius = this_node;
prev_node_epoch = this_epoch;
}
Ok(Self {
prop,
targets: nodes,
x0,
xf,
current_iteration: 0,
max_iterations: 50,
improvement_threshold: 0.01,
variables: [
Vary::VelocityX.into(),
Vary::VelocityY.into(),
Vary::VelocityZ.into(),
],
all_dvs: Vec::with_capacity(node_count),
})
}
}