// CompleteJsonExporter.cpp #include "QuadrupedRobotSimulation/CompleteJsonExporter.h" #include "QuadrupedRobotSimulation/BaseClass.h" #include "QuadrupedRobotSimulation/KinematicsSimulation.h" #include #include #include #include #include #include // 主导出函数 std::string CompleteJsonExporter::ExportCompleteDataJsonString(const QuadrupedRobotSimulation &simulation) { try { // 创建数据对象 CompleteExportData exportData; // 基本信息 exportData.GaitInfo = CreateGaitInfo(simulation); // 系统参数 exportData.SystemParameters = CreateSystemParameters(simulation); // 轨迹数据(所有腿) exportData.TrajectoryData = CreateTrajectoryData(simulation); // 电机数据(所有腿) exportData.MotorData = CreateMotorData(simulation); // 约束检查数据 exportData.ConstraintData = CreateConstraintData(simulation); // 统计信息 exportData.Statistics = CreateStatistics(simulation); // 初始角度数据 exportData.InitialAngles = CreateInitialAngles(simulation); // 相位信息 exportData.PhaseInfo = CreatePhaseInfo(simulation); // 运动范围统计 exportData.MotionRange = CreateMotionRange(simulation); // 序列化为JSON json j = exportData; return j.dump(2); // 缩进2个空格 } catch (const std::exception &ex) { std::cerr << "导出JSON数据时出错: " << ex.what() << std::endl; throw; } } // 创建步态信息 GaitInfo CompleteJsonExporter::CreateGaitInfo(const QuadrupedRobotSimulation &simulation) { GaitInfo gaitInfo; gaitInfo.GaitType = simulation.gait_type; gaitInfo.Period = simulation.T; gaitInfo.Frequency = simulation.f; gaitInfo.StepTime = simulation.step; gaitInfo.SupportTime = simulation.t_s; gaitInfo.SwingTime = simulation.t_w; gaitInfo.SupportRatio = simulation.support_ratio; gaitInfo.SwingRatio = simulation.swing_ratio; gaitInfo.TotalFrames = simulation.Trajectory_L.size(); gaitInfo.TotalTime = simulation.Trajectory_L.size() * simulation.step; return gaitInfo; } // 创建系统参数 SystemParameters CompleteJsonExporter::CreateSystemParameters(const QuadrupedRobotSimulation &simulation) { SystemParameters systemParams; // 基本参数 systemParams.L10 = simulation.L10; systemParams.L20 = simulation.L20; systemParams.L30 = simulation.L30; // 步态设计参数 systemParams.StepLength = simulation.s_l; systemParams.StepHeight = simulation.s_h; systemParams.X = simulation.X; systemParams.DeltaX = simulation.deltX; // 小腿连杆参数 systemParams.L21 = simulation.L21; systemParams.L22 = simulation.L22; systemParams.L23 = simulation.L23; systemParams.Beta1 = simulation.beta1; systemParams.BB2_BC_Angle = simulation.BB2_BC_angle; systemParams.C1_B_Length = simulation.C1_B_length; // 脚踝连杆参数 systemParams.CC1 = simulation.CC1; systemParams.L31 = simulation.L31; systemParams.C2C3_Length = simulation.C2C3_length; systemParams.Lead = simulation.lead1; // 脚部构型参数 systemParams.D1_L_Offset = simulation.D1_L_offset; systemParams.D2_L_Offset = simulation.D2_L_offset; systemParams.C4_D2_Offset = simulation.C4_D2_offset; // 电机参数 systemParams.ThighMotorReduction = simulation.thigh_motor_reduction; systemParams.ShankMotorReduction = simulation.shank_motor_reduction; systemParams.AnkleMotorReduction = simulation.ankle_motor_reduction; return systemParams; } // 创建轨迹数据 TrajectoryData CompleteJsonExporter::CreateTrajectoryData(const QuadrupedRobotSimulation &simulation) { int n_frames = simulation.Trajectory_L.size(); // 计算相位偏移帧数 int phase_LH = static_cast(simulation.timeLH * n_frames); int phase_RF = static_cast(simulation.timeRF * n_frames); int phase_RH = static_cast(simulation.timeRH * n_frames); TrajectoryData trajectoryData; trajectoryData.TotalFrames = n_frames; trajectoryData.StepTime = simulation.step; // 为每条腿创建轨迹数据 std::vector legCodes = {"LF", "LH", "RF", "RH"}; std::vector phaseShifts = {0, phase_LH, phase_RF, phase_RH}; for (size_t i = 0; i < legCodes.size(); i++) { std::string legCode = legCodes[i]; int phaseShift = phaseShifts[i]; bool isRightLeg = legCode[0] == 'R'; // 检查是否以'R'开头 LegTrajectory legTraj; legTraj.LegCode = legCode; legTraj.PhaseShift = phaseShift; legTraj.IsRightLeg = isRightLeg; for (int frame = 0; frame < n_frames; frame++) { int shiftedIdx = (frame + phaseShift) % n_frames; FrameData frameData; frameData.FrameNumber = frame; frameData.Time = frame * simulation.step; frameData.ShiftedFrameNumber = shiftedIdx; // 关键点坐标 frameData.A_Point = Point2D(simulation.A_point[0], simulation.A_point[1]); frameData.B_Point = ArrayToPoint(simulation.Trajectory_B[shiftedIdx]); frameData.C_Point = ArrayToPoint(simulation.Trajectory_C[shiftedIdx]); frameData.L_Point = ArrayToPoint(simulation.Trajectory_L[shiftedIdx]); frameData.D1_Point = ArrayToPoint(simulation.Trajectory_D1[shiftedIdx]); frameData.D2_Point = ArrayToPoint(simulation.Trajectory_D2[shiftedIdx]); frameData.C4_Point = ArrayToPoint(simulation.Trajectory_C4[shiftedIdx]); frameData.B1_Point = ArrayToPoint(simulation.Trajectory_B1[shiftedIdx]); frameData.B2_Point = ArrayToPoint(simulation.Trajectory_B2[shiftedIdx]); frameData.C1_Point = ArrayToPoint(simulation.Trajectory_C1[shiftedIdx]); frameData.C2_Point = ArrayToPoint(simulation.Trajectory_C2[shiftedIdx]); frameData.C3_Point = ArrayToPoint(simulation.Trajectory_C3[shiftedIdx]); // 角度数据 frameData.AB_Horizontal_Angle = simulation.AB_horizontal_angles[shiftedIdx]; frameData.AB_BC_Angle = simulation.AB_BC_angles[shiftedIdx]; frameData.BC_CL_Angle = simulation.BC_CL_angles[shiftedIdx]; frameData.AB1_AB_Angle = simulation.AB1_AB_angles[shiftedIdx]; // 距离数据 frameData.C3_C4_Distance = simulation.C3_C4_distances[shiftedIdx]; frameData.C2_C3_Distance = simulation.C2_C3_distances[shiftedIdx]; frameData.C2_C4_Distance = simulation.C2_C4_distances[shiftedIdx]; frameData.C2_C3_C4_Angle = simulation.C2_C3_C4_angles[shiftedIdx]; // 如果是右侧腿,调整大腿角度(镜像变换) if (isRightLeg) { frameData.AB_Horizontal_Angle = 540 - frameData.AB_Horizontal_Angle; // 确保角度在0-360度范围内 while (frameData.AB_Horizontal_Angle >= 360) { frameData.AB_Horizontal_Angle -= 360; } while (frameData.AB_Horizontal_Angle < 0) { frameData.AB_Horizontal_Angle += 360; } } legTraj.Frames.push_back(frameData); } trajectoryData.Legs[legCode] = legTraj; } return trajectoryData; } // 创建电机数据 MotorDataExport CompleteJsonExporter::CreateMotorData(const QuadrupedRobotSimulation &simulation) { MotorDataExport motorData; motorData.StepTime = simulation.step; // 获取四条腿的电机数据 std::map legsData = { {"LF", simulation.motor_data_LF}, {"LH", simulation.motor_data_LH}, {"RF", simulation.motor_data_RF}, {"RH", simulation.motor_data_RH}}; for (const auto &kvp : legsData) { std::string legCode = kvp.first; const MotorData &data = kvp.second; LegMotorData legMotorData; legMotorData.LegCode = legCode; int n_frames = data.frame_start_times.size(); for (int i = 0; i < n_frames; i++) { MotorFrameData frameData; frameData.FrameNumber = i; frameData.StartTime = data.frame_start_times[i]; frameData.EndTime = data.frame_end_times[i]; // 大腿电机数据 frameData.Thigh.Angle = data.AB_angles[i]; frameData.Thigh.AngleIncrement = data.AB_angle_increments[i]; frameData.Thigh.Speed = data.thigh_motor_speeds[i]; // 小腿电机数据 frameData.Shank.Angle = data.AB1_AB_angles[i]; frameData.Shank.AngleIncrement = data.AB1_AB_angle_increments[i]; frameData.Shank.Speed = data.shank_motor_speeds[i]; // 脚踝电机数据 frameData.Ankle.Angle = data.ankle_motor_angles[i]; frameData.Ankle.AngleIncrement = data.ankle_motor_angle_increments[i]; frameData.Ankle.Speed = data.ankle_motor_speeds[i]; // 丝杠相关数据 frameData.C3C4_Distance = data.C3C4_distances[i]; frameData.C3C4_DistanceIncrement = data.C3C4_distance_increments[i]; legMotorData.Frames.push_back(frameData); } motorData.Legs[legCode] = legMotorData; } return motorData; } // 创建约束检查数据 ConstraintData CompleteJsonExporter::CreateConstraintData(const QuadrupedRobotSimulation &simulation) { const double AB1_AB_min = 23.0; const double AB1_AB_max = 130.0; const double C3_C4_min = 125.0; const double C3_C4_max = 205.0; ConstraintData constraintData; // 计算AB1-AB角度的绝对值的最大最小值 double ab1_ab_min_actual = std::numeric_limits::max(); double ab1_ab_max_actual = std::numeric_limits::lowest(); bool ab1_ab_all_valid = true; for (double angle : simulation.AB1_AB_angles) { double abs_angle = std::abs(angle); ab1_ab_min_actual = std::min(ab1_ab_min_actual, abs_angle); ab1_ab_max_actual = std::max(ab1_ab_max_actual, abs_angle); if (abs_angle < AB1_AB_min || abs_angle > AB1_AB_max) { ab1_ab_all_valid = false; } } // 计算C3-C4距离的最大最小值 double c3c4_min_actual = std::numeric_limits::max(); double c3c4_max_actual = std::numeric_limits::lowest(); bool c3c4_all_valid = true; for (double distance : simulation.C3_C4_distances) { c3c4_min_actual = std::min(c3c4_min_actual, distance); c3c4_max_actual = std::max(c3c4_max_actual, distance); if (distance < C3_C4_min || distance > C3_C4_max) { c3c4_all_valid = false; } } // 计算CL距离的最大最小值 double cl_min_actual = std::numeric_limits::max(); double cl_max_actual = std::numeric_limits::lowest(); bool cl_all_valid = true; for (double distance : simulation.CL_distances) { cl_min_actual = std::min(cl_min_actual, distance); cl_max_actual = std::max(cl_max_actual, distance); if (std::abs(distance - simulation.L30) >= 1e-6) { cl_all_valid = false; } } // 计算点积的最大最小值 double dot_min_actual = std::numeric_limits::max(); double dot_max_actual = std::numeric_limits::lowest(); bool dot_all_valid = true; for (double dot_product : simulation.dot_products) { dot_min_actual = std::min(dot_min_actual, dot_product); dot_max_actual = std::max(dot_max_actual, dot_product); if (std::abs(dot_product) >= 1e-6) { dot_all_valid = false; } } // 设置约束数据 constraintData.AB1_AB_Constraint.MinAllowed = AB1_AB_min; constraintData.AB1_AB_Constraint.MaxAllowed = AB1_AB_max; constraintData.AB1_AB_Constraint.MinActual = ab1_ab_min_actual; constraintData.AB1_AB_Constraint.MaxActual = ab1_ab_max_actual; constraintData.AB1_AB_Constraint.IsValid = ab1_ab_all_valid; constraintData.AB1_AB_Constraint.CheckType = "绝对值检查"; constraintData.C3C4_Constraint.MinAllowed = C3_C4_min; constraintData.C3C4_Constraint.MaxAllowed = C3_C4_max; constraintData.C3C4_Constraint.MinActual = c3c4_min_actual; constraintData.C3C4_Constraint.MaxActual = c3c4_max_actual; constraintData.C3C4_Constraint.IsValid = c3c4_all_valid; constraintData.CL_Distance_Constraint.MinAllowed = simulation.L30; constraintData.CL_Distance_Constraint.MaxAllowed = simulation.L30; constraintData.CL_Distance_Constraint.MinActual = cl_min_actual; constraintData.CL_Distance_Constraint.MaxActual = cl_max_actual; constraintData.CL_Distance_Constraint.IsValid = cl_all_valid; constraintData.Perpendicularity_Constraint.MaxDotProduct = dot_max_actual; constraintData.Perpendicularity_Constraint.MinDotProduct = dot_min_actual; constraintData.Perpendicularity_Constraint.IsValid = dot_all_valid; // 收集约束违反信息 std::vector violations; // 检查AB1-AB约束违反 for (size_t i = 0; i < simulation.AB1_AB_angles.size(); i++) { double abs_angle = std::abs(simulation.AB1_AB_angles[i]); if (abs_angle < AB1_AB_min || abs_angle > AB1_AB_max) { ConstraintViolation violation; violation.ConstraintType = "AB1_AB_Angle"; violation.Frame = static_cast(i); violation.Time = i * simulation.step; violation.Value = simulation.AB1_AB_angles[i]; violation.AllowedRange = DoubleToString(AB1_AB_min) + "~" + DoubleToString(AB1_AB_max); violation.Severity = "Error"; violations.push_back(violation); } } // 检查C3-C4约束违反 for (size_t i = 0; i < simulation.C3_C4_distances.size(); i++) { double distance = simulation.C3_C4_distances[i]; if (distance < C3_C4_min || distance > C3_C4_max) { ConstraintViolation violation; violation.ConstraintType = "C3C4_Distance"; violation.Frame = static_cast(i); violation.Time = i * simulation.step; violation.Value = distance; violation.AllowedRange = DoubleToString(C3_C4_min) + "~" + DoubleToString(C3_C4_max); violation.Severity = "Error"; violations.push_back(violation); } } constraintData.ConstraintViolations = violations; return constraintData; } // 创建统计信息 StatisticsData CompleteJsonExporter::CreateStatistics(const QuadrupedRobotSimulation &simulation) { StatisticsData statistics; // 计算角度统计 double ab_horizontal_min = FindMin(simulation.AB_horizontal_angles); double ab_horizontal_max = FindMax(simulation.AB_horizontal_angles); double ab_bc_min = FindMin(simulation.AB_BC_angles); double ab_bc_max = FindMax(simulation.AB_BC_angles); double bc_cl_min = FindMin(simulation.BC_CL_angles); double bc_cl_max = FindMax(simulation.BC_CL_angles); double ab1_ab_min = FindMin(simulation.AB1_AB_angles); double ab1_ab_max = FindMax(simulation.AB1_AB_angles); // 角度统计 statistics.AngleStatistics.AB_Horizontal.Min = ab_horizontal_min; statistics.AngleStatistics.AB_Horizontal.Max = ab_horizontal_max; statistics.AngleStatistics.AB_Horizontal.Range = ab_horizontal_max - ab_horizontal_min; statistics.AngleStatistics.AB_BC.Min = ab_bc_min; statistics.AngleStatistics.AB_BC.Max = ab_bc_max; statistics.AngleStatistics.AB_BC.Range = ab_bc_max - ab_bc_min; statistics.AngleStatistics.BC_CL.Min = bc_cl_min; statistics.AngleStatistics.BC_CL.Max = bc_cl_max; statistics.AngleStatistics.BC_CL.Range = bc_cl_max - bc_cl_min; statistics.AngleStatistics.AB1_AB.Min = ab1_ab_min; statistics.AngleStatistics.AB1_AB.Max = ab1_ab_max; statistics.AngleStatistics.AB1_AB.Range = ab1_ab_max - ab1_ab_min; // 计算距离统计 double c3c4_min = FindMin(simulation.C3_C4_distances); double c3c4_max = FindMax(simulation.C3_C4_distances); double c2c3_min = FindMin(simulation.C2_C3_distances); double c2c3_max = FindMax(simulation.C2_C3_distances); double c2c4_min = FindMin(simulation.C2_C4_distances); double c2c4_max = FindMax(simulation.C2_C4_distances); // 距离统计 statistics.DistanceStatistics.C3_C4.Min = c3c4_min; statistics.DistanceStatistics.C3_C4.Max = c3c4_max; statistics.DistanceStatistics.C3_C4.Range = c3c4_max - c3c4_min; statistics.DistanceStatistics.C2_C3.Min = c2c3_min; statistics.DistanceStatistics.C2_C3.Max = c2c3_max; statistics.DistanceStatistics.C2_C3.Range = c2c3_max - c2c3_min; statistics.DistanceStatistics.C2_C4.Min = c2c4_min; statistics.DistanceStatistics.C2_C4.Max = c2c4_max; statistics.DistanceStatistics.C2_C4.Range = c2c4_max - c2c4_min; // 计算电机速度统计(使用左前腿的数据) double thigh_min = FindMin(simulation.motor_data_LF.thigh_motor_speeds); double thigh_max = FindMax(simulation.motor_data_LF.thigh_motor_speeds); double shank_min = FindMin(simulation.motor_data_LF.shank_motor_speeds); double shank_max = FindMax(simulation.motor_data_LF.shank_motor_speeds); double ankle_min = FindMin(simulation.motor_data_LF.ankle_motor_speeds); double ankle_max = FindMax(simulation.motor_data_LF.ankle_motor_speeds); // 电机速度统计 statistics.MotorSpeedStatistics.Thigh.Min = thigh_min; statistics.MotorSpeedStatistics.Thigh.Max = thigh_max; statistics.MotorSpeedStatistics.Thigh.Range = std::abs(thigh_max - thigh_min); statistics.MotorSpeedStatistics.Shank.Min = shank_min; statistics.MotorSpeedStatistics.Shank.Max = shank_max; statistics.MotorSpeedStatistics.Shank.Range = std::abs(shank_max - shank_min); statistics.MotorSpeedStatistics.Ankle.Min = ankle_min; statistics.MotorSpeedStatistics.Ankle.Max = ankle_max; statistics.MotorSpeedStatistics.Ankle.Range = std::abs(ankle_max - ankle_min); // 轨迹统计 statistics.TrajectoryStatistics.TotalFrames = simulation.Trajectory_L.size(); statistics.TrajectoryStatistics.TotalTime = simulation.Trajectory_L.size() * simulation.step; statistics.TrajectoryStatistics.SwingFrames = static_cast(std::round(simulation.t_w / simulation.step)); statistics.TrajectoryStatistics.SupportFrames = static_cast(std::round(simulation.t_s / simulation.step)); return statistics; } // 创建初始角度数据 InitialAnglesData CompleteJsonExporter::CreateInitialAngles(const QuadrupedRobotSimulation &simulation) { InitialAnglesData initialAngles; // 获取原始初始角度 std::map rawInitialAngles; rawInitialAngles["LF"] = RawInitialAngles{ .Thigh = simulation.AB_horizontal_angles[0], .Shank = simulation.AB1_AB_angles[0], .Ankle = simulation.C3_C4_distances[0]}; // 计算相位偏移帧数 int n_frames = simulation.Trajectory_L.size(); int phase_LH = static_cast(simulation.timeLH * n_frames); int phase_RF = static_cast(simulation.timeRF * n_frames); int phase_RH = static_cast(simulation.timeRH * n_frames); // 添加其他腿的初始角度 rawInitialAngles["LH"] = RawInitialAngles{ .Thigh = simulation.AB_horizontal_angles[phase_LH], .Shank = simulation.AB1_AB_angles[phase_LH], .Ankle = simulation.C3_C4_distances[phase_LH]}; rawInitialAngles["RF"] = RawInitialAngles{ .Thigh = simulation.AB_horizontal_angles[phase_RF], .Shank = simulation.AB1_AB_angles[phase_RF], .Ankle = simulation.C3_C4_distances[phase_RF]}; rawInitialAngles["RH"] = RawInitialAngles{ .Thigh = simulation.AB_horizontal_angles[phase_RH], .Shank = simulation.AB1_AB_angles[phase_RH], .Ankle = simulation.C3_C4_distances[phase_RH]}; // 创建每条腿的初始角度数据 std::vector legCodes = {"LF", "LH", "RF", "RH"}; std::vector motorDatas = { simulation.motor_data_LF, simulation.motor_data_LH, simulation.motor_data_RF, simulation.motor_data_RH}; for (size_t i = 0; i < legCodes.size(); i++) { std::string legCode = legCodes[i]; const MotorData &motorData = motorDatas[i]; const RawInitialAngles &rawAngles = rawInitialAngles[legCode]; LegInitialAngles legInitialAngles; legInitialAngles.LegCode = legCode; // 调试初始标定位置(原始值) legInitialAngles.RawInitialAngles = rawAngles; // 标定后位置(调整后的值) legInitialAngles.CalibratedAngles.Thigh = motorData.AB_angles[0]; legInitialAngles.CalibratedAngles.Shank = motorData.AB1_AB_angles[0]; legInitialAngles.CalibratedAngles.Ankle = motorData.ankle_motor_angles[0]; // 调整信息 legInitialAngles.Adjustments.ThighAdjustment = motorData.AB_angles[0] - rawAngles.Thigh; legInitialAngles.Adjustments.ShankAdjustment = motorData.AB1_AB_angles[0] - rawAngles.Shank; legInitialAngles.Adjustments.AnkleAdjustment = motorData.ankle_motor_angles[0] - rawAngles.Ankle; initialAngles.Legs[legCode] = legInitialAngles; } return initialAngles; } // 创建相位信息 PhaseInfo CompleteJsonExporter::CreatePhaseInfo(const QuadrupedRobotSimulation &simulation) { PhaseInfo phaseInfo; int n_frames = simulation.Trajectory_L.size(); phaseInfo.GaitType = simulation.gait_type; phaseInfo.TimeLF = simulation.timeLF; phaseInfo.TimeLH = simulation.timeLH; phaseInfo.TimeRF = simulation.timeRF; phaseInfo.TimeRH = simulation.timeRH; phaseInfo.PhaseLF = 0; phaseInfo.PhaseLH = static_cast(simulation.timeLH * n_frames); phaseInfo.PhaseRF = static_cast(simulation.timeRF * n_frames); phaseInfo.PhaseRH = static_cast(simulation.timeRH * n_frames); phaseInfo.SupportRatio = simulation.support_ratio; phaseInfo.SwingRatio = simulation.swing_ratio; phaseInfo.SupportTime = simulation.t_s; phaseInfo.SwingTime = simulation.t_w; return phaseInfo; } // 创建运动范围数据 MotionRangeData CompleteJsonExporter::CreateMotionRange(const QuadrupedRobotSimulation &simulation) { MotionRangeData motionRange; // 为每条腿计算运动范围 std::vector legCodes = {"LF", "LH", "RF", "RH"}; std::vector phaseShifts = { 0, static_cast(simulation.timeLH * simulation.Trajectory_L.size()), static_cast(simulation.timeRF * simulation.Trajectory_L.size()), static_cast(simulation.timeRH * simulation.Trajectory_L.size())}; for (size_t i = 0; i < legCodes.size(); i++) { std::string legCode = legCodes[i]; int phaseShift = phaseShifts[i]; // 计算L点运动范围 std::vector x_values, y_values; for (size_t idx = 0; idx < simulation.Trajectory_L.size(); idx++) { int shiftedIdx = (idx + phaseShift) % simulation.Trajectory_L.size(); const auto &point = simulation.Trajectory_L[shiftedIdx]; x_values.push_back(point[0]); y_values.push_back(point[1]); } double x_min = FindMin(x_values); double x_max = FindMax(x_values); double y_min = FindMin(y_values); double y_max = FindMax(y_values); LegMotionRange legMotionRange; legMotionRange.LegCode = legCode; legMotionRange.PhaseShift = phaseShift; legMotionRange.L_Point.X.Min = x_min; legMotionRange.L_Point.X.Max = x_max; legMotionRange.L_Point.X.Range = x_max - x_min; legMotionRange.L_Point.Y.Min = y_min; legMotionRange.L_Point.Y.Max = y_max; legMotionRange.L_Point.Y.Range = y_max - y_min; legMotionRange.L_Point.TotalRange = std::sqrt( std::pow(x_max - x_min, 2) + std::pow(y_max - y_min, 2)); motionRange.Legs[legCode] = legMotionRange; } return motionRange; } // 辅助函数:将数组转换为Point2D Point2D CompleteJsonExporter::ArrayToPoint(const std::vector &array) { if (array.size() >= 2) { return Point2D(array[0], array[1]); } return Point2D(0.0, 0.0); } // 模板函数:查找最小值 template T CompleteJsonExporter::FindMin(const std::vector &values) { if (values.empty()) { return T(); } T min_val = values[0]; for (const auto &val : values) { if (val < min_val) { min_val = val; } } return min_val; } // 模板函数:查找最大值 template T CompleteJsonExporter::FindMax(const std::vector &values) { if (values.empty()) { return T(); } T max_val = values[0]; for (const auto &val : values) { if (val > max_val) { max_val = val; } } return max_val; } // 模板函数:检查所有值是否满足条件 template bool CompleteJsonExporter::All(const std::vector &values, std::function predicate) { for (const auto &val : values) { if (!predicate(val)) { return false; } } return true; } // 辅助函数:将double转换为字符串 std::string CompleteJsonExporter::DoubleToString(double value, int precision) { std::ostringstream oss; oss << std::fixed << std::setprecision(precision) << value; return oss.str(); }