using System; using MultiWheelC.TrajectoryPlanning.CoarsePath; using MultiWheelC.TrajectoryPlanning.Utils; namespace MultiWheelC.TrajectoryPlanning.EMPlanner; /// Coordinate conversion that keeps Frenet lateral sign relative to travel direction. public static class FrenetTransform { public static bool TryReconstruct(FrenetReferencePoint referencePoint, double lateralOffset, double lateralDerivative, double minimumFrenetDenominator, out Pose2D pose) { pose = null; if (referencePoint == null || !IsFinite(lateralOffset) || !IsFinite(lateralDerivative) || !IsFinite(minimumFrenetDenominator) || minimumFrenetDenominator <= 0d) return false; double denominator = 1d - referencePoint.GeometricCurvature * lateralOffset; if (!IsFinite(denominator) || denominator < minimumFrenetDenominator) return false; double travelYaw = referencePoint.TravelYaw; double x = referencePoint.X - lateralOffset * Math.Sin(travelYaw); double y = referencePoint.Y + lateralOffset * Math.Cos(travelYaw); double optimizedTravelYaw = travelYaw + Math.Atan2(lateralDerivative, denominator); double vehicleYaw = referencePoint.Direction == TravelDirection.Forward ? AngleMath.NormalizeRadians(optimizedTravelYaw) : AngleMath.NormalizeRadians(optimizedTravelYaw + Math.PI); if (!IsFinite(x) || !IsFinite(y) || !IsFinite(vehicleYaw)) return false; pose = new Pose2D(x, y, vehicleYaw); return true; } internal static double GetTravelYaw(double vehicleYaw, TravelDirection direction) { return direction == TravelDirection.Forward ? vehicleYaw : vehicleYaw + Math.PI; } private static bool IsFinite(double value) { return !double.IsNaN(value) && !double.IsInfinity(value); } }