namespace RobotNet10.RobotApp.SLAM.Cartographer; /// /// MCL configuration (from mcl.yaml). Used when SetInitialPoseAsync runs MCL before adding localization trajectory. /// public class MclConfiguration { public bool Enabled { get; set; } public double InitialNoiseX { get; set; } = 1.0; public double InitialNoiseY { get; set; } = 1.0; public double InitialNoiseYaw { get; set; } = 0.3; /// When user provides initial pose (SetInitialPoseAsync), use these smaller noise values so particles stay near the pose and iteration 1 does not jump far. If zero, fall back to InitialNoiseX/Y/Yaw. public double InitialNoiseWhenPoseGivenX { get; set; } = 0.15; public double InitialNoiseWhenPoseGivenY { get; set; } = 0.15; public double InitialNoiseWhenPoseGivenYaw { get; set; } = 0.05; public int ParticlesNum { get; set; } = 1000; public bool UseAugmentedMcl { get; set; } public bool AddRandomParticlesInResampling { get; set; } = true; public double RandomParticlesRate { get; set; } = 0.1; public double[] RandomParticlesNoise { get; set; } = [0.05f, 0.05f, 0.1]; public double[] OdomNoiseDdm { get; set; } = [1.0, 0.5, 0.5, 1.5]; /// Odometry noise for omni-directional model (9 params: xx, xy, xyaw, yx, yy, yyaw, yawx, yawy, yawyaw). Used when UseOmniDirectionalModel=true. public double[] OdomNoiseOdm { get; set; } = [4.0, 1.0, 1.0, 1.0, 4.0, 1.0, 1.0, 1.0, 8.0]; public bool UseOmniDirectionalModel { get; set; } public int MeasurementModelType { get; set; } = 0; /// Scan step for likelihood calculation (xloc: scanStep_ = 10). Use every Nth beam to avoid underflow with many beams. 1 = use all beams (slow, underflow risk), 10 = every 10th beam (recommended). public int ScanStep { get; set; } = 10; public double ZHit { get; set; } = 0.9; public double ZShort { get; set; } = 0.2; public double ZMax { get; set; } = 0.05; public double ZRand { get; set; } = 0.05; public double VarHit { get; set; } = 0.08; public double LambdaShort { get; set; } = 1.0; public double LambdaUnknown { get; set; } = 0.01; /// Prior probability for known obstacles (class-conditional model). Default: 0.5. xloc: pKnownPrior_. public double KnownClassPrior { get; set; } = 0.5; /// Computed: Prior probability for known obstacles (same as KnownClassPrior, for C# code compatibility). public double PKnownPrior => KnownClassPrior; /// Computed: Prior probability for unknown obstacles (1 - KnownClassPrior). public double PUnknownPrior => 1.0 - KnownClassPrior; public double UnknownScanProbThreshold { get; set; } = 0.9; public double AlphaSlow { get; set; } = 0.001; public double AlphaFast { get; set; } = 0.99; public bool RejectUnknownScan { get; set; } = true; public double ResampleThresholdEss { get; set; } = 0.5; public double[] ResampleThresholds { get; set; } = [0.2, 0.2, 0.2, 0.02f, -99999.0]; /// Reliability transition decay for differential drive (2 params: dist_coeff, yaw_coeff). Used when UseOmniDirectionalModel=false. public double[] RelTransDdm { get; set; } = [0.0, 0.0]; /// Reliability transition decay for omni-directional (3 params: x_coeff, y_coeff, yaw_coeff). Used when UseOmniDirectionalModel=true. public double[] RelTransOdm { get; set; } = [0.0, 0.0, 0.0]; public int ClassifierType { get; set; } /// Estimate reliability per particle (MAE-based); used by decision model (xloc: estimateReliability_). public bool EstimateReliability { get; set; } /// MAE failure threshold in meters for simple decision model when classifier files not used (xloc: ~0.12). public double FailureThreshold { get; set; } = 0.12; /// Use global-localization pose sampler (merge external poses as extra particles). public bool UseGLPoseSampler { get; set; } /// Max time diff (sec) between scan and GL poses to fuse (xloc: glSampledPoseTimeTH_). public double GLSampledPoseTimeTH { get; set; } = 0.5; /// GMM positional variance for GL predictive likelihood (xloc: gmmPositionalVariance_). public double GmmPositionalVariance { get; set; } = 0.1; /// GMM angular variance for GL predictive likelihood (xloc: gmmAngularVariance_). public double GmmAngularVariance { get; set; } = 0.1; /// Uniform rate in predictive distribution for GL (xloc: predDistUnifRate_). public double PredDistUnifRate { get; set; } = 0.05; /// Pose change below this (meters) for convergence (xloc: pose_change_threshold 0.03). public double ConvergencePoseChangeThresholdMeters { get; set; } = 0.03; /// Yaw change below this (radians) for convergence (xloc: yaw_change_threshold 0.05). public double ConvergenceYawChangeThresholdRad { get; set; } = 0.05; /// Pose must stay stable for this duration (seconds) before convergence (xloc: stable_duration 0.3). public double ConvergenceStableDurationSeconds { get; set; } = 0.3; /// Min reliability [0,1] to allow pose-stable convergence (xloc: reliability_ >= 0.9). public double ConvergenceReliabilityMin { get; set; } = 0.9; /// Max MAE (meters) for best particle to allow pose-stable convergence (xloc: mae <= 0.12). public double ConvergenceMaeMaxMeters { get; set; } = 0.12; /// Timeout in seconds; after this, force convergence with initial pose (for Relocalizing state auto-resume fallback). public double ConvergenceTimeoutSeconds { get; set; } = 30.0; /// /// Max MCL iterations before forcing convergence. /// Note: C# does 5 iterations per scan. At 10Hz lidar = 50 iter/sec. /// 1500 iterations = 30 seconds at 10Hz, 60 seconds at 5Hz (matches ConvergenceTimeoutSeconds). /// public int ConvergenceMaxIterations { get; set; } = 1500; /// /// Min MCL iterations before allowing convergence (at least 2 scans at 10Hz). /// public int ConvergenceMinIterations { get; set; } = 10; /// /// DeviceId of the lidar used for MCL scan (xloc uses a single "scan" topic). /// If null or empty, the first lidar in Sensors.Lidars is used. /// When multiple lidars exist, only this lidar's range data is passed to MCL; others are ignored during MCL phase. /// public string? PrimaryLidarId { get; set; } /// /// MCL reliability monitoring configuration for Localizing state /// public MclReliabilityMonitoringConfiguration ReliabilityMonitoring { get; set; } = new(); } /// /// MCL reliability monitoring configuration for Localizing state /// Runs MCL periodically (every 2 seconds by default) to provide reliability and MAE metrics /// public class MclReliabilityMonitoringConfiguration { /// /// Enable MCL reliability monitoring during Localizing state /// public bool EnableReliabilityMonitoring { get; set; } = true; /// /// Interval between MCL updates (seconds) /// public double MonitoringIntervalSeconds { get; set; } = 2.0; /// /// Number of particles for monitoring (less than initialization for performance) /// Recommended: 500 (vs 1000 for initialization) /// public int MonitoringParticlesNum { get; set; } = 500; /// /// Number of MCL iterations per monitoring cycle /// public int MonitoringIterationsPerCycle { get; set; } = 5; }