using System; using System.Runtime.InteropServices; namespace MultiWheelC.TrajectoryPlanning.EMPlanner; [StructLayout(LayoutKind.Sequential, Pack = 8)] internal struct OsqpCscMatrix { public int RowCount; public int ColumnCount; public IntPtr ColumnPointers; public IntPtr RowIndices; public IntPtr Values; public int MaximumNonZeroCount; public int NonZeroCount; public int OwnsData; } [StructLayout(LayoutKind.Sequential, Pack = 8)] internal struct OsqpSettings { public int Device; public int LinearSystemSolver; public int AllocateSolution; public int Verbose; public int ProfilerLevel; public int WarmStarting; public int Scaling; public int Polishing; public double Rho; public int RhoIsVector; public double Sigma; public double Alpha; public int ConjugateGradientMaximumIterations; public int ConjugateGradientToleranceReduction; public double ConjugateGradientToleranceFraction; public int ConjugateGradientPreconditioner; public int AdaptiveRho; public int AdaptiveRhoInterval; public double AdaptiveRhoFraction; public double AdaptiveRhoTolerance; public int MaximumIterations; public double AbsoluteTolerance; public double RelativeTolerance; public double PrimalInfeasibilityTolerance; public double DualInfeasibilityTolerance; public int ScaledTermination; public int CheckTermination; public int CheckDualityGap; public double TimeLimit; public double PolishingDelta; public int PolishingRefinementIterations; } [StructLayout(LayoutKind.Sequential, Pack = 8)] internal struct OsqpInfo { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.I1)] public byte[] Status; public int StatusValue; public int PolishingStatus; public double ObjectiveValue; public double DualObjectiveValue; public double PrimalResidual; public double DualResidual; public double DualityGap; public int Iterations; public int RhoUpdates; public double RhoEstimate; public double SetupTime; public double SolveTime; public double UpdateTime; public double PolishingTime; public double RunTime; public double PrimalDualIntegral; public double RelativeKktError; } [StructLayout(LayoutKind.Sequential, Pack = 8)] internal struct OsqpSolution { public IntPtr Primal; public IntPtr Dual; public IntPtr PrimalInfeasibilityCertificate; public IntPtr DualInfeasibilityCertificate; } [StructLayout(LayoutKind.Sequential, Pack = 8)] internal struct OsqpSolverPrefix { public IntPtr Settings; public IntPtr Solution; public IntPtr Info; public IntPtr Workspace; } internal static class OsqpNativeStructures { public static void ValidatePinnedLayout() { AssertSize(typeof(OsqpCscMatrix), 48); AssertOffset(typeof(OsqpCscMatrix), nameof(OsqpCscMatrix.ColumnPointers), 8); AssertOffset(typeof(OsqpCscMatrix), nameof(OsqpCscMatrix.Values), 24); AssertOffset(typeof(OsqpCscMatrix), nameof(OsqpCscMatrix.MaximumNonZeroCount), 32); AssertSize(typeof(OsqpSettings), 192); AssertOffset(typeof(OsqpSettings), nameof(OsqpSettings.Rho), 32); AssertOffset(typeof(OsqpSettings), nameof(OsqpSettings.Sigma), 48); AssertOffset(typeof(OsqpSettings), nameof(OsqpSettings.ConjugateGradientToleranceFraction), 72); AssertOffset(typeof(OsqpSettings), nameof(OsqpSettings.AdaptiveRhoFraction), 96); AssertOffset(typeof(OsqpSettings), nameof(OsqpSettings.AbsoluteTolerance), 120); AssertOffset(typeof(OsqpSettings), nameof(OsqpSettings.TimeLimit), 168); AssertOffset(typeof(OsqpSettings), nameof(OsqpSettings.PolishingRefinementIterations), 184); AssertSize(typeof(OsqpInfo), 152); AssertOffset(typeof(OsqpInfo), nameof(OsqpInfo.StatusValue), 32); AssertOffset(typeof(OsqpInfo), nameof(OsqpInfo.ObjectiveValue), 40); AssertOffset(typeof(OsqpInfo), nameof(OsqpInfo.Iterations), 80); AssertOffset(typeof(OsqpInfo), nameof(OsqpInfo.SetupTime), 96); AssertOffset(typeof(OsqpInfo), nameof(OsqpInfo.RelativeKktError), 144); AssertSize(typeof(OsqpSolution), 32); AssertSize(typeof(OsqpSolverPrefix), 32); AssertOffset(typeof(OsqpSolverPrefix), nameof(OsqpSolverPrefix.Workspace), 24); } public static OsqpNativeSetupMemory AllocateSetupMemory(OsqpNativeMethods.SetDefaultSettingsDelegate setDefaultSettings) { if (setDefaultSettings == null) throw new ArgumentNullException(nameof(setDefaultSettings)); return new OsqpNativeSetupMemory(setDefaultSettings); } private static void AssertSize(Type type, int expectedSize) { int actualSize = Marshal.SizeOf(type); if (actualSize != expectedSize) throw new InvalidOperationException(type.Name + " has native size " + actualSize + " instead of " + expectedSize + "."); } private static void AssertOffset(Type type, string fieldName, int expectedOffset) { int actualOffset = checked((int)Marshal.OffsetOf(type, fieldName).ToInt64()); if (actualOffset != expectedOffset) throw new InvalidOperationException(type.Name + "." + fieldName + " has native offset " + actualOffset + " instead of " + expectedOffset + "."); } } internal sealed class OsqpNativeSetupMemory : IDisposable { private IntPtr upperTriangularP; private IntPtr constraints; private IntPtr settings; public OsqpNativeSetupMemory(OsqpNativeMethods.SetDefaultSettingsDelegate setDefaultSettings) { try { upperTriangularP = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(OsqpCscMatrix))); constraints = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(OsqpCscMatrix))); settings = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(OsqpSettings))); Zero(upperTriangularP, Marshal.SizeOf(typeof(OsqpCscMatrix))); Zero(constraints, Marshal.SizeOf(typeof(OsqpCscMatrix))); Zero(settings, Marshal.SizeOf(typeof(OsqpSettings))); setDefaultSettings(settings); } catch { Dispose(); throw; } } public IntPtr UpperTriangularP { get { return upperTriangularP; } } public IntPtr Constraints { get { return constraints; } } public IntPtr Settings { get { return settings; } } public void Dispose() { if (settings != IntPtr.Zero) { Marshal.FreeHGlobal(settings); settings = IntPtr.Zero; } if (constraints != IntPtr.Zero) { Marshal.FreeHGlobal(constraints); constraints = IntPtr.Zero; } if (upperTriangularP != IntPtr.Zero) { Marshal.FreeHGlobal(upperTriangularP); upperTriangularP = IntPtr.Zero; } } private static void Zero(IntPtr memory, int byteCount) { for (int index = 0; index < byteCount; index++) Marshal.WriteByte(memory, index, 0); } }