// BaseClass.h - 完整修复版 #ifndef BASE_CLASS_H #define BASE_CLASS_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "QuadrupedRobotSimulation/OPERATION.h" #include "SharedGeometry/SharedGeometry.h" #include "QuadrupedRobotSimulation/RobotConfig.hpp" using json = nlohmann::json; // 1. 首先完整定义 CheckResultItem 结构 struct CheckResultItem { std::string Condition; // 添加缺失的成员变量 bool Passed = false; std::optional Actual; std::optional Expected; std::optional Tolerance; std::map AdditionalData; CheckResultItem() : Condition(""), Passed(false) { AdditionalData = std::map(); } CheckResultItem(std::string cond, bool passed = false) : Condition(std::move(cond)), Passed(passed) { AdditionalData = std::map(); } }; // 3. 现在安全地声明 CheckResultItem 的序列化函数 void to_json(json &j, const CheckResultItem &item); void from_json(const json &j, CheckResultItem &item); // 3. 前向声明 ModelID struct ModelID; // 4. 在namespace nlohmann中前向声明特化 namespace nlohmann { // 为 std::optional 添加序列化支持 template struct adl_serializer>; // 为 std::vector> 的序列化声明 template <> struct adl_serializer>>; // 为 Vector2D 的序列化声明 template <> struct adl_serializer; // 为 ModelID 的序列化声明 template <> struct adl_serializer; } struct RobotGaitRequest { RequestParameters req_param; }; struct LinkModelIDInfo { std::string LinkName; std::string ModelID; std::string StartPoint; std::string EndPoint; std::string Description; NLOHMANN_DEFINE_TYPE_INTRUSIVE(LinkModelIDInfo, LinkName, ModelID, StartPoint, EndPoint, Description) }; struct LegLinkDisplay { std::string LegName; std::string LinkName; std::string ModelID; std::string StartPoint; std::string EndPoint; std::string Description; int Index = 0; std::string UniqueID; NLOHMANN_DEFINE_TYPE_INTRUSIVE(LegLinkDisplay, LegName, LinkName, ModelID, StartPoint, EndPoint, Description, Index, UniqueID) }; struct RobotData { GaitInfo GaitInfo; SystemParameters SystemParameters; std::vector LF; std::vector LH; std::vector RF; std::vector RH; NLOHMANN_DEFINE_TYPE_INTRUSIVE(RobotData, GaitInfo, SystemParameters, LF, LH, RF, RH) }; struct Point2D { double X = 0.0; double Y = 0.0; Point2D() = default; Point2D(double x, double y); friend void to_json(json &j, const Point2D &p); friend void from_json(const json &j, Point2D &p); }; struct FrameData { int FrameNumber = 0; double Time = 0.0; int ShiftedFrameNumber = 0; Point2D A_Point; Point2D B_Point; Point2D C_Point; Point2D L_Point; Point2D D1_Point; Point2D D2_Point; Point2D C4_Point; Point2D B1_Point; Point2D B2_Point; Point2D C1_Point; Point2D C2_Point; Point2D C3_Point; double AB_Horizontal_Angle = 0.0; double AB_BC_Angle = 0.0; double BC_CL_Angle = 0.0; double AB1_AB_Angle = 0.0; double C3_C4_Distance = 0.0; double C2_C3_Distance = 0.0; double C2_C4_Distance = 0.0; double C2_C3_C4_Angle = 0.0; NLOHMANN_DEFINE_TYPE_INTRUSIVE(FrameData, FrameNumber, Time, ShiftedFrameNumber, A_Point, B_Point, C_Point, L_Point, D1_Point, D2_Point, C4_Point, B1_Point, B2_Point, C1_Point, C2_Point, C3_Point, AB_Horizontal_Angle, AB_BC_Angle, BC_CL_Angle, AB1_AB_Angle, C3_C4_Distance, C2_C3_Distance, C2_C4_Distance, C2_C3_C4_Angle) }; struct LegTrajectory { std::string LegCode; int PhaseShift = 0; bool IsRightLeg = false; std::vector Frames; NLOHMANN_DEFINE_TYPE_INTRUSIVE(LegTrajectory, LegCode, PhaseShift, IsRightLeg, Frames) }; struct TrajectoryData { int TotalFrames = 0; double StepTime = 0.0; std::map Legs; NLOHMANN_DEFINE_TYPE_INTRUSIVE(TrajectoryData, TotalFrames, StepTime, Legs) }; struct MotorInfo { double Angle = 0.0; double AngleIncrement = 0.0; double Speed = 0.0; NLOHMANN_DEFINE_TYPE_INTRUSIVE(MotorInfo, Angle, AngleIncrement, Speed) }; struct MotorFrameData { int FrameNumber = 0; double StartTime = 0.0; double EndTime = 0.0; MotorInfo Thigh; MotorInfo Shank; MotorInfo Ankle; double C3C4_Distance = 0.0; double C3C4_DistanceIncrement = 0.0; NLOHMANN_DEFINE_TYPE_INTRUSIVE(MotorFrameData, FrameNumber, StartTime, EndTime, Thigh, Shank, Ankle, C3C4_Distance, C3C4_DistanceIncrement) }; struct LegMotorData { std::string LegCode; std::vector Frames; NLOHMANN_DEFINE_TYPE_INTRUSIVE(LegMotorData, LegCode, Frames) }; struct MotorDataExport { double StepTime = 0.0; std::map Legs; NLOHMANN_DEFINE_TYPE_INTRUSIVE(MotorDataExport, StepTime, Legs) }; struct MinMax { double Min = 0.0; double Max = 0.0; double Range = 0.0; NLOHMANN_DEFINE_TYPE_INTRUSIVE(MinMax, Min, Max, Range) }; struct AngleConstraint { double MinAllowed = 0.0; double MaxAllowed = 0.0; double MinActual = 0.0; double MaxActual = 0.0; bool IsValid = false; std::string CheckType; NLOHMANN_DEFINE_TYPE_INTRUSIVE(AngleConstraint, MinAllowed, MaxAllowed, MinActual, MaxActual, IsValid, CheckType) }; struct DistanceConstraint { double MinAllowed = 0.0; double MaxAllowed = 0.0; double MinActual = 0.0; double MaxActual = 0.0; bool IsValid = false; NLOHMANN_DEFINE_TYPE_INTRUSIVE(DistanceConstraint, MinAllowed, MaxAllowed, MinActual, MaxActual, IsValid) }; struct PerpendicularityConstraint { double MaxDotProduct = 0.0; double MinDotProduct = 0.0; bool IsValid = false; NLOHMANN_DEFINE_TYPE_INTRUSIVE(PerpendicularityConstraint, MaxDotProduct, MinDotProduct, IsValid) }; struct ConstraintViolation { std::string ConstraintType; int Frame = 0; double Time = 0.0; double Value = 0.0; std::string AllowedRange; std::string Severity; NLOHMANN_DEFINE_TYPE_INTRUSIVE(ConstraintViolation, ConstraintType, Frame, Time, Value, AllowedRange, Severity) }; struct ConstraintData { AngleConstraint AB1_AB_Constraint; DistanceConstraint C3C4_Constraint; DistanceConstraint CL_Distance_Constraint; PerpendicularityConstraint Perpendicularity_Constraint; std::vector ConstraintViolations; NLOHMANN_DEFINE_TYPE_INTRUSIVE(ConstraintData, AB1_AB_Constraint, C3C4_Constraint, CL_Distance_Constraint, Perpendicularity_Constraint, ConstraintViolations) }; struct AngleStatistics { MinMax AB_Horizontal; MinMax AB_BC; MinMax BC_CL; MinMax AB1_AB; NLOHMANN_DEFINE_TYPE_INTRUSIVE(AngleStatistics, AB_Horizontal, AB_BC, BC_CL, AB1_AB) }; struct DistanceStatistics { MinMax C3_C4; MinMax C2_C3; MinMax C2_C4; NLOHMANN_DEFINE_TYPE_INTRUSIVE(DistanceStatistics, C3_C4, C2_C3, C2_C4) }; struct MotorSpeedStatistics { MinMax Thigh; MinMax Shank; MinMax Ankle; NLOHMANN_DEFINE_TYPE_INTRUSIVE(MotorSpeedStatistics, Thigh, Shank, Ankle) }; struct TrajectoryStatistics { int TotalFrames = 0; double TotalTime = 0.0; int SwingFrames = 0; int SupportFrames = 0; NLOHMANN_DEFINE_TYPE_INTRUSIVE(TrajectoryStatistics, TotalFrames, TotalTime, SwingFrames, SupportFrames) }; struct StatisticsData { AngleStatistics AngleStatistics; DistanceStatistics DistanceStatistics; MotorSpeedStatistics MotorSpeedStatistics; TrajectoryStatistics TrajectoryStatistics; NLOHMANN_DEFINE_TYPE_INTRUSIVE(StatisticsData, AngleStatistics, DistanceStatistics, MotorSpeedStatistics, TrajectoryStatistics) }; struct RawInitialAngles { double Thigh = 0.0; double Shank = 0.0; double Ankle = 0.0; NLOHMANN_DEFINE_TYPE_INTRUSIVE(RawInitialAngles, Thigh, Shank, Ankle) }; struct CalibratedAngles { double Thigh = 0.0; double Shank = 0.0; double Ankle = 0.0; NLOHMANN_DEFINE_TYPE_INTRUSIVE(CalibratedAngles, Thigh, Shank, Ankle) }; struct Adjustments { double ThighAdjustment = 0.0; double ShankAdjustment = 0.0; double AnkleAdjustment = 0.0; NLOHMANN_DEFINE_TYPE_INTRUSIVE(Adjustments, ThighAdjustment, ShankAdjustment, AnkleAdjustment) }; struct LegInitialAngles { std::string LegCode; RawInitialAngles RawInitialAngles; CalibratedAngles CalibratedAngles; Adjustments Adjustments; NLOHMANN_DEFINE_TYPE_INTRUSIVE(LegInitialAngles, LegCode, RawInitialAngles, CalibratedAngles, Adjustments) }; struct InitialAnglesData { std::map Legs; NLOHMANN_DEFINE_TYPE_INTRUSIVE(InitialAnglesData, Legs) }; struct PhaseInfo { std::string GaitType; double TimeLF = 0.0; double TimeLH = 0.0; double TimeRF = 0.0; double TimeRH = 0.0; int PhaseLF = 0; int PhaseLH = 0; int PhaseRF = 0; int PhaseRH = 0; double SupportRatio = 0.0; double SwingRatio = 0.0; double SupportTime = 0.0; double SwingTime = 0.0; NLOHMANN_DEFINE_TYPE_INTRUSIVE(PhaseInfo, GaitType, TimeLF, TimeLH, TimeRF, TimeRH, PhaseLF, PhaseLH, PhaseRF, PhaseRH, SupportRatio, SwingRatio, SupportTime, SwingTime) }; struct MotionRange { MinMax X; MinMax Y; double TotalRange = 0.0; NLOHMANN_DEFINE_TYPE_INTRUSIVE(MotionRange, X, Y, TotalRange) }; struct LegMotionRange { std::string LegCode; int PhaseShift = 0; MotionRange L_Point; NLOHMANN_DEFINE_TYPE_INTRUSIVE(LegMotionRange, LegCode, PhaseShift, L_Point) }; struct MotionRangeData { std::map Legs; NLOHMANN_DEFINE_TYPE_INTRUSIVE(MotionRangeData, Legs) }; struct SplitModelID { std::vector>> LF; std::vector>> LH; std::vector>> RF; std::vector>> RH; NLOHMANN_DEFINE_TYPE_INTRUSIVE(SplitModelID, LF, LH, RF, RH) }; // 支撑点检查结果类 struct SupportCheckResult { bool IsSupport = false; std::map Checks; std::vector Reasons; std::vector FailedChecks; SupportCheckResult(); NLOHMANN_DEFINE_TYPE_INTRUSIVE(SupportCheckResult, IsSupport, Checks, Reasons, FailedChecks) }; class MotorData { public: std::vector frame_start_times; std::vector frame_end_times; std::vector AB_angles; std::vector AB_angle_increments; std::vector thigh_motor_speeds; std::vector AB1_AB_angles; std::vector AB1_AB_angle_increments; std::vector shank_motor_speeds; std::vector C3C4_distances; std::vector C3C4_distance_increments; std::vector ankle_motor_angles; std::vector ankle_motor_angle_increments; std::vector ankle_motor_speeds; MotorData(int n_frames = 0); void Resize(int n_frames); MotorData Clone() const; friend void to_json(json &j, const MotorData &md); friend void from_json(const json &j, MotorData &md); }; struct ReverseCalculationResult { int Frame = 0; double Time = 0.0; std::map> Points; bool Valid = false; std::vector Errors; NLOHMANN_DEFINE_TYPE_INTRUSIVE(ReverseCalculationResult, Frame, Time, Points, Valid, Errors) }; struct CompleteExportData { GaitInfo GaitInfo; SystemParameters SystemParameters; TrajectoryData TrajectoryData; MotorDataExport MotorData; ConstraintData ConstraintData; StatisticsData Statistics; InitialAnglesData InitialAngles; PhaseInfo PhaseInfo; MotionRangeData MotionRange; NLOHMANN_DEFINE_TYPE_INTRUSIVE(CompleteExportData, GaitInfo, SystemParameters, TrajectoryData, MotorData, ConstraintData, Statistics, InitialAngles, PhaseInfo, MotionRange) }; class ModelIDSplitter { public: // 修改参数类型为 const ModelID& static SplitModelID SplitModelIDToArrays(const ModelID &modelID, const std::map> &pointsDict); private: static std::vector>> SplitLegDictionaryDataToArrays(const std::vector> &legData, const std::set &validKeys); static std::map> SplitDictionaryToArrays(const std::map &dict, const std::set &validKeys); static std::vector SplitKey(const std::string &compositeKey, const std::set &validKeys); }; class QuadrupedRobotConfiguration { public: // 基本几何参数 std::vector A_point; double L10; double L20; double L30; // 小腿连杆机构参数 double L21; double L22; double L23; double beta1; double CC1; // 脚踝连杆机构参数 double L31; double C2C3_length; double lead1; // 步态控制参数 double s_l; double s_h; double X; // 脚部构型参数 double D1_L_offset; double D2_L_offset; double C4_D2_offset; // 步态控制参数 double T; double f; std::string gait_type; double support_ratio; double swing_ratio; // 电机参数 double thigh_motor_reduction; double shank_motor_reduction; double ankle_motor_reduction; // 逆向运动学特有参数 double adjusted_shank_angles_factory; // 初始C3C4距离 double initial_C3C4_LF; double initial_C3C4_LH; double initial_C3C4_RF; double initial_C3C4_RH; // 计算得到的中间变量 double BB2_BC_angle_rad; double C1_B_length; double CC4_reference_distance; double deltX; double step; double t_s; double t_w; double timeLF; double timeLH; double timeRF; double timeRH; QuadrupedRobotConfiguration(); QuadrupedRobotConfiguration(const GaitInfo &gaitInfo, const SystemParameters &sysParams); void FromGaitInfoAndSystemParameters(const GaitInfo &gaitInfo, const SystemParameters &sysParams); void CalculateDerivedParameters(); struct ValidationResultFrame { int Frame = 0; double ThighAngle = 0.0; double ShankAngle = 0.0; double AnkleAngle = 0.0; bool IsValid = false; NLOHMANN_DEFINE_TYPE_INTRUSIVE(ValidationResultFrame, Frame, ThighAngle, ShankAngle, AnkleAngle, IsValid) }; // 在QuadrupedRobotConfiguration类中添加公共方法(BaseClass.h中) void debugPrint() const; struct ValidationResult { bool IsValid = false; std::vector Errors; std::vector Warnings; ValidationResult(); NLOHMANN_DEFINE_TYPE_INTRUSIVE(ValidationResult, IsValid, Errors, Warnings) }; ValidationResult Validate() const; private: void FromSystemParameters(const SystemParameters &sysParams); void FromGaitInfo(const GaitInfo &gaitInfo); friend void to_json(json &j, const QuadrupedRobotConfiguration &config); friend void from_json(const json &j, QuadrupedRobotConfiguration &config); }; class RobotGaitDataManager { private: RobotGaitRequest _data; static std::mutex _lock; public: RobotGaitDataManager(); const RobotGaitRequest &GetData() const; void SetData(const RobotGaitRequest &data); void LoadFromJson(const nlohmann::json &j, bool useDefaultForMissing = true); void LoadDefaultData(); ModelID GetModelIDObject() const; GaitInfo GetGaitInfo() const; SystemParameters GetSystemParameters() const; std::map>> GetModelID() const; LegParameters GetParam() const; RobotBody GetRobotBody() const; std::map GetParamDictionary() const; // 在 RobotGaitDataManager 类声明中修改 std::map> Get_old_initial_points_dictLF() const; std::map> Get_old_initial_points_dictLH() const; void Set_old_initial_points_dictLF(const std::map> &L_point); void Set_old_initial_points_dictLH(const std::map> &L_point); void SetRobotBody_x(const double x); private: RobotGaitRequest CreateDefaultRobotGaitRequest() const; RobotGaitRequest FillMissingDataWithDefaults(const RobotGaitRequest &data) const; static bool IsDefaultValue(double value); }; class SimulationStatistics { public: int TotalFrames = 0; double TotalTime = 0.0; double MinABAngle = 0.0; double MaxABAngle = 0.0; double MinBCAngle = 0.0; double MaxBCAngle = 0.0; double MinAB1ABAngle = 0.0; double MaxAB1ABAngle = 0.0; double MinC3C4Distance = 0.0; double MaxC3C4Distance = 0.0; double MaxThighSpeed = 0.0; double MaxShankSpeed = 0.0; double MaxAnkleSpeed = 0.0; SimulationStatistics() = default; explicit SimulationStatistics(const QuadrupedRobotConfiguration &config); std::string ToString() const; friend void to_json(json &j, const SimulationStatistics &stats); friend void from_json(const json &j, SimulationStatistics &stats); }; class SplitModelIDExtensions { public: static std::map>> ToSimpleDictionary(const SplitModelID &splitModelID); private: static std::map> MergeLegData(const std::vector>> &legData); }; // 实用函数 Point2D ArrayToPoint(const std::vector &array); #endif // BASE_CLASS_H