f2m package¶
Subpackages¶
Submodules¶
f2m.ampl_interface module¶
- class f2m.ampl_interface.AMPLModel(ampl_mod_path: str, auto_reset: bool = True)¶
Bases:
objectCode from https://gitlab.com/EuropeanSpaceAgency/trajectory-to-events
- checkSolved()¶
- coerceSpecialVariable(var_name)¶
- display(*args)¶
- getAMPL()¶
- getConstraint(name)¶
- getConstraints()¶
- getObjective(name)¶
- getObjectiveShape(obj_name)¶
- getObjectiveValue(obj_name)¶
- getObjectiveValues(name_list=None)¶
- getObjectives()¶
- getParamShape(param_name)¶
- getParameter(name)¶
- getParameterValue(param_name)¶
- getParameterValues(name_list=None)¶
- getParameters()¶
- getSetSize(set_name)¶
- getSolutionValues(name_list=None)¶
- getSpecialVariable(name_list=None)¶
- getVarShape(var_name)¶
- getVariable(name)¶
- getVariableValue(var_name)¶
- getVariableValues(name_list=None)¶
- getVariables()¶
- items()¶
- keys()¶
- reset()¶
- setParameterValue(param_name, param_value)¶
- setParameterValues(param_dict={}, **kwargs)¶
- showAMPLOutput()¶
- solve(hide_solver_output=True)¶
- solveAsync(callback, hide_solver_output=True)¶
- f2m.ampl_interface.extract_ocp_params(p)¶
[DEPRECATED] Extract user-defined parameters for the OCP
- f2m.ampl_interface.sample_ocp_params(traj_config, parameter)¶
[DEPRECATED] Sample specified trajectory parameter range to generate new OCP
- Parameters:
traj_config (dict) – Trajectory configuration
parameter (str) – Parameter to sample
Returns:
f2m.camera_noise module¶
- f2m.camera_noise.add_gaussian_noise(image: ndarray, std: float = 6, cosmic_rays_outliers: bool = True, framerate: int = 4) ndarray¶
f2m.motion_field module¶
- f2m.motion_field.least_squares_estimation(vars: dict[str, float], pars: dict[str, float], points: ndarray, flow: ndarray, focal_length: float, framerate: int, image_width: int, target_radius: int | None = None, stable_depth: bool = False, least_squares_kwargs: dict = {}) OptimizeResult¶
Estimate the spacecraft state using least squares optimization over motion field equations. If the system is linear, linear least squares will be used, otheriwse a non-linear version will be used.
- Parameters:
vars (dict[str, float]) – variables to optimize. The keys are the variable names and the values are the initial guesses.
pars (dict[str, float]) – parameters with known values
points (np.ndarray) – points in the image plane, shape (n, 2)
flow (np.ndarray) – optical flow vectors corresponding to points, shape (n, 2)
focal_length (float) – camera focal length related to the image width
framerate (int) – camera framerate
image_width (int) – image width, in pixels
target_radius (int, optional) – radius of the target in meters. Defaults to None (planar case)
stable_depth (bool, optional) – If True, replaces NaN depth values with the maximum depth
least_squares_kwargs (dict, optional) – additional arguments to pass to scipy.optimize.least_squares. Defaults to {}.
- Returns:
optimization result. The x attribute contains the optimized variables
- Return type:
OptimizeResult
- f2m.motion_field.motion_field(sx: float | ndarray, sy: float | ndarray, state: ndarray, fx: float = 1, fy: float = 1, target_radius: float | None = None, alpha: float | None = None, beta: float | None = None, stable_depth: bool = False) tuple[ndarray, ndarray]¶
Computes the motion field assuming a planar or spherical target surface. If target_radius is None, a planar surface is assumed; otherwise, the surface is treated as spherical.
A necessary step to compute the depth map is estimating the surface inclination relative to the camera, which is represented by the components of the unit vector orthogonal to the surface at the center of the image: (alpha, beta, gamma). By default, these values are inferred from the spacecraft state. Specifically, the orientation angles (phi, theta, psi) are used in the planar case, and in the spherical case, the rangefinder measurement (rho) and target_radius are also required.
Alternatively, users can explicitly provide alpha and beta (gamma is inferred from them to complete the unit vector). This is useful when surface geometry is known or constant.
If stable_depth is True, any NaN values in the computed depth map will be replaced by the maximum depth value found in the map.
- Parameters:
sx (float or np.ndarray) – Horizontal image coordinate(s) on the sensor.
sy (float or np.ndarray) – Vertical image coordinate(s) on the sensor.
state (np.ndarray) – Spacecraft state vector [x, y, z, vx, vy, vz, phi, theta, psi, p, q, r, rho]. - x and y are ignored and can be set to any value. - Planar case (target_radius is None): use either theta or z (rho overrides z if present). - Spherical case (target_radius is not None): requires rho; z is ignored.
fx (float, optional) – Horizontal focal length. Defaults to 1.
fy (float, optional) – Vertical focal length. Defaults to 1.
target_radius (float, optional) – Radius of the target in meters. If None, a planar target is assumed.
alpha (float, optional) – X-component of the surface normal vector.
beta (float, optional) – Y-component of the surface normal vector.
stable_depth (bool, optional) – If True, replaces NaN depth values with the maximum depth. Defaults to False.
- Returns:
The horizontal (u) and vertical (v) components of the motion field.
- Return type:
tuple
- f2m.motion_field.ransac_estimation(vars: dict[str, float], pars: dict[str, float], points: ndarray, flow: ndarray, focal_length: float, framerate: int, image_width: int, target_radius: int | None = None, least_squares_kwargs: dict = {}, min_samples: int = 3, residual_threshold: float = 0.1, consensus_threshold: float = 0.75, max_trials: int = 100) dict[str, Any]¶
Estimate the spacecraft state using least squares optimization over motion field equations with RANSAC to handle outliers
- Parameters:
vars (dict[str, float]) – variables to optimize. The keys are the variable names and the values are the initial guesses.
pars (dict[str, float]) – parameters with known values
points (np.ndarray) – points in the image plane, shape (n, 2)
flow (np.ndarray) – optical flow vectors corresponding to points, shape (n, 2)
focal_length (float) – camera focal length related to the image width
framerate (int) – camera framerate
image_width (int) – image width, in pixels
target_radius (int, optional) – radius of the target in meters. Defaults to None (planar case).
least_squares_kwargs (dict, optional) – additional arguments to pass to scipy.optimize.least_squares. Defaults to {}.
min_samples (int, optional) – number of samples to fit the model. Defaults to 3.
residual_threshold (float, optional) – maximum residual to consider an inlier. Defaults to 0.1.
consensus_threshold (float, optional) – minimum ratio of inliers to consider the model valid. Defaults to 0.75.
max_trials (int, optional) – maximum number of iterations. Defaults to 100.
- Returns:
- dictionary with the following keys:
result: optimized variables
mask: boolean mask indicating inliers
iterations: number of iterations
converged: whether the algorithm converged
consensus: ratio of inliers
- Return type:
dict[str, Any]
f2m.optical_flow module¶
- class f2m.optical_flow.LKOpticalFlowEstimator(feature_params: dict = None, lk_params: dict = None, do_histogram_equalization: bool = False, mask: ndarray = None)¶
Bases:
object- forward(img0: ndarray, img1: ndarray, features: ndarray = None, verbose: bool = False) tuple[ndarray, ndarray]¶
Compute the optical flow between two frames
- Parameters:
img0 (np.ndarray) – [3]xHxW cv2 image representing the first frame
img1 (np.ndarray) – [3]xHxW cv2 image representing the second frame
features (np.ndarray) – Nx2 array representing already tracked feature coordinates (Optional)
verbose (bool) – Debugging mode flag
- Returns:
Nx2 array representing features coordinates and Nx2 array representing their flow
- Return type:
tuple[np.ndarray, np.ndarray]
- update_tracked_points(tracked_points: ndarray, image: ndarray, verbose: bool = False) ndarray¶
Detects, filters then adds additional points to the list of tracked points
- Parameters:
tracked_points (np.ndarray) – Nx2 array of position of tracked points in next frame
image (np.ndarray) – [1]xHxW cv2 image representing the grayscale frame of the image
verbose (bool) – Debugging mode flag
- Returns:
Nx2 array of position of tracked points for the next frame of OF
- Return type:
np.ndarray
- f2m.optical_flow.draw_optical_flow(img: ndarray, points: ndarray, flow: ndarray, arrow_scale: float = 3.0, arrow_thickness: int = 2, color: tuple[int, int, int] = (0, 255, 0)) ndarray¶
Draw representation of optical flow
- Parameters:
img (np.ndarray) – cv2 image
points (np.ndarray) – Nx2 array representing features coordinates
flow (np.ndarray) – Nx2 array representing their flow
arrow_scale (float, optional) – scale optical flow arrows for better visualization. Defaults to 3.
arrow_thickness (int, optional) – thickness of the arrows. Defaults to 2.
(tuple[int (color) – color of arrows)
int – color of arrows)
int] – color of arrows)
- Returns:
[2]xHxW representation of the flow
- Return type:
np.ndarray
- f2m.optical_flow.generate_optical_flow_video(frames: ndarray, of_estimator: LKOpticalFlowEstimator, output_path: Path, arrow_scale: float = 3.0, arrow_thickness: int = 2, frame_interval: int = 1, fps: int = 4, verbose: bool = False, save_frames: bool = False) None¶
Generate the optical flow video between all frames
- Parameters:
frames (np.ndarray) – cv2 arrays representing video frames in BGR
of_estimator (LKOpticalFlowEstimator) – optical flow estimator
output_dir (Path) – where to save output frames
arrow_scale (float, optional) – scale optical flow arrows for better visualization. Defaults to 3.
arrow_thickness (int, optional) – thickness of the arrows. Defaults to 2.
frame_interval (int, optional) – Detect new points to track every frame_interval frames. Defaults to 1.
fps (int) – framerate in the output video. Defaults to 4
verbose (bool) – Debugging mode flag
save_frames (bool) – Save frames to disk
f2m.symbolic module¶
- f2m.symbolic.H_numerical(phi, theta, rho, R)¶
Created with lambdify. Signature:
func(phi, theta, rho, R)
Expression:
-R + R*sin(acos(cos(phi)*cos(theta)) +…
Source code:
- def _lambdifygenerated(phi, theta, rho, R):
return -R + R*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R))/sqrt(-cos(phi)**2*cos(theta)**2 + 1)
Imported modules:
- f2m.symbolic.alpha_numerical(phi, theta, rho, R)¶
Created with lambdify. Signature:
func(phi, theta, rho, R)
Expression:
-R*sin(theta)*sin(acos(cos(phi)*cos(theta)) +…
Source code:
- def _lambdifygenerated(phi, theta, rho, R):
return -R*sin(theta)*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R))/(sqrt(-cos(phi)**2*cos(theta)**2 + 1)*sqrt(abs(R*sin(theta)*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R)))**2/abs(sqrt(-cos(phi)**2*cos(theta)**2 + 1))**2 + abs(R*sin(phi)*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R))*cos(theta))**2/abs(sqrt(-cos(phi)**2*cos(theta)**2 + 1))**2 + abs(R*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R))*cos(phi)*cos(theta)/sqrt(-cos(phi)**2*cos(theta)**2 + 1) - rho)**2))
Imported modules:
- f2m.symbolic.beta_numerical(phi, theta, rho, R)¶
Created with lambdify. Signature:
func(phi, theta, rho, R)
Expression:
R*sin(phi)*sin(acos(cos(phi)*cos(theta)) +…
Source code:
- def _lambdifygenerated(phi, theta, rho, R):
return R*sin(phi)*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R))*cos(theta)/(sqrt(-cos(phi)**2*cos(theta)**2 + 1)*sqrt(abs(R*sin(theta)*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R)))**2/abs(sqrt(-cos(phi)**2*cos(theta)**2 + 1))**2 + abs(R*sin(phi)*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R))*cos(theta))**2/abs(sqrt(-cos(phi)**2*cos(theta)**2 + 1))**2 + abs(R*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R))*cos(phi)*cos(theta)/sqrt(-cos(phi)**2*cos(theta)**2 + 1) - rho)**2))
Imported modules:
- f2m.symbolic.gamma_numerical(phi, theta, rho, R)¶
Created with lambdify. Signature:
func(phi, theta, rho, R)
Expression:
(-R*sin(acos(cos(phi)*cos(theta)) +…
Source code:
- def _lambdifygenerated(phi, theta, rho, R):
return (-R*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R))*cos(phi)*cos(theta)/sqrt(-cos(phi)**2*cos(theta)**2 + 1) + rho)/sqrt(abs(R*sin(theta)*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R)))**2/abs(sqrt(-cos(phi)**2*cos(theta)**2 + 1))**2 + abs(R*sin(phi)*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R))*cos(theta))**2/abs(sqrt(-cos(phi)**2*cos(theta)**2 + 1))**2 + abs(R*sin(arccos(cos(phi)*cos(theta)) + arcsin(rho*sqrt(-cos(phi)**2*cos(theta)**2 + 1)/R))*cos(phi)*cos(theta)/sqrt(-cos(phi)**2*cos(theta)**2 + 1) - rho)**2)
Imported modules:
- f2m.symbolic.get_alpha(phi_value: float, theta_value: float, rho_value: float, R_value: float) float¶
Calculate alpha based on the given parameters.
- Parameters:
phi_value (float) – The value of phi.
theta_value (float) – The value of theta.
rho_value (float) – The value of rho.
R_value (float) – The value of R.
- Returns:
The calculated alpha.
- Return type:
float
- f2m.symbolic.get_beta(phi_value: float, theta_value: float, rho_value: float, R_value: float) float¶
Calculate beta based on the given parameters.
- Parameters:
phi_value (float) – The value of phi.
theta_value (float) – The value of theta.
rho_value (float) – The value of rho.
R_value (float) – The value of R.
- Returns:
The calculated beta.
- Return type:
float
- f2m.symbolic.get_gamma(phi_value: float, theta_value: float, rho_value: float, R_value: float) float¶
Calculate gamma based on the given parameters.
- Parameters:
phi_value (float) – The value of phi.
theta_value (float) – The value of theta.
rho_value (float) – The value of rho.
R_value (float) – The value of R.
- Returns:
The calculated gamma.
- Return type:
float
- f2m.symbolic.get_h(phi_value: float, theta_value: float, rho_value: float, R_value: float) float¶
Calculate h based on the given parameters.
- Parameters:
phi_value (float) – The value of phi.
theta_value (float) – The value of theta.
rho_value (float) – The value of rho.
R_value (float) – The value of R.
- Returns:
The calculated h.
- Return type:
float
- f2m.symbolic.is_singularity(phi_value: float, theta_value: float, epsilon: float = 1e-07) bool¶
Return True if abs value of phi and theta are lower than epsilon.
- Parameters:
phi_value (float) – the value of phi.
theta_value (float) – the value of theta.
epsilon (float, optional) – threshold value to decide if we are in a singluarity. Defaults to 1e-7.
- Returns:
True if we are in a singularity, False otherwise.
- Return type:
bool
f2m.trajectory module¶
- f2m.trajectory.AMPL_to_PANGU_conversion(trajectory: ndarray, camera_tilt: tuple[float, float, float] | None = [0, 0, 0], z_flip: bool = True)¶
Apply rotations required to convert AMPL trajectory to ventral landing scenario for south polar landing + camera tilt.
- Parameters:
trajectory (np.ndarray) – The trajectory to convert, with shape Nx13, where each state is [x, y, z, vx, vy, vz, phi, theta, psi, p, q, r, m]
(Optional (camera_tilt) – (float, float, float)): camera tilt angles on X, Y, and Z axes. Defaults to [0, 0, 0].
z_flip (bool) – If True, flips the z-axis of the trajectory. Defaults to True.
- Returns:
The converted trajectory with the shape Nx14, where each state is [x, y, z, vx, vy, vz, qw, qx, qy, qz, p, q, r, m]
- Return type:
np.ndarray
- f2m.trajectory.center_traj_on_landing_site(trajectory: ndarray, landing_site: tuple[float, float, float] = (-25010, -40149, -3530.85)) ndarray¶
Centers the trajectory on the landing site such that the final position is above the landing site.
- Parameters:
trajectory (np.ndarray) – The trajectory to center
landing_site (tuple[float, float, float]) – The coordinates of the landing site
- Returns:
The trajectory translated such that the landing position is above the landing site
- Return type:
np.ndarray
- f2m.trajectory.convert_state_history_inertial_to_body_frame(traj_dir: str, return_ranges=False)¶
Converts an inertial state history to a body frame one. The body frame is defined in get_axes_from_state().
- Parameters:
traj_dir (str) – The directory from which to load the trajectory.
- Returns:
The time and state history in the body frame.
- Return type:
tuple(np.ndarray, np.ndarray)
- f2m.trajectory.generate_hohmann_trajectory(output_dir: Path, init_position, alt_p=None, alt_a=None, r_moon=1737400.0, mu_moon: float = 4902800118000.0, n_points=200, save_traj=True, as_array=False, fps: int = 4, field_of_view: int = 60, camera_tilt: tuple[float, float, float] | None = None, indices=None) dict | ndarray¶
Generates a Hohmann transfer trajectory.
Warning! User discretion is advised. This function isn’t validated and therefore is not guaranteed to work for all init_position values (and camera_tilts)
- Parameters:
output_dir (Path) – Path to the directory where trajectory files should be saved.
init_position (array-like) – Initial position vector for the transfer.
alt_p (float, optional) – Pericenter altitude in meters.
alt_p – Apocenter altitude in meters.
period_frac (float, optional) – Fraction of the orbital period to simulate. Defaults to 0.5.
r_moon (float, optional) – Radius of the Moon in meters. Defaults to 1737.4e3 m.
mu_moon (float, optional) – The gravitational parameter. Defaults to the Moon 4.902800118e12 m**3/s**2.
save_traj (bool, optional) – If True, saves the trajectory to a file. Defaults to True.
as_array (bool, optional) – If True, returns the trajectory as a NumPy array. Defaults to False.
fps (int, optional) – Frames per second for trajectory interpolation. Defaults to 4.
field_of_view (int, optional) – Camera field of view in degrees. Defaults to 60.
camera_tilt (Optional[tuple[float, float, float]], optional) – Camera tilt angles (X, Y, Z) in radians. Defaults to None.
indices (list) – List of indices that represents the indices of the state history that you want to save. Defaults to None.
- Returns:
If as_array is True, returns the trajectory as a NumPy array. Otherwise, returns a dictionary of state history.
- Return type:
np.ndarray
- f2m.trajectory.generate_multiple_trajectories(landing_model_path: Path, parameters_path: Path, output_dir: Path, number_of_trajectories: int, save_continuation: bool = False, save_traj: bool = True, verbose: bool = True, fps: int = 4, camera_tilt: tuple[float, float, float] | None = [0, 0, 0], offset: tuple[float, float, float] = [0, 0, 0], landing_site: tuple[float, float, float] = [-25010, -40149, -3530.85])¶
[DEPRECATED] Generate a trajectory with.
- Parameters:
landing_model_path (Path) – Path to the landing model.
parameters_path (Path) – Path to the parameters file.
output_dir (Path) – Path to the output directory.
number_of_trajectories (int) – Number of trajectories to generate.
save_continuation (bool, optional) – Save trajectory for each updated parameters. Defaults to False.
save_traj (bool, optional) – Save the trajectory for each full set of updated parameters. Defaults to True.
verbose (bool, optional) – Verbose flag. Defaults to True.
fps (int, optional) – States per second. Defaults to 4.
(Optional (camera_tilt) – (float, float, float)): camera tilt angles on X, Y, and Z axes
offset (tuple[float, float, float]) – position offset applied to the trajectory
- f2m.trajectory.generate_trajectory(landing_model_path: Path, parameters_path: Path, output_dir: Path, verbose: bool = True, fps: int = 4, camera_tilt: tuple[float, float, float] | None = [0, 0, 0], landing_site: tuple[float, float, float] = [-25010, -40149, -3530.85], z_flip: bool = True, save: bool = True) ndarray¶
Generate a trajectory with the given parameters, using AMPL and save it in the output directory.
- Parameters:
landing_model_path (Path) – Path to the landing model.
parameters_path (Path) – Path to the parameters file.
output_dir (Path) – Path to the output directory.
verbose (bool, optional) – Verbose flag. Defaults to True.
fps (int, optional) – States per second. Defaults to 4.
(Optional (camera_tilt) – (float, float, float)): camera tilt angles on X, Y, and Z axes. Defaults to [0, 0, 0].
offset (tuple[float, float, float]) – position offset applied to the trajectory. Defaults to [0, 0, 0].
landing_site (tuple[float, float, float]) – The coordinates to translate the origin to the landing site position. Defaults to [-25010, -40149, -3530.850].
- Returns:
The optimized trajectory state history.
- Return type:
np.ndarray
- f2m.trajectory.get_angular_state_history(orbit: dict, as_array=False, sequence='XYZ')¶
Computes the angular state history of a spacecraft, assuming the camera points toward the Moon’s center.
- Parameters:
orbit (dict) – Dictionary of time-mapped position and velocity states.
as_array (bool, optional) – If True, returns results as a NumPy array. Defaults to False.
sequence (str) – If XYZ (used for ispace traj), then XYZ rotation order is maintained, else if “ZYX” (for hohmann transfer) then ZYX rotation order
- Returns:
A dictionary mapping time values to angular states [phi, theta, psi, phi_dot, theta_dot, psi_dot]. or np.ndarray: An array of the angular states [phi, theta, psi, phi_dot, theta_dot, psi_dot].
- Return type:
dict
- f2m.trajectory.get_hohmann_state_history(alt_p, alt_a, r_body, mu, n_points=100, as_array=False, direction='inbound')¶
Generate position and velocity history along a Hohmann transfer orbit.
- Parameters:
alt_p – float Perigee altitude above the central body [m].
alt_a – float Apogee altitude above the central body [m].
r_body – float Radius of the central body [m].
mu – float Gravitational parameter of the central body [m^3/s^2].
n_points – int, optional Number of points along the transfer orbit (default is 100).
as_array – bool, optional If True, return a NumPy array of shape (n_points, 6) where each row is [x, y, z, vx, vy, vz]. If False, return a dict keyed by time with each value being a 6-element state vector.
- Returns:
- np.ndarray or dict
The trajectory states along the transfer orbit, either as an array or a dictionary indexed by time.
Notes
The orbit is assumed to be planar and elliptical (Hohmann transfer).
The z and vz components are always zero due to the planar assumption.
The trajectory is computed for half the orbital period, corresponding
to the Hohmann transfer time.
- f2m.trajectory.get_landing_site(landing_site: str) tuple[float, float, float]¶
Get the landing site coordinates from the given string
- Parameters:
landing_site (str) – The landing site name
- Returns:
The landing site coordinates
- Return type:
tuple[float, float, float]
- f2m.trajectory.get_period(mu, radius)¶
Orbital period using Kepler’s third law
- f2m.trajectory.get_state_history_from_csv(path)¶
Read a CSV file containing trajectory state history.
- Parameters:
path (str) – Path to the CSV file.
- Returns:
Time and state history arrays.
- Return type:
tuple
- f2m.trajectory.get_velocity_from_position_diff(t, x)¶
Interpolates velocity from position data using finite differences.
- Parameters:
t (np.ndarray) – Time data.
x (np.ndarray) – Position data.
- Returns:
Interpolated velocity data.
- Return type:
np.ndarray
- f2m.trajectory.interpolate_vector(t, x, dt=1)¶
Interpolates position data using cubic splines.
- Parameters:
t (np.ndarray) – Time data.
x (np.ndarray) – Position data.
dt (int, float) – Time step for interpolation.
- Returns:
Interpolated position data.
- Return type:
np.ndarray
- f2m.trajectory.rotate_vector_rodrigues(v, k, theta)¶
Rotate vector v around axis k by angle theta (Rodrigues’ rotation formula).
- f2m.trajectory.rotated_hohmann_state_history(r_init, alt_p=None, alt_a=None, r_body=1737400.0, mu=4902800118000.0, n_points=100, as_array=False)¶
Generate a rotated Hohmann transfer trajectory to align with an arbitrary initial position vector.
- Parameters:
r_init – array-like Desired initial position vector in inertial frame [m].
alt_p – Passed through to get_hohmann_state_history.
alt_a – Passed through to get_hohmann_state_history.
r_body – Passed through to get_hohmann_state_history.
mu – Passed through to get_hohmann_state_history.
n_points – Passed through to get_hohmann_state_history.
as_array – Passed through to get_hohmann_state_history.
- Returns:
State history as array or dict, rotated to start at r_init.
Note
If alt_p is None and alt_a is not None -> outbound traj where r_init is periapsis position. If alt_p is not None and alt_a is None -> inbound traj where r_init is apoapsis position. Make sure that r_init corresponds properly to apoapsis or periapsis, making sure it’s smaller than alt_a if alt_a is passed, and idem for alt_p.
- f2m.trajectory.save_ampl_trajectory(ampl_model: AMPLModel, output_dir: Path, fps: int, camera_tilt: tuple[float, float, float] | None = [0, 0, 0], landing_site: tuple[float, float, float] = [-25010, -40149, -3530.85], z_flip: bool = True) None¶
Saves the computed trajectory and generates a flight file for visualization.
- Parameters:
ampl_model (AMPLModel) – The AMPL optimization model containing trajectory results.
output_dir (Path) – Directory to save trajectory data.
fps (int) – Frames per second for trajectory interpolation.
camera_tilt (Optional[tuple[float, float, float]]) – Camera tilt angles (X, Y, Z).
- f2m.trajectory.save_trajectory_hohmann(full_state_history: dict, output_dir: Path, fps: int, field_of_view=60, camera_tilt: tuple[float, float, float] | None = None, indices=None) None¶
Saves the computed Hohmann trajectory and generates a PANGU flight file.
- Parameters:
full_state_history (dict) – Dictionary of trajectory state history.
output_dir (Path) – Directory to save trajectory data.
fps (int) – Frames per second for trajectory interpolation.
field_of_view (int, optional) – Camera field of view in degrees. Defaults to 60.
camera_tilt (Optional[tuple[float, float, float]]) – Camera tilt angles (X, Y, Z).
- f2m.trajectory.solve_kepler(M, e, tol=1e-10, max_iter=100)¶
Solves Kepler’s equation E - e*sin(E) = M for E using Newton-Raphson.
- Parameters:
M (float) – Mean anomaly in radians
e (float) – Eccentricity (0 <= e < 1)
tol (float) – Convergence tolerance
max_iter (int) – Maximum number of iterations
- Returns:
Eccentric anomaly E in radians
- Return type:
float
- f2m.trajectory.trajectory_to_flight(trajectory: ndarray, field_of_view: int = 60, output_dir: Path | None = None) list[str]¶
Generate PANGU flight file starting from array representing trajectory’s states and saves it to output_dir/flight.fli.
- Parameters:
trajectory (np.ndarray) – trajectory’s state with shape Nx13 Note: trajectory shape can vary so long as position is in the 0 - 2, and attitude is in the 6 - 9 column. The convention we used is [x, y, z, vx, vy, vz, qw, qx, qy, qz, p, q, r].
field_of_view (int) – the field of view of the camera in degrees. Defaults to 60
output_dir (Optional[Path]) – Directory to save the flight file. If None, the flight file will not be saved.
- Returns:
Each element represents a line of Pangu’s flight file
- Return type:
list[str]
- f2m.trajectory.trajectory_to_flight_hohmann(trajectory: ndarray, field_of_view: int = 60, camera_tilt: tuple[float, float, float] | None = None) list[str]¶
Generate PANGU flight file with positions in quaternions, starting from array representing Hohmann trajectory’s states
- Parameters:
trajectory (np.ndarray) – tracjectory’s state with shape Nx12. Each state is [x, y, z, vx, vy, vz, phi, theta, psi, p, q, r]
field_of_view (int) – the field of view of the camera in degrees. Defaults to 60
(Optional (camera_tilt) – (float, float, float)): camera tilt angles on X, Y, and Z axes. Defaults to None.
- Returns:
Each element represents a line of Pangu’s flight file
- Return type:
list[str]
f2m.utils module¶
- f2m.utils.dict2array(d: dict)¶
- f2m.utils.get_axes_from_state(state: ndarray)¶
Computes a right-handed coordinate frame from a state vector.
- Parameters:
state (np.ndarray) – The state vector [x, y, z, vx, vy, vz].
- Returns:
A tuple (e_x, e_y, e_z) representing the unit vectors of the frame.
- Return type:
tuple
- Raises:
RuntimeError – If e_z and e_v are not linearly independent.
- f2m.utils.get_camera_tilt(tilt_frame: Literal['body', 'hohmann', 'landing'], pitch: float = 0, yaw: float = 0) tuple[float, float, float]¶
Returns the camera tilt as Euler angles (in radians) in the specified reference frame.
⚠️ Disclaimer: Camera tilt is currently defined inconsistently between PANGU and the rest of the codebase, as they use different reference frames. This means that if you pass a tilt value to
f2m.trajectory.generate_trajectory()orf2m.trajectory.generate_hohmann_trajectory(), you must convert it appropriately before applying it to rotate the state used in motion field inversion.This conversion is not yet implemented automatically. Instead, this helper function can be used to obtain the correct camera tilt in one of the supported reference frames.
For Hohmann transfers, only equatorial orbits are currently supported.
- Frame Transformations:
- Body ↔ Hohmann:
Body +x → Hohmann +y Body +y → Hohmann -z
- Body ↔ Landing:
Body +x → Landing -x Body +y → Landing +y
- Parameters:
tilt_frame (str) – The reference frame in which to express the camera tilt. Must be one of: “body”, “hohmann”, or “landing”.
pitch (float) – Rotation (in radians) around the body-fixed y-axis. Default is 0.
yaw (float) – Rotation (in radians) around the body-fixed x-axis. Default is 0.
- Returns:
- The Euler angles (roll, pitch, yaw) representing the camera tilt
in the requested frame.
- Return type:
tuple(float, float, float)
Examples
>>> get_camera_tilt("hohmann", pitch=1) (0, 0, -1)
>>> get_camera_tilt("body", pitch=1) (0, 1, 0)
>>> get_camera_tilt("landing", pitch=1) (0, 1, 0)
- f2m.utils.get_dcm_from_euler_angles(angles, sequence='XYZ')¶
Computes the direction cosine matrix (DCM) from given Euler angles.
- Parameters:
angles (np.ndarray 3x1) – The Euler angles [phi, theta, psi] in radians.
sequence (str, optional) – The rotation sequence, either ‘XYZ’ or ‘ZYX’. Default is ‘XYZ’.
- Returns:
The 3x3 DCM corresponding to the given Euler angles.
- Return type:
np.ndarray
- f2m.utils.get_euler_angles_from_dcm(e_x, e_y, e_z, sequence)¶
Computes the Euler angles from a given direction cosine matrix (DCM).
- Parameters:
e_x (np.ndarray 3x1) – The first column of the DCM.
e_y (np.ndarray 3x1) – The second column of the DCM.
e_z (np.ndarray 3x1) – The third column of the DCM.
sequence (str, optional) – The rotation sequence, either ‘XYZ’ or ‘ZYX’. Default is ‘XYZ’.
- Returns:
The computed Euler angles [phi, theta, psi] in radians.
- Return type:
np.ndarray
- f2m.utils.get_quaternion_from_dcm(e_x, e_y, e_z)¶
Computes a quaternion from a given direction cosine matrix (DCM).
- Parameters:
e_x (np.ndarray 3x1) – The first column of the DCM.
e_y (np.ndarray 3x1) – The second column of the DCM.
e_z (np.ndarray 3x1) – The third column of the DCM.
- Returns:
The computed quaternion [q0, q1, q2, q3].
- Return type:
np.ndarray
- f2m.utils.get_quaternion_from_euler_angles(angles, sequence='XYZ')¶
Computes a quaternion from given Euler angles.
- Parameters:
angles (np.ndarray 3x1) – The Euler angles [phi, theta, psi] in radians.
sequence (str, optional) – The rotation sequence, either ‘XYZ’ or ‘ZYX’. Default is ‘XYZ’.
- Returns:
The computed quaternion [q0, q1, q2, q3].
- Return type:
np.ndarray
- f2m.utils.get_quaternion_state_history(state_history: ndarray)¶
Computes the quaternion state history from a given state history.
This function assumes that the camera is oriented such that it points toward the position vector from the origin (e.g., the Moon).
- Parameters:
state_history (np.ndarray) – An array of state vectors, where each row is [x, y, z, vx, vy, vz].
- Returns:
An array of quaternions representing the orientation history.
- Return type:
np.ndarray
- f2m.utils.load_trajectory(traj_dir: Path | str | None = None, verbose: bool = False, use_interp: bool = False, return_throttle: bool = False, return_mass: bool = True, return_ranges: bool = True, custom_traj_file: Path | str | None = None) tuple[ndarray, ndarray, ndarray]¶
Takes either a trajectory directory or custom file as input to load the trajectory. This function is flexible regarding whether mass is given and whether there are range measurements available.
- Parameters:
traj_dir (Path|str|None) – The directory from which to load the trajectory. Defaults to None.
verbose (bool) – Flag to enable verbose output. Defaults to False.
use_interp (bool) – Flag to enable loading the interpolated state. Defaults to False.
return_throttle (bool) – Flag to specify whether the thrust exists and should be returned as a separate array. Defaults to False.
return_mass (bool) – Flag that keeps the mass (if it exists) in the state history, otherwise discard the last column (being mass). Defaults to True.
return_ranges (bool) – An option to determine whether or not the ranges are added to the state history
custom_traj_file (Path|str|None) – The path to the file containing the custom specified state history. Defaults to None.
- Returns:
time, state history, thrusts.
- Return type:
tuple(np.ndarray, np.ndarray, np.ndarray)
- f2m.utils.scale_pixel_coordinates(coord: ndarray, image_width: int) ndarray¶
Scale pixels coordinates in [-0.5, 0.5]
- Parameters:
x (np.ndarray) – pixel coordinates
image_width (int) – image resolution
- Returns:
rescaled coordinates
- Return type:
np.ndarray
f2m.visualization module¶
- f2m.visualization.generate_video_comparison(frames: ndarray, traj: ndarray, of_estimator: LKOpticalFlowEstimator, output_path: Path, rangefinder: bool = True, slope_estimation: bool = False, known_velocity: bool = False, alpha: float = None, beta: float = None, rotation_vector: ndarray = array([0, 0, 0]), focal_length: float = 0.866025, arrow_scale: float = 3.0, frame_interval: int = 1, fps: int = 4, verbose: bool = False, rotation: list[float] = [0, 0, 0]) None¶
Generate the video comparing ground truth optical flow to predicted optical flow for visual comparison
- Parameters:
frames (np.ndarray) – cv2 arrays representing video frames in BGR.
traj (np.ndarray) – trajectory data.
of_estimator (LKOpticalFlowEstimator) – optical flow estimator.
output_path (Path) – Where to save output frames.
rotation_vector (np.ndarray, optional) – Rotation vector for camera perspective in radians [roll, -pitch, yaw]. Defaults to np.array([0, 0, 0]).
focal_length (float, optional) – Focal length of video source.
arrow_scale (float, optional) – scale optical flow arrows for better visualization. Defaults to 3.
frame_interval (int, optional) – Detect new points to track every frame_interval frames. Defaults to 1.
fps (int, optional) – framerate in the output video. Defaults to 4
verbose (bool, optional) – defaults to False
- f2m.visualization.plot_angles(traj_dir: Path, save: bool = False) None¶
- f2m.visualization.plot_angular_velocities(traj_dir: Path, plot_magnitude: bool = False, save: bool = False, as_svg: bool = False) None¶
- f2m.visualization.plot_hohmann_transfer(traj_dir: Path, init_position, alt_a=None, alt_p=None, mu_body=4902800118000.0, planet_radius=1737400.0, save: bool = False)¶
- f2m.visualization.plot_main_thruster(traj_dir: Path, save: bool = False) None¶
- f2m.visualization.plot_mass(traj_dir: Path, save: bool = False) None¶
- f2m.visualization.plot_orbit(orbit_arr: ndarray, planet_radius=1737400.0, translate_planet: ndarray = [0, 0, 0], save: bool = False, title='Generic Orbit', traj_dir=None, elev: float = None, azim: float = None)¶
- f2m.visualization.plot_orbit_textured(orbit_arr: ndarray, texture_file: str, planet_radius: float = 1737400.0, translate_planet: ndarray = [0, 0, 0], downsample_scale: int = 1, sun_pos: tuple = (1000000000.0, 45, 45), save: bool = False, title='Textured Orbit', traj_dir=None, elev: float = None, azim: float = None, show_axes: bool = True)¶
- f2m.visualization.plot_positions(traj_dir: Path, save: bool = False) None¶
- f2m.visualization.plot_rho_vs_z(traj_dir: Path, estimate_z: bool = False, save: bool = False) None¶
- f2m.visualization.plot_thrusters(traj_dir: Path, save: bool = False) None¶
- f2m.visualization.plot_trajectory(traj_dir: Path, save: bool = False, as_svg: bool = False) None¶
- f2m.visualization.plot_velocities(traj_dir: Path, save: bool = False) None¶
- f2m.visualization.plot_velocity_boxplots(results, compare_param='landing_site', filter_params=None, components=['$v_x$', '$v_y$', '$v_z$'], title='Velocity Error Comparison', ylims=None, figsize=(8, 5), legend_label=None, legend_loc='upper right', logscale=False, error_metric='absolute', save=False, svg=False, output_path=None)¶
Creates a grouped box plot showing velocity component errors.
Parameters: - gt_by_group: list of arrays (n_components x time) for each group (e.g., landing site) - pred_by_group: list of arrays, same shape as gt_by_group - group_labels: list of labels (e.g., landing site names), same length as gt_by_group - components: list of component names to label plots - title: plot title - max_error: y-axis limit for error - figsize: figure size - save: whether to save the plot - output_path: path to save to (if save=True)
- f2m.visualization.plot_velocity_comparison(gt, pred, components_to_plot=['vx (m/s)', 'vy (m/s)', 'vz (m/s)'], error_tol=1, title=None, max_error=3, output_path=None, save=False, figsize=(20, 7))¶
- f2m.visualization.plot_velocity_comparison_paper(gt, pred, components_to_plot=['$v_x$ $(m/s)$', '$v_y$ $(m/s)$', '$v_z$ $(m/s)$'], title=None, ylims=None, output_path=None, save=False, svg=False, figsize=(8, 6))¶
- f2m.visualization.set_axes_equal(ax)¶
Make axes of 3D plot have equal scale so that spheres appear as spheres, cubes as cubes, etc.
- Input
ax: a matplotlib axis, e.g., as output from plt.gca().