Source code for suboptimumg.track.track_factory

import numpy as np

from .gps import *
from .models import *
from .track import Track
from .utils import *


[docs] def from_corners(corner_input: CornerListInput): """ Factory method to generate a Track class from a list of corners. Compatible with tracks saved in YAML. Parameters ---------- corner_input : CornerListInput Corner list input containing corners and track parameters Returns ------- Track Track instance created from corner list """ # Convert corner length to step count. Optionally scale the length of a track. discretized_corners = scale_and_discretize_corner_lengths( corner_input.corners, corner_input.shorten * (0.1 / corner_input.distance_step), ) x_m, y_m, arcs = corners_to_cartesian( discretized_corners, corner_input.distance_step, start_angle_deg=corner_input.ideal_rotation_angle, ) if corner_input.clean_corners: discretized_corners = smooth_and_normalize_corner_radii(discretized_corners) dx, radius, cumulative_dist = unroll_corners_into_track( discretized_corners, corner_input.distance_step ) return Track( dx, radius, cumulative_dist, x_m, y_m, corner_input.distance_step, False, original_corners=corner_input.corners, arcs=arcs, )
[docs] def from_coordinates(coord_input: CoordinateListInput): """ Factory method to generate a Track from GPS coordinates (latitude/longitude). Creates a continuous representation with Menger curvature, then discretizes it. Parameters ---------- coord_input: CoordinateListInput Contains GPS coordinates and track parameters Returns ------- Track Track instance with continuous representation """ spline_data, tck, cumulative_dist = gps_interpolate( coord_input, ) x_m, y_m, absolute_origin = gps_to_cartesian(spline_data, origin_offset=True) # TODO: improve implementation of this whole thing. # gps_to_cartesian should be performed first, then interpolate # however interpolate doesn't actually equally space the points # so for now manually reinterpolate here. # Compute actual 2D arc length along the path dx_points = np.diff(x_m) dy_points = np.diff(y_m) distances = np.sqrt(dx_points**2 + dy_points**2) # Compute cumulative arc length arc_length = np.zeros(len(x_m)) arc_length[1:] = np.cumsum(distances) # Create uniform arc length array with distance_step spacing total_arc_length = arc_length[-1] num_points = int(np.ceil(total_arc_length / coord_input.distance_step)) + 1 uniform_arc_length = np.linspace(0, total_arc_length, num_points) # Interpolate x and y at uniform arc lengths x_m = np.interp(uniform_arc_length, arc_length, x_m) y_m = np.interp(uniform_arc_length, arc_length, y_m) cumulative_dist = uniform_arc_length # Calculate radii and dx dx = np.full(cumulative_dist.shape, coord_input.distance_step) radii = np.full(cumulative_dist.shape, 0.0) for idx in range(len(cumulative_dist)): _, radius = calculate_menger_curvature( x_m, y_m, cumulative_dist, cumulative_dist[idx], coord_input.sample_dist, ) radii[idx] = radius return Track( dx, radii, cumulative_dist, x_m, y_m, coord_input.distance_step, True, sample_dist=coord_input.sample_dist, tck=tck, absolute_origin=absolute_origin, )
[docs] def from_data(data: TrackData) -> Track: """ Factory method to create a Track from a TrackData model. Parameters ---------- data : ContinuousTrackData | DiscreteTrackData A TrackData instance containing all track fields including pre-computed seed indices Returns ------- Track A new Track instance with all fields populated from the data model """ # Create a new Track instance without calling __init__ instance = Track.__new__(Track) # Set common fields instance.dx = data.dx instance.radius = data.radius instance.cumulative_dist = data.cumulative_dist instance.x_m = data.x_m instance.y_m = data.y_m instance.distance_step = data.distance_step instance.seed_idx = data.seed_idx # Set type-specific fields match data: case ContinuousTrackData(): instance.continuous = True instance.sample_dist = data.sample_dist instance.tck = data.tck instance.absolute_origin = data.absolute_origin case DiscreteTrackData(): instance.continuous = False instance.original_corners = data.original_corners instance.arcs = data.arcs return instance