规范模块目录和第三方依赖结构

This commit is contained in:
zhangshun
2026-06-01 16:57:39 +08:00
parent e8e485b115
commit c2ce29d874
1758 changed files with 187 additions and 102 deletions

View File

@@ -0,0 +1,93 @@
#ifndef CRANK_ROCKING_BLOCK_MECHANISM_FORWARD_H
#define CRANK_ROCKING_BLOCK_MECHANISM_FORWARD_H
#include "FourBarMechanism/CrankSliderMechanism.h"
#include <vector>
#include <string>
#include <map>
#include <memory>
// 曲柄摇块机构(正解)
class CrankRockingBlockMechanism_Forward
{
private:
std::string name;
MechanismType type;
MechanismParameters parameters;
// 轨迹数据
std::vector<Vector2D> trajectoryB; // 滑块B的轨迹
std::vector<Vector2D> crankCirclePoints; // 曲柄端点A的轨迹
std::vector<Vector2D> rockerTrajectory; // 摇块轨迹
// 性能统计
int frameCount;
SimpleTimer timer;
// 配置参数
double thetaADelta;
double thetaAValueFactor;
int thetaAFlip;
public:
CrankRockingBlockMechanism_Forward();
// 基本属性
std::string getName() const;
MechanismType getType() const;
MechanismParameters getParameters() const;
void setParameters(const MechanismParameters &params);
// 设置连杆长度
void setLink(double OA, double AB, double OC);
void setOA(double length);
void setAB(double length);
void setOC(double distance);
// 配置方法
void setThetaADelta(double delta);
void setThetaAValueFactor(double factor);
void setThetaAFlip(int flip);
// 主要计算函数
MechanismState calculate(double crankAngleDeg);
// 获取输入范围
std::pair<double, double> getInputRange();
// 轨迹相关
std::vector<Vector2D> getTrajectoryPoints() const;
std::vector<Vector2D> getCrankCirclePoints() const;
std::vector<Vector2D> getRockerTrajectory() const;
void clearTrajectory();
// 参数验证
ValidationResult validateParameters();
// 状态信息
std::string getStatusText();
// 获取配置参数
double getThetaADelta() const;
double getThetaAValueFactor() const;
int getThetaAFlip() const;
double getOA() const;
double getAB() const;
double getOC() const;
private:
Vector2D calculatePointB(const Vector2D &A, const Vector2D &C, double AB);
void checkLimitPositions(MechanismState &state, const Vector2D &A,
const Vector2D &B, const Vector2D &C,
double OA, double AB, double OC);
double normalizeAngle(double angle);
std::pair<double, double> getValidCrankRange() const;
bool checkFullRotationCondition(double OA, double AB, double OC) const;
// 辅助方法
double degreesToRadians(double degrees) const;
double radiansToDegrees(double radians) const;
std::string formatDouble(double value, int precision = 3) const;
};
#endif // CRANK_ROCKING_BLOCK_MECHANISM_FORWARD_H

View File

@@ -0,0 +1,54 @@
#ifndef CRANK_ROCKING_BLOCK_MECHANISM_INVERSE_H
#define CRANK_ROCKING_BLOCK_MECHANISM_INVERSE_H
#include "FourBarMechanism/CrankSliderMechanism.h"
#include <vector>
#include <string>
#include <map>
#include <memory>
// 曲柄摇块机构(逆解)
class CrankRockingBlockMechanism_Inverse
{
private:
std::string name;
MechanismType type;
MechanismParameters parameters;
std::vector<Vector2D> trajectoryPoints;
public:
CrankRockingBlockMechanism_Inverse();
// 基本属性
std::string getName() const;
MechanismType getType() const;
MechanismParameters getParameters() const;
void setParameters(const MechanismParameters &params);
// 设置连杆长度
void setLink(double OA, double AB, double OC);
void setOA(double length);
void setAB(double length);
void setOC(double distance);
// 主要计算函数
MechanismState calculate(double acDistance);
// 获取输入范围
std::pair<double, double> getInputRange();
// 轨迹相关
std::vector<Vector2D> getTrajectoryPoints() const;
void clearTrajectory();
// 参数验证
ValidationResult validateParameters();
// 状态信息
std::string getStatusText();
private:
std::pair<double, double> getACRange() const;
};
#endif // CRANK_ROCKING_BLOCK_MECHANISM_INVERSE_H

View File

@@ -0,0 +1,201 @@
// mechanism_simulation.h
#ifndef MECHANISM_SIMULATION_H
#define MECHANISM_SIMULATION_H
#include <string>
#include <vector>
#include <map>
#include <cmath>
#include <chrono>
#include <memory>
#include "SharedGeometry/SharedGeometry.h" // 包含共享的几何类
// 定义常数
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
// // 前向声明
// class Vector2D;
// class Pose7;
// class PoseCalculator;
struct MechanismParameters;
struct MechanismState;
struct ValidationResult;
class SimpleTimer;
class CrankSliderMechanism;
// 机构类型枚举
enum class MechanismType
{
Unknown = 0,
CrankSlider = 1, // 曲柄滑块机构
FourBar = 2, // 四杆机构
CrankRockingBlock = 3, // 曲柄摇块机构(逆解)
CrankRockingBlock_Forward = 4, // 曲柄摇块机构(正解)
};
// 机制参数结构体
struct MechanismParameters
{
double CrankLength2;
double ConnectingRodLength2;
double SliderOffset2;
double InputValue;
double AngularVelocity;
// 四杆机构参数
double L1; // 曲柄
double L2; // 连杆
double L3; // 摇杆
double L4; // 机架
MechanismParameters();
};
// 机制状态结构体
struct MechanismState
{
std::map<std::string, Vector2D> Points;
std::map<std::string, Pose7> Poses;
std::map<std::string, double> Angles;
double InputValue;
std::string ErrorMessage;
std::string WarningMessage;
MechanismState();
bool hasError() const;
bool hasWarning() const;
};
// 验证结果结构体
struct ValidationResult
{
std::vector<std::string> Errors;
std::vector<std::string> Warnings;
bool isValid() const;
std::string getCombinedMessage() const;
};
// 姿态计算器
// class PoseCalculator
// {
// public:
// static Pose7 CalculatePoseAndQuaternion(const Vector2D &start, const Vector2D &end);
// };
// 简单的时间封装
class SimpleTimer
{
private:
std::chrono::steady_clock::time_point start;
public:
SimpleTimer();
void reset();
double elapsedSeconds() const;
};
// 曲柄滑块机构类
class CrankSliderMechanism
{
private:
std::string name;
MechanismParameters parameters;
MechanismType type;
// 轨迹数据
std::vector<Vector2D> trajectoryB;
std::vector<Vector2D> sliderTrajectory;
std::vector<Vector2D> crankCirclePoints;
// 性能统计
int frameCount;
SimpleTimer timer;
// 配置参数
std::string codeBody;
std::string l1ABModelName;
std::string l2BSModelName;
std::string l3SModelName;
double thetaADelta;
double thetaAValueFactor;
int thetaAFlip;
// 辅助方法
double degreesToRadians(double degrees) const;
double radiansToDegrees(double radians) const;
std::string formatDouble(double value, int precision = 3) const;
public:
CrankSliderMechanism();
// json calculate(const json &param)
// 基本属性访问
std::string getName() const;
MechanismType getType() const;
MechanismParameters getParameters() const;
void setName(const std::string &newName);
void setParameters(const MechanismParameters &params);
// 设置连杆长度
void setLink(double crankLength, double rodLength, double sliderOffset);
// 配置方法
void setThetaADelta(double delta);
void setThetaAValueFactor(double factor);
void setThetaAFlip(int flip);
void setL_AB(double length);
void setL_BS(double length);
void setS_OFS(double offset);
void setCodeBody(const std::string &code);
void setL1ABModelName(const std::string &modelName);
void setL2BSModelName(const std::string &modelName);
void setL3SModelName(const std::string &modelName);
// 主要计算函数
MechanismState calculate(double _angleDeg);
// 参数验证
ValidationResult validateParameters();
// 获取输入范围
std::pair<double, double> getInputRange();
// 获取轨迹点
std::vector<Vector2D> getTrajectoryPoints();
// 获取滑块轨迹
std::vector<Vector2D> getSliderTrajectory() const;
// 获取曲柄圆轨迹点
std::vector<Vector2D> getCrankCirclePoints() const;
// 清除轨迹
void clearTrajectory();
// 获取状态文本
std::string getStatusText();
// 获取配置参数
double getThetaADelta() const;
double getThetaAValueFactor() const;
int getThetaAFlip() const;
double getL_AB() const;
double getL_BS() const;
double getS_OFS() const;
std::string getCodeBody() const;
std::string getL1ABModelName() const;
std::string getL2BSModelName() const;
std::string getL3SModelName() const;
};
// 工厂函数
CrankSliderMechanism *createCrankSliderMechanism();
void deleteCrankSliderMechanism(CrankSliderMechanism *mechanism);
// 智能指针版本(可选)
using CrankSliderMechanismPtr = std::shared_ptr<CrankSliderMechanism>;
CrankSliderMechanismPtr createCrankSliderMechanismSmart();
#endif // MECHANISM_SIMULATION_H

View File

@@ -0,0 +1,94 @@
// FourBarMechanism.h
#ifndef FOUR_BAR_MECHANISM_H
#define FOUR_BAR_MECHANISM_H
#include "FourBarMechanism/CrankSliderMechanism.h"
#include <string>
#include <vector>
#include <map>
#include <cmath>
#include <chrono>
#include <memory>
#include "SharedGeometry/SharedGeometry.h"
// 前向声明
struct MechanismParameters;
struct MechanismState;
struct ValidationResult;
// 四杆机构类
class FourBarMechanism
{
private:
std::string name;
MechanismParameters parameters;
// 轨迹数据
std::vector<Vector2D> trajectoryB;
std::vector<Vector2D> trajectoryC;
std::vector<Vector2D> crankCirclePoints;
// 性能统计
int frameCount;
std::chrono::steady_clock::time_point startTime;
// 辅助方法
double degreesToRadians(double degrees) const;
double radiansToDegrees(double radians) const;
std::string formatDouble(double value, int precision = 2) const;
// 内部计算方法
bool calculatePointC(const Vector2D &A, const Vector2D &D, const Vector2D &B,
double l2, double l3, Vector2D &C) const;
bool checkGrashofCondition() const;
bool isShortestLinkCrank() const;
public:
FourBarMechanism();
// 基本属性访问
std::string getName() const;
MechanismType getType() const;
MechanismParameters getParameters() const;
void setName(const std::string &newName);
void setParameters(const MechanismParameters &params);
// 设置杆件长度
void setLink(double l1, double l2, double l3, double l4);
// 主要计算函数
MechanismState calculate(double angleDeg);
// 参数验证
ValidationResult validateParameters();
// 获取输入范围
std::pair<double, double> getInputRange();
// 获取轨迹点
std::vector<Vector2D> getTrajectoryPoints() const;
std::vector<Vector2D> getTrajectoryC() const;
std::vector<Vector2D> getCrankCirclePoints() const;
// 清除轨迹
void clearTrajectory();
// 获取状态文本
std::string getStatusText();
// 获取参数
double getL1() const;
double getL2() const;
double getL3() const;
double getL4() const;
};
// 工厂函数
FourBarMechanism *createFourBarMechanism();
void deleteFourBarMechanism(FourBarMechanism *mechanism);
// 智能指针版本
using FourBarMechanismPtr = std::shared_ptr<FourBarMechanism>;
FourBarMechanismPtr createFourBarMechanismSmart();
#endif // FOUR_BAR_MECHANISM_H

View File

@@ -0,0 +1,101 @@
// SliderCrankMechanism.h
#ifndef SLIDER_CRANK_MECHANISM_H
#define SLIDER_CRANK_MECHANISM_H
#include "FourBarMechanism/CrankSliderMechanism.h"
#include <string>
#include <vector>
#include <map>
#include <cmath>
#include "SharedGeometry/SharedGeometry.h"
// 解模式枚举
enum class SolutionMode
{
Auto = 0,
Solution1 = 1,
Solution2 = 2
};
// 机制参数结构体(扩展版本)
struct MechanismParametersExt
{
double CrankLength;
double ConnectingRodLength;
double SliderOffset;
double InputValue;
double AngularVelocity;
SolutionMode SolutionMode;
std::pair<double, double> CrankAngleRange1;
std::pair<double, double> CrankAngleRange2;
MechanismParametersExt();
};
// 解模式枚举
// 曲柄滑块机构逆解类
class SliderCrankMechanism
{
private:
std::string name;
MechanismParametersExt parameters;
// 轨迹数据
std::vector<Vector2D> trajectoryB;
std::vector<Vector2D> sliderTrajectory;
std::vector<Vector2D> trajectoryBAlt;
// 辅助方法
double degreesToRadians(double degrees) const;
double radiansToDegrees(double radians) const;
std::string formatDouble(double value, int precision = 3) const;
double clamp(double value, double min, double max) const;
// 计算滑块范围
std::pair<double, double> calculateSliderRange();
public:
SliderCrankMechanism();
// 基本属性访问
std::string getName() const;
MechanismType getType() const;
MechanismParametersExt getParameters() const;
void setName(const std::string &newName);
void setParameters(const MechanismParametersExt &params);
// 设置连杆长度
void setLink(double crankLength, double rodLength, double sliderOffset);
// 设置解模式
void setSolutionMode(SolutionMode mode);
// 主要计算函数(逆解)
MechanismState calculate(double sliderX);
// 参数验证
ValidationResult validateParameters();
// 获取输入范围
std::pair<double, double> getInputRange();
// 获取轨迹点
std::vector<Vector2D> getTrajectoryPoints();
std::vector<Vector2D> getSliderTrajectory() const;
std::vector<Vector2D> getAlternativeTrajectory() const;
// 清除轨迹
void clearTrajectory();
// 获取状态文本
std::string getStatusText();
};
// 工厂函数
SliderCrankMechanism *createSliderCrankMechanism();
void deleteSliderCrankMechanism(SliderCrankMechanism *mechanism);
// 智能指针版本
using SliderCrankMechanismPtr = std::shared_ptr<SliderCrankMechanism>;
SliderCrankMechanismPtr createSliderCrankMechanismSmart();
#endif // SLIDER_CRANK_MECHANISM_H

View File

@@ -0,0 +1,41 @@
#ifndef KINEMATICS_WEBAPI_H
#define KINEMATICS_WEBAPI_H
#include "utils.h"
#include "RobotManager.h"
#include "spc_core.h"
#include <string>
#include <atomic>
#include <functional>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
class KinematicsWebAPI
{
private:
std::atomic<bool> running_{false};
int m_port;
std::function<void(const std::string &)> onLog;
public:
KinematicsWebAPI();
// 日志函数
void log(const std::string &message);
// 获取当前时间戳
std::string getCurrentTimestamp();
// 处理API请求的主函数
std::string func(std::string sanitized_body);
// 初始化函数
std::string init_func();
// 运行状态检查
bool is_running() const;
};
#endif // KINEMATICS_WEBAPI_H

View File

@@ -0,0 +1,706 @@
// BaseClass.h - 完整修复版
#ifndef BASE_CLASS_H
#define BASE_CLASS_H
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <cmath>
#include <algorithm>
#include <stdexcept>
#include <iostream>
#include <mutex>
#include <optional>
#include <set>
#include <functional>
#include <sstream>
#include <iomanip>
#include <nlohmann/json.hpp>
#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<double> Actual;
std::optional<double> Expected;
std::optional<double> Tolerance;
std::map<std::string, double> AdditionalData;
CheckResultItem() : Condition(""), Passed(false)
{
AdditionalData = std::map<std::string, double>();
}
CheckResultItem(std::string cond, bool passed = false)
: Condition(std::move(cond)), Passed(passed)
{
AdditionalData = std::map<std::string, double>();
}
};
// 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 <typename T>
struct adl_serializer<std::optional<T>>;
// 为 std::vector<std::map<std::string, std::string>> 的序列化声明
template <>
struct adl_serializer<std::vector<std::map<std::string, std::string>>>;
// 为 Vector2D 的序列化声明
template <>
struct adl_serializer<Vector2D>;
// 为 ModelID 的序列化声明
template <>
struct adl_serializer<ModelID>;
}
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<LinkModelIDInfo> LF;
std::vector<LinkModelIDInfo> LH;
std::vector<LinkModelIDInfo> RF;
std::vector<LinkModelIDInfo> 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<FrameData> Frames;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(LegTrajectory, LegCode, PhaseShift, IsRightLeg, Frames)
};
struct TrajectoryData
{
int TotalFrames = 0;
double StepTime = 0.0;
std::map<std::string, LegTrajectory> 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<MotorFrameData> Frames;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(LegMotorData, LegCode, Frames)
};
struct MotorDataExport
{
double StepTime = 0.0;
std::map<std::string, LegMotorData> 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<ConstraintViolation> 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<std::string, LegInitialAngles> 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<std::string, LegMotionRange> Legs;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(MotionRangeData, Legs)
};
struct SplitModelID
{
std::vector<std::map<std::string, std::vector<std::string>>> LF;
std::vector<std::map<std::string, std::vector<std::string>>> LH;
std::vector<std::map<std::string, std::vector<std::string>>> RF;
std::vector<std::map<std::string, std::vector<std::string>>> RH;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(SplitModelID, LF, LH, RF, RH)
};
// 支撑点检查结果类
struct SupportCheckResult
{
bool IsSupport = false;
std::map<std::string, CheckResultItem> Checks;
std::vector<std::string> Reasons;
std::vector<std::string> FailedChecks;
SupportCheckResult();
NLOHMANN_DEFINE_TYPE_INTRUSIVE(SupportCheckResult, IsSupport, Checks, Reasons, FailedChecks)
};
class MotorData
{
public:
std::vector<double> frame_start_times;
std::vector<double> frame_end_times;
std::vector<double> AB_angles;
std::vector<double> AB_angle_increments;
std::vector<double> thigh_motor_speeds;
std::vector<double> AB1_AB_angles;
std::vector<double> AB1_AB_angle_increments;
std::vector<double> shank_motor_speeds;
std::vector<double> C3C4_distances;
std::vector<double> C3C4_distance_increments;
std::vector<double> ankle_motor_angles;
std::vector<double> ankle_motor_angle_increments;
std::vector<double> 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<std::string, std::vector<double>> Points;
bool Valid = false;
std::vector<std::string> 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<std::string, std::vector<double>> &pointsDict);
private:
static std::vector<std::map<std::string, std::vector<std::string>>>
SplitLegDictionaryDataToArrays(const std::vector<std::map<std::string, std::string>> &legData,
const std::set<std::string> &validKeys);
static std::map<std::string, std::vector<std::string>>
SplitDictionaryToArrays(const std::map<std::string, std::string> &dict,
const std::set<std::string> &validKeys);
static std::vector<std::string> SplitKey(const std::string &compositeKey,
const std::set<std::string> &validKeys);
};
class QuadrupedRobotConfiguration
{
public:
// 基本几何参数
std::vector<double> 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<std::string> Errors;
std::vector<std::string> 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<std::string, std::vector<std::map<std::string, std::string>>> GetModelID() const;
LegParameters GetParam() const;
RobotBody GetRobotBody() const;
std::map<std::string, LegParam> GetParamDictionary() const;
// 在 RobotGaitDataManager 类声明中修改
std::map<std::string, std::vector<double>> Get_old_initial_points_dictLF() const;
std::map<std::string, std::vector<double>> Get_old_initial_points_dictLH() const;
void Set_old_initial_points_dictLF(const std::map<std::string, std::vector<double>> &L_point);
void Set_old_initial_points_dictLH(const std::map<std::string, std::vector<double>> &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<std::string, std::map<std::string, std::vector<std::string>>>
ToSimpleDictionary(const SplitModelID &splitModelID);
private:
static std::map<std::string, std::vector<std::string>>
MergeLegData(const std::vector<std::map<std::string, std::vector<std::string>>> &legData);
};
// 实用函数
Point2D ArrayToPoint(const std::vector<double> &array);
#endif // BASE_CLASS_H

View File

@@ -0,0 +1,51 @@
// CompleteJsonExporter.h
#ifndef COMPLETE_JSON_EXPORTER_H
#define COMPLETE_JSON_EXPORTER_H
#include "QuadrupedRobotSimulation/BaseClass.h"
#include "QuadrupedRobotSimulation/KinematicsSimulation.h"
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <map>
#include <sstream>
#include <iomanip>
class CompleteJsonExporter
{
public:
// 主导出函数
static std::string ExportCompleteDataJsonString(const QuadrupedRobotSimulation &simulation);
// 各个组件的创建函数
static GaitInfo CreateGaitInfo(const QuadrupedRobotSimulation &simulation);
static SystemParameters CreateSystemParameters(const QuadrupedRobotSimulation &simulation);
static TrajectoryData CreateTrajectoryData(const QuadrupedRobotSimulation &simulation);
static MotorDataExport CreateMotorData(const QuadrupedRobotSimulation &simulation);
static ConstraintData CreateConstraintData(const QuadrupedRobotSimulation &simulation);
static StatisticsData CreateStatistics(const QuadrupedRobotSimulation &simulation);
static InitialAnglesData CreateInitialAngles(const QuadrupedRobotSimulation &simulation);
static PhaseInfo CreatePhaseInfo(const QuadrupedRobotSimulation &simulation);
static MotionRangeData CreateMotionRange(const QuadrupedRobotSimulation &simulation);
private:
// 辅助函数
static Point2D ArrayToPoint(const std::vector<double> &array);
// 查找最小值和最大值的模板函数
template <typename T>
static T FindMin(const std::vector<T> &values);
template <typename T>
static T FindMax(const std::vector<T> &values);
// 检查所有值是否满足条件的模板函数
template <typename T>
static bool All(const std::vector<T> &values, std::function<bool(const T &)> predicate);
// 转换函数
static std::string DoubleToString(double value, int precision = 6);
};
#endif // COMPLETE_JSON_EXPORTER_H

View File

@@ -0,0 +1,144 @@
// KinematicsHelper.h
#ifndef KINEMATICS_HELPER_H
#define KINEMATICS_HELPER_H
#include "QuadrupedRobotSimulation/BaseClass.h"
#include "QuadrupedRobotSimulation/KinematicsSimulation.h"
#include "QuadrupedRobotSimulation/KinematicsReverse.h"
#include "QuadrupedRobotSimulation/CompleteJsonExporter.h"
#include <string>
#include <memory>
#include <chrono>
#include <thread>
/**
* @brief 工具类:提供便捷的正逆解计算方法
*/
class KinematicsHelper
{
public:
/**
* @brief 模拟机器人完整运动
*/
static void SimRobot();
/**
* @brief 输入三个电机的值,返回各个连杆的姿态
* @param jsonInput JSON输入字符串可选
* @return JSON格式的所有点计算结果
*/
static json QuadrupedRobot_CalculateAllPointsFromMotorAngles(const std::string &jsonInput = "");
/**
* @brief 执行正向运动学计算:计算所有轨迹
* @param jsonInput JSON输入字符串可选
* @return JSON格式的正向运动学计算结果
*/
static json QuadrupedRobot_PerformForwardKinematics(const std::string &jsonInput = "");
/**
* @brief 单腿运动计算
* @param thigh_angle_deg 大腿电机角度(度)
* @param shank_angle_deg 小腿电机角度(度)
* @param ankle_angle_deg 脚踝电机角度(度)
* @param leg_type 腿类型:"LF"、"LH"、"RF"、"RH"
* @param json JSON输入字符串可选
* @return JSON格式的单腿计算结果
*/
static std::string QuadrupedRobot_CalculateAllPointsOnlyOneLegFromMotorAngles(
double thigh_angle_deg, double shank_angle_deg, double ankle_angle_deg,
const std::string &leg_type = "LF", const std::string &json = "");
/**
* @brief 获得RobotGaitDataManager机器人管理句柄
* @param json JSON输入字符串可选
* @return 共享指针指向RobotGaitDataManager对象
*/
static std::shared_ptr<RobotGaitDataManager> RobotGaitDataManagerFromJson(const std::string &jsonInput = "", const std::string &robotID = "0");
/**
* @brief 从JSON字符串创建配置对象
* @param jsonInput JSON输入字符串可选
* @return QuadrupedRobotConfiguration对象
*/
static QuadrupedRobotConfiguration CreateConfigFromJson(const std::string &jsonInput = "");
/**
* @brief 根据机器人的机构数据和机构类型,计算机器人四个腿的所有轨迹数据
* @param config 机器人配置
* @return JSON格式的正向运动学计算结果
*/
static std::string PerformForwardKinematics(const QuadrupedRobotConfiguration &config);
/**
* @brief 导出完整数据为JSON字符串
* @param config 机器人配置
* @return JSON格式的完整导出数据
*/
static std::string ExportCompleteData(const QuadrupedRobotConfiguration &config);
/**
* @brief 批量逆向计算
* @param motor_data 电机数据映射
* @param leg_type 腿类型
* @param max_frames 最大帧数(可选)
* @param jsonInput 配置JSON可选
* @return 逆向计算结果向量
*/
static std::vector<ReverseCalculationResult> BatchReverseCalculation(
const std::map<std::string, std::vector<double>> &motor_data,
const std::string &leg_type = "LF",
std::optional<int> max_frames = std::nullopt,
const std::string &jsonInput = "");
/**
* @brief 计算并验证支撑点
* @param pointsDict 点字典
* @param groundHeight 地面高度
* @param tolerance 容差
* @param json 配置JSON可选
* @return 支撑点检查结果
*/
static SupportCheckResult CheckSupportPoint(
const std::map<std::string, std::vector<double>> &pointsDict,
double groundHeight = 0.0,
double tolerance = 1.0,
const std::string &json = "");
/**
* @brief 生成线框播放数据
* @param frameRate 帧率
* @param modelCode 模型代码
* @param positions 位置数组
* @param quaternions 四元数数组
* @return P_OPERATION对象
*/
static P_OPERATION MakeOperation(
int frameRate,
const std::string &modelCode,
const std::vector<std::vector<double>> &positions,
const std::vector<std::vector<double>> &quaternions);
/**
* @brief 等待函数(用于模拟延迟)
* @param milliseconds 等待的毫秒数
*/
static void Wait(int milliseconds)
{
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
}
private:
/**
* @brief 从JSON创建默认配置
* @return 默认机器人步态请求
*/
static RobotGaitRequest CreateDefaultRequest();
/**
* @brief 加载并验证JSON数据
* @param json JSON字符串
* @return 验证后的RobotGaitRequest对象
*/
static RobotGaitRequest LoadAndValidateJson(const std::string &jsonInput);
};
#endif // KINEMATICS_HELPER_H

View File

@@ -0,0 +1,219 @@
// KinematicsReverse.h
#ifndef KINEMATICS_REVERSE_H
#define KINEMATICS_REVERSE_H
#include <vector>
#include <string>
#include <map>
#include <cmath>
#include <memory>
#include <algorithm>
#include <functional>
#include <optional>
#include "utils.h"
#include "QuadrupedRobotSimulation/BaseClass.h"
#include "QuadrupedRobotSimulation/OPERATION.h"
#include "SharedGeometry/SharedGeometry.h"
class ReverseKinematicsCalculator
{
private:
// 统一配置
QuadrupedRobotConfiguration _config;
std::shared_ptr<RobotGaitDataManager> _manager;
// 基本输入参数
double adjusted_shank_angles_factory;
std::vector<double> 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 D1_L_offset;
double D2_L_offset;
double C4_D2_offset;
// 初始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_distance;
// 数学常量
static constexpr double PI = 3.14159265358979323846;
static constexpr double DegToRad = PI / 180.0;
static constexpr double RadToDeg = 180.0 / PI;
// 静态变量模拟C#的静态字段)
std::map<std::string, std::vector<double>> old_initial_points_dictLF;
std::map<std::string, std::vector<double>> old_initial_points_dictLH;
static bool IsSupporLF;
static bool IsSupporLH;
static double BodyPosition_x;
static double BodyPosition_y;
static double BodyPosition_z;
static double BodyPosition_qx;
static double BodyPosition_qy;
static double BodyPosition_qz;
static double BodyPosition_qw;
static const std::string BodyCode;
public:
// 构造函数
ReverseKinematicsCalculator(std::shared_ptr<RobotGaitDataManager> manager = nullptr);
void debugPrintParamDict(const std::map<std::string, LegParam> &paramDict) const;
void debugPrintLegCalculation(const std::string &legName, const LegParam &legParam,
const std::map<std::string, std::vector<double>> &points_dict,
const ModelID &modelID) const;
void debugPrintFinalJson(const std::vector<C_ObjStates> &objStates) const;
// 主计算函数
std::string CalculateAllPointsFromMotorAnglesJsonStr();
std::string CalculateAllPointsOnlyOneLegFromMotorAnglesJsonStr(
double thigh_angle_deg, double shank_angle_deg, double ankle_angle_deg,
const std::string &leg_type = "LF", bool IsReset = false);
// 逆向计算主函数
std::map<std::string, std::vector<double>> CalculateAllPointsFromMotorAnglesReverse(
double thigh_angle_deg, double shank_angle_deg, double ankle_angle_deg,
const std::string &leg_type = "LF", bool IsReset = false);
// 判断是否为支撑点
bool IsSupportPoint(const std::map<std::string, std::vector<double>> &pointsDict,
double groundHeight = 0.0, double tolerance = 1.0);
// 验证计算结果
std::pair<bool, std::vector<std::string>> ValidateReverseCalculation(
const std::map<std::string, std::vector<double>> &points_dict,
double thigh_angle, double shank_angle, double ankle_angle);
// 批量计算
std::vector<ReverseCalculationResult> BatchReverseCalculation(
const std::map<std::string, std::vector<double>> &motor_data,
const std::string &leg_type = "LF", std::optional<int> max_frames = std::nullopt);
// 获取配置
QuadrupedRobotConfiguration GetConfig() const { return _config; }
// 更新配置
void UpdateConfiguration(const QuadrupedRobotConfiguration &newConfig);
private:
// 从配置加载参数
void LoadParametersFromConfig();
// 计算派生参数
void CalculateDerivedParameters();
// 验证配置
void ValidateConfiguration();
// 计算点C四杆机构解析解
std::optional<Vector2D> CalculatePointC(const Vector2D &A, const Vector2D &D,
const Vector2D &B, double l2, double l3);
// 选择C点确保C和B在AD同侧
Vector2D SelectCPointByADSide(const Vector2D &A, const Vector2D &D,
const Vector2D &B, const Vector2D &C1, const Vector2D &C2);
// 根据大腿角度计算B点
std::vector<double> CalculateBFromThighAngleReverse(double thigh_angle_deg);
// 根据小腿角度计算B1点
std::vector<double> CalculateB1FromShankAngleReverse(const std::vector<double> &B_p,
double shank_angle_deg);
// 根据四杆机构计算B2点
std::pair<std::vector<double>, std::string> CalculateB2FromFourbarReverse(
const std::vector<double> &A_p, const std::vector<double> &B_p,
const std::vector<double> &B1_p, double L22, double L23);
// 根据B和B2计算C点
std::vector<double> CalculateCFromBAndB2Reverse(const std::vector<double> &B1,
const std::vector<double> &B2,
double L, double theta_deg);
// 反向计算C1点
std::vector<double> CalculateC1PointReverse(const std::vector<double> &B_p,
const std::vector<double> &C_p);
// 根据C1点计算C2点
std::vector<double> CalculateC2PointFromC1Reverse(const std::vector<double> &C1_p,
const std::vector<double> &B_p,
const std::vector<double> &C_point);
// 根据脚踝角度计算C3C4距离
double CalculateC3C4DistanceFromAnkleAngleReverse(double ankle_angle_deg,
const std::string &leg_type = "LF");
// 已知三角形三边和两个顶点,求第三个顶点
std::vector<double> FindThirdVertex(const std::vector<double> &C,
const std::vector<double> &C2,
double a, double b, double c);
// 根据C和C2点计算C4点
std::vector<double> CalculateC4PointFromCAndC2Reverse(const std::vector<double> &C_p,
const std::vector<double> &C2_p,
double ankle_angle_deg,
const std::string &leg_type = "LF");
// 根据C和C4点计算L点
std::vector<double> CalculateLPointsFromCAndC4Reverse(const std::vector<double> &C,
const std::vector<double> &C4);
// 求直角三角形直角顶点
std::vector<double> FindRightAngleThirdVertex(const std::vector<double> &C,
const std::vector<double> &L,
double a, double b);
// 根据C和L点计算D1点
std::vector<double> CalculateD1PointsFromCAndLReverse(const std::vector<double> &C_p,
const std::vector<double> &L_p);
// 求直角三角形直角顶点D2
std::vector<double> FindRightAngleVertexD2(const std::vector<double> &L,
const std::vector<double> &C4,
double a, double b);
// 根据L和C4点计算D2点
std::vector<double> CalculateD2PointsFromCAndLReverse(const std::vector<double> &L,
const std::vector<double> &C4);
// 求直角三角形直角顶点C3
std::vector<double> FindRightAngleVertex(const std::vector<double> &C2,
const std::vector<double> &C4, double L);
// 根据C2和C4点计算C3点
std::vector<double> CalculateC3PointFromC2AndC4Reverse(const std::vector<double> &C2_point,
const std::vector<double> &C4_point);
// 从字典安全获取点坐标
std::vector<double> GetPointSafe(const std::map<std::string, std::vector<double>> &pointsDict,
const std::string &key);
// 获取模型ID
// 新版本:
// std::string GetValueModelID(
// const ModelID &modelID, // 改为 ModelID 类型
// const std::string &legName, const std::string &key);
const LegModelIDs &GetLegModelIDs(const ModelID &modelID, const std::string &legName);
// 辅助函数:旋转向量
std::vector<double> RotateVector(double angle, const std::vector<double> &vector);
};
#endif // KINEMATICS_REVERSE_H

View File

@@ -0,0 +1,201 @@
// KinematicsSimulation.h
#ifndef KINEMATICS_SIMULATION_H
#define KINEMATICS_SIMULATION_H
#include "QuadrupedRobotSimulation/BaseClass.h"
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#include <stdexcept>
#include <iostream>
#include <functional>
class QuadrupedRobotSimulation
{
private:
// 常量
static constexpr double PI = 3.14159265358979323846;
public:
// 使用统一配置
QuadrupedRobotConfiguration _config;
// ============== 从配置继承的字段 ==============
// 主几何参数
double A_x; // 固定点A的X坐标
double A_y; // 固定点A的Y坐标
std::vector<double> A_point; // A点坐标数组
double L10; // AB连杆长度大腿长度
double L20; // BC连杆长度小腿上段长度
double L30; // C点到L点脚端点的垂直距离
double s_l; // 步长
double s_h; // 步高
double X; // 下铰链点与大腿铰链点投影水平距离
// 小腿连杆机构参数
double L22; // B1到B2的连杆长度
double L23; // B到B2的连杆长度
double beta1; // B-B2与BC的夹角
double CC1; // C到C1点的距离
// 脚踝连杆机构参数
double L31; // C1到C2的连杆长度
double C2C3_length; // C2到C3的连杆长度固定长度
double lead1; // 丝杠导程mm
// 脚部构型参数
double D1_L_offset; // D1点与L点的水平偏移左侧
double D2_L_offset; // D2点与L点的水平偏移右侧
double C4_D2_offset; // C4点与D2点的垂直距离
// 电机参数
double thigh_motor_reduction; // 大腿电机减速比
double shank_motor_reduction; // 小腿电机减速比
double ankle_motor_reduction; // 脚踝电机减速比
// 逆向运动学参数
double adjusted_shank_angles_factory; // 小腿角度调整参数
// ============== 计算得到的中间变量 ==============
double BB2_BC_angle; // B-B2与BC的夹角弧度
double C1_B_length; // C1到B点的距离
// ============== 步态相位时间 ==============
double timeLF = 0; // 左前腿相位时间
double timeLH = 0; // 左后腿相位时间
double timeRF = 0; // 右前腿相位时间
double timeRH = 0; // 右后腿相位时间
// ============== 轨迹数据列表 ==============
std::vector<std::vector<double>> Trajectory_C; // C点轨迹
std::vector<std::vector<double>> Trajectory_B; // B点轨迹
std::vector<std::vector<double>> Trajectory_D1; // D1点轨迹
std::vector<std::vector<double>> Trajectory_D2; // D2点轨迹
std::vector<std::vector<double>> Trajectory_C4; // C4点轨迹
std::vector<std::vector<double>> Trajectory_B1; // B1点轨迹
std::vector<std::vector<double>> Trajectory_B2; // B2点轨迹
std::vector<std::vector<double>> Trajectory_C1; // C1点轨迹
std::vector<std::vector<double>> Trajectory_C2; // C2点轨迹
std::vector<std::vector<double>> Trajectory_C3; // C3点轨迹
// ============== 角度和距离数据列表 ==============
std::vector<double> AB_horizontal_angles; // AB连杆与水平夹角
std::vector<double> AB_BC_angles; // AB与BC夹角
std::vector<double> BC_CL_angles; // BC与CL夹角
std::vector<double> AB1_AB_angles; // AB1与AB夹角θ1
std::vector<double> BCL_angles; // B-C-L夹角
std::vector<double> C3_C4_distances; // C3-C4距离mm
std::vector<double> C2_C3_distances; // C2-C3距离mm
std::vector<double> C2_C4_distances; // C2-C4距离mm
std::vector<double> C2_C3_C4_angles; // ∠C2C3C4角度
std::vector<double> CL_distances; // C-L距离mm
std::vector<double> dot_products; // 点积验证数据
// ============== 电机数据对象 ==============
MotorData motor_data_LF; // 左前腿电机数据
MotorData motor_data_LH; // 左后腿电机数据
MotorData motor_data_RF; // 右前腿电机数据
MotorData motor_data_RH; // 右后腿电机数据
// 原始电机数据(调整前)
MotorData motor_data_LF_raw;
MotorData motor_data_LH_raw;
MotorData motor_data_RF_raw;
MotorData motor_data_RH_raw;
std::string gait_type; // 步态类型:"walk"、"trot"、"standup"
// 步态控制参数
double T; // 步态周期时间(秒)
double f; // 控制频率Hz
double step; // 时间步长(秒)
double t_s; // 支撑阶段时间
double t_w; // 摆动阶段时间
double support_ratio = 0.5; // 支撑阶段比例
double swing_ratio = 0.5; // 摆动阶段比例
double deltX; // x方向偏移距离
double L21; // A到B1的连杆长度
std::vector<std::vector<double>> Trajectory_L; // L点脚端点轨迹
// 构造函数
QuadrupedRobotSimulation(const QuadrupedRobotConfiguration &config = QuadrupedRobotConfiguration());
QuadrupedRobotSimulation();
// 获取配置对象
const QuadrupedRobotConfiguration &GetConfig() const { return _config; }
// 主计算函数
std::string CalculateAllTrajectories_JsonStr();
void CalculateAllTrajectories();
std::string CalculateAllTrajectoriesJsonString();
// 设置步态参数
void SetGaitParameters();
private:
// 初始化方法
void LoadParametersFromConfig();
void InitializeParameters();
// 轨迹计算方法
void CalculateTrajectoryL_V2();
void CalculateTrajectoryC();
void CalculateTrajectoryB();
void CalculateAllPoints();
void CalculateAllAngles();
void CheckConstraints();
void CalculateMotorData();
// 辅助计算方法
std::vector<std::vector<double>> CalculateSupportPoints(const std::vector<double> &L_point);
std::vector<double> Calculate_B_Position(const std::vector<double> &A, const std::vector<double> &C,
double AB_length, double BC_length);
double Calculate_BCL_Angle(const std::vector<double> &B_point, const std::vector<double> &C_point,
const std::vector<double> &L_point);
std::vector<double> CalculateSwingPointWithConstraints(const std::vector<double> &L_point,
double target_BCL_angle,
const std::vector<double> &prev_C,
double &prev_angle);
void RecalculateAllPoints();
// 辅助点计算方法
std::vector<double> Calculate_B2_Position(const std::vector<double> &B, const std::vector<double> &C,
double B_B2_length, double BB2_BC_angle);
std::vector<double> Calculate_B1_Position(const std::vector<double> &A, const std::vector<double> &B2,
double A_B1_length, double B1B2_length);
std::vector<double> Calculate_C1_Position(const std::vector<double> &B, const std::vector<double> &C,
double C1_B_length);
std::vector<double> Calculate_C2_Position(const std::vector<double> &C1, const std::vector<double> &B,
const std::vector<double> &C, double C1C2_length);
std::vector<double> Calculate_C3_Position(const std::vector<double> &C2, const std::vector<double> &C4,
double C2C3_length);
double Calculate_C2C3C4_Angle(const std::vector<double> &C2, const std::vector<double> &C3,
const std::vector<double> &C4);
double Distance(const std::vector<double> &p1, const std::vector<double> &p2);
// 电机数据计算方法
MotorData CalculateIncrementsAndVelocities();
MotorData CalculateOtherLegData(const MotorData &baseData, int shift, bool isRightLeg);
MotorData AdjustMotorAngles(const MotorData &motorData, const std::vector<double> &frame_start_times, double step);
MotorData ReverseShankData(const MotorData &motorData, double step, double shank_motor_reduction);
MotorData AdjustAnkleAngles(const MotorData &data);
// 数学辅助函数
double NonlinearAngleFunction(double t, double start_angle_deg, double end_angle_deg,
const std::string &function_type, double curvature);
std::vector<double> Linspace(double start, double end, int num);
std::vector<std::vector<double>> Zeros(int rows, int cols);
std::vector<std::vector<double>> Flip(const std::vector<std::vector<double>> &array);
std::vector<std::vector<double>> VStack(const std::vector<std::vector<double>> &array1,
const std::vector<std::vector<double>> &array2);
int PythonRoundExact(double value);
// 数组操作函数
std::vector<double> ShiftArray(const std::vector<double> &array, int shiftFrames);
};
#endif // KINEMATICS_SIMULATION_H

View File

@@ -0,0 +1,347 @@
// OPERATION.h
#ifndef OPERATION_H
#define OPERATION_H
#include <string>
#include <vector>
#include <cmath>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
// 毫米转米函数
inline double MMToM(double MM)
{
return std::round(MM / 1000.0 * 100000.0) / 100000.0; // 保留5位小数
}
// 帧内容类
class C_ObjStates
{
public:
std::string i = ""; // 模型代码
std::string tx = ""; // tx
std::string ty = ""; // ty
std::string tz = ""; // tz
std::string qx = ""; // qx
std::string qy = ""; // qy
std::string qz = ""; // qz
std::string qw = ""; // qw
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(C_ObjStates, i, tx, ty, tz, qx, qy, qz, qw)
// 工艺类
class C_Craft
{
public:
std::string CraftCode;
std::string CraftValue;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(C_Craft, CraftCode, CraftValue)
// 帧信号类
class C_Signalwrite
{
public:
std::string TagID;
std::string TagValue;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(C_Signalwrite, TagID, TagValue)
// 可见性类
class C_Visible
{
public:
std::string ModelCode;
std::string Visible;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(C_Visible, ModelCode, Visible)
// 旋转类
class C_Rotation
{
public:
std::string ModelCode;
std::string Axis;
int Rate = 0;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(C_Rotation, ModelCode, Axis, Rate)
// 等待类
class C_Wait
{
public:
std::string WaitStr;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(C_Wait, WaitStr)
// 附加类
class C_Attach
{
public:
std::string AttachToModelCode = "";
std::string AttachToModelName = "";
bool IsTwoWay = false;
bool IsAttach = false;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(C_Attach, AttachToModelCode, AttachToModelName, IsTwoWay, IsAttach)
// 帧类
class C_Frames
{
public:
std::string time = "0.01"; // 帧时间
std::vector<C_ObjStates> objStates;
std::vector<C_Craft> crafts;
std::vector<C_Signalwrite> signalwrites;
std::vector<C_Visible> visibles;
std::vector<C_Rotation> rotations;
std::vector<C_Wait> waits;
std::vector<C_Attach> attachs;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(C_Frames, time, objStates, crafts, signalwrites,
visibles, rotations, waits, attachs)
// 操作类(帧集合)
class C_OPERATION
{
public:
std::vector<C_Frames> frames;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(C_OPERATION, frames)
// 项目操作类
class P_OPERATION
{
public:
C_OPERATION OPERATION;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(P_OPERATION, OPERATION)
// 功能类
class P_OPERATION_Func
{
public:
/**
* 生成线框播放数据
* @param PP_FrameValue 帧率值
* @param modelCode 模型代码
* @param ptQList 点位置和四元数列表 [x, y, z, qx, qy, qz, qw]
* @return 帧列表
*/
static std::vector<C_Frames> _MakeCraftPlayData_Line_Frame(
int PP_FrameValue,
const std::string &modelCode,
const std::vector<std::vector<double>> &ptQList)
{
std::vector<C_Frames> frames;
for (size_t i = 0; i < ptQList.size(); i++)
{
const auto &currQ = ptQList[i];
if (currQ.size() < 7)
{
// 数据不足,跳过
continue;
}
// 创建对象状态
C_ObjStates objState;
objState.i = modelCode;
objState.tx = std::to_string(MMToM(currQ[0]));
objState.ty = std::to_string(MMToM(currQ[1]));
objState.tz = std::to_string(MMToM(currQ[2]));
objState.qx = std::to_string(currQ[3]);
objState.qy = std::to_string(currQ[4]);
objState.qz = std::to_string(currQ[5]);
objState.qw = std::to_string(currQ[6]);
// 创建帧
C_Frames frame;
frame.time = std::to_string(PP_FrameValue * i / 1000.0);
frame.objStates.push_back(objState);
frames.push_back(frame);
}
return frames;
}
/**
* 生成线框播放数据(简化版本)
* @param frameRate 帧率
* @param modelCode 模型代码
* @param positions 位置数组 [x, y, z] (毫米)
* @param quaternions 四元数数组 [qx, qy, qz, qw]
* @return 帧列表
*/
static std::vector<C_Frames> MakeCraftPlayData_Simple(
int frameRate,
const std::string &modelCode,
const std::vector<std::vector<double>> &positions,
const std::vector<std::vector<double>> &quaternions)
{
if (positions.size() != quaternions.size())
{
// 数据长度不匹配,返回空列表
return {};
}
std::vector<C_Frames> frames;
for (size_t i = 0; i < positions.size(); i++)
{
if (positions[i].size() < 3 || quaternions[i].size() < 4)
{
continue;
}
// 创建对象状态
C_ObjStates objState;
objState.i = modelCode;
objState.tx = std::to_string(MMToM(positions[i][0]));
objState.ty = std::to_string(MMToM(positions[i][1]));
objState.tz = std::to_string(MMToM(positions[i][2]));
objState.qx = std::to_string(quaternions[i][0]);
objState.qy = std::to_string(quaternions[i][1]);
objState.qz = std::to_string(quaternions[i][2]);
objState.qw = std::to_string(quaternions[i][3]);
// 创建帧
C_Frames frame;
frame.time = std::to_string(i / static_cast<double>(frameRate));
frame.objStates.push_back(objState);
frames.push_back(frame);
}
return frames;
}
/**
* 生成完整的操作对象
* @param frameRate 帧率
* @param modelCode 模型代码
* @param positions 位置数组
* @param quaternions 四元数数组
* @return P_OPERATION对象
*/
static P_OPERATION MakeOperation(
int frameRate,
const std::string &modelCode,
const std::vector<std::vector<double>> &positions,
const std::vector<std::vector<double>> &quaternions)
{
auto frames = MakeCraftPlayData_Simple(frameRate, modelCode, positions, quaternions);
P_OPERATION operation;
operation.OPERATION.frames = frames;
return operation;
}
/**
* 添加信号写入到帧
* @param frame 目标帧
* @param tagID 标签ID
* @param tagValue 标签值
*/
static void AddSignalWrite(C_Frames &frame, const std::string &tagID, const std::string &tagValue)
{
C_Signalwrite signal;
signal.TagID = tagID;
signal.TagValue = tagValue;
frame.signalwrites.push_back(signal);
}
/**
* 添加工艺命令到帧
* @param frame 目标帧
* @param craftCode 工艺代码
* @param craftValue 工艺值
*/
static void AddCraft(C_Frames &frame, const std::string &craftCode, const std::string &craftValue)
{
C_Craft craft;
craft.CraftCode = craftCode;
craft.CraftValue = craftValue;
frame.crafts.push_back(craft);
}
/**
* 添加可见性控制到帧
* @param frame 目标帧
* @param modelCode 模型代码
* @param visible 是否可见 ("true" 或 "false")
*/
static void AddVisible(C_Frames &frame, const std::string &modelCode, const std::string &visible)
{
C_Visible visibleCmd;
visibleCmd.ModelCode = modelCode;
visibleCmd.Visible = visible;
frame.visibles.push_back(visibleCmd);
}
/**
* 添加旋转控制到帧
* @param frame 目标帧
* @param modelCode 模型代码
* @param axis 旋转轴 ("x", "y", "z")
* @param rate 旋转速率
*/
static void AddRotation(C_Frames &frame, const std::string &modelCode,
const std::string &axis, int rate)
{
C_Rotation rotation;
rotation.ModelCode = modelCode;
rotation.Axis = axis;
rotation.Rate = rate;
frame.rotations.push_back(rotation);
}
/**
* 添加等待命令到帧
* @param frame 目标帧
* @param waitStr 等待字符串
*/
static void AddWait(C_Frames &frame, const std::string &waitStr)
{
C_Wait wait;
wait.WaitStr = waitStr;
frame.waits.push_back(wait);
}
/**
* 添加附加命令到帧
* @param frame 目标帧
* @param attachToModelCode 附加目标模型代码
* @param attachToModelName 附加目标模型名称
* @param isTwoWay 是否双向附加
* @param isAttach 是否附加true=附加false=分离)
*/
static void AddAttach(C_Frames &frame, const std::string &attachToModelCode,
const std::string &attachToModelName,
bool isTwoWay, bool isAttach)
{
C_Attach attach;
attach.AttachToModelCode = attachToModelCode;
attach.AttachToModelName = attachToModelName;
attach.IsTwoWay = isTwoWay;
attach.IsAttach = isAttach;
frame.attachs.push_back(attach);
}
};
#endif // OPERATION_H

View File

@@ -0,0 +1,173 @@
#pragma once
#include <string>
#include <vector>
#include <map>
#include <nlohmann/json.hpp>
#include <fstream>
#include <sstream>
#include <iostream> // 必须包含这个头文件
#include <iomanip>
// 前置声明
struct GaitInfo;
struct SystemParameters;
struct ComponentID;
struct LegModelIDs;
struct ModelID;
struct LegParam;
struct LegParameters;
struct RobotBody;
struct RequestParameters;
// GaitInfo 结构
struct GaitInfo
{
std::string GaitType;
double Period;
double Frequency;
double StepTime;
double SupportTime;
double SwingTime;
double SupportRatio;
double SwingRatio;
int TotalFrames;
double TotalTime;
};
// SystemParameters 结构
struct SystemParameters
{
double A_x;
double A_y;
double L10;
double L20;
double L30;
double StepLength;
double StepHeight;
double X;
double DeltaX;
double L21;
double L22;
double L23;
double Beta1;
double BB2_BC_Angle;
double C1_B_Length;
double CC1;
double L31;
double C2C3_Length;
double Lead;
double D1_L_Offset;
double D2_L_Offset;
double C4_D2_Offset;
double ThighMotorReduction;
double ShankMotorReduction;
double AnkleMotorReduction;
};
// ComponentID 结构
struct ComponentID
{
std::string name;
std::string uuid;
};
// LegModelIDs 结构
struct LegModelIDs
{
std::vector<ComponentID> components;
};
// ModelID 结构
struct ModelID
{
LegModelIDs LF;
LegModelIDs LH;
LegModelIDs RF;
LegModelIDs RH;
};
// LegParam 结构
struct LegParam
{
double thigh_angle_deg;
double shank_angle_deg;
double ankle_angle_deg;
};
// LegParameters 结构
struct LegParameters
{
LegParam LF;
LegParam LH;
LegParam RF;
LegParam RH;
};
// RobotBody 结构
struct RobotBody
{
std::string BodyCode;
double x;
double y;
double z;
double qx;
double qy;
double qz;
double qw;
};
// RequestParameters 主结构
struct RequestParameters
{
GaitInfo GaitInfo;
SystemParameters SystemParameters;
ModelID ModelID;
LegParameters Param;
RobotBody RobotBody;
std::string RobotID = "0";
double t_percentage;
// 初始化静态变量 左腿和右腿
std::map<std::string, std::vector<double>> old_initial_points_dictLF;
std::map<std::string, std::vector<double>> old_initial_points_dictLH;
// 静态方法
static RequestParameters fromJsonString(const std::string &jsonStr);
static RequestParameters fromJsonFile(const std::string &filename);
// 静态函数版本
static RequestParameters &updateFromJson(const nlohmann::json &j, RequestParameters &req_param);
// 序列化为JSON字符串
std::string toJsonString() const;
// 保存到文件
bool saveToFile(const std::string &filename) const;
// 显示所有数据的调试函数
void debugPrint() const;
};
// JSON序列化/反序列化声明
void to_json(nlohmann::json &j, const GaitInfo &g);
void from_json(const nlohmann::json &j, GaitInfo &g);
void to_json(nlohmann::json &j, const SystemParameters &s);
void from_json(const nlohmann::json &j, SystemParameters &s);
void to_json(nlohmann::json &j, const ComponentID &c);
void from_json(const nlohmann::json &j, ComponentID &c);
void to_json(nlohmann::json &j, const LegModelIDs &l);
void from_json(const nlohmann::json &j, LegModelIDs &l);
void to_json(nlohmann::json &j, const ModelID &m);
void from_json(const nlohmann::json &j, ModelID &m);
void to_json(nlohmann::json &j, const LegParam &l);
void from_json(const nlohmann::json &j, LegParam &l);
void to_json(nlohmann::json &j, const LegParameters &l);
void from_json(const nlohmann::json &j, LegParameters &l);
void to_json(nlohmann::json &j, const RobotBody &r);
void from_json(const nlohmann::json &j, RobotBody &r);
void to_json(nlohmann::json &j, const RequestParameters &c);
void from_json(const nlohmann::json &j, RequestParameters &c);

View File

@@ -0,0 +1,109 @@
// graph_utils.hpp
#pragma once
#include <iostream>
#include <map>
#include <string>
#include <vector>
class GraphUtils
{
private:
// 定义边类型
using Edge = std::pair<std::string, std::string>;
using EdgeMap = std::map<std::string, Edge>;
// 静态数据成员
static EdgeMap graphData;
// 初始化静态数据
static EdgeMap initGraphData()
{
EdgeMap data;
data["AB"] = {"A", "B"};
data["AB1"] = {"A", "B1"};
data["B1B2"] = {"B1", "B2"};
data["BC"] = {"B", "C"};
data["C2C3"] = {"C2", "C3"};
data["C4C3"] = {"C4", "C3"};
data["CC4"] = {"C", "C4"};
return data;
}
public:
// 静态方法 - 获取所有边
static const EdgeMap &getGraph()
{
static EdgeMap instance = initGraphData();
return instance;
}
// 获取边的两个节点
static std::pair<std::string, std::string> getNodes(const std::string &edgeName)
{
const auto &graph = getGraph();
auto it = graph.find(edgeName);
if (it != graph.end())
{
return it->second;
}
return {"", ""}; // 返回空值表示未找到
}
// 获取所有边名
static std::vector<std::string> getEdgeNames()
{
std::vector<std::string> names;
const auto &graph = getGraph();
names.reserve(graph.size());
for (const auto &pair : graph)
{
names.push_back(pair.first);
}
return names;
}
// 导出为字符串
static std::string toString()
{
const auto &graph = getGraph();
std::string result = "{\n";
for (const auto &pair : graph)
{
result += " \"" + pair.first + "\": [\"" +
pair.second.first + "\", \"" +
pair.second.second + "\"],\n";
}
// 移除最后一个逗号
if (!graph.empty())
{
result.pop_back(); // 移除换行符
result.pop_back(); // 移除逗号
result += "\n";
}
result += "}";
return result;
}
// 查找包含节点的边
static std::vector<std::string> findEdgesWithNode(const std::string &node)
{
std::vector<std::string> result;
const auto &graph = getGraph();
for (const auto &pair : graph)
{
if (pair.second.first == node || pair.second.second == node)
{
result.push_back(pair.first);
}
}
return result;
}
// 显示图形
static void display()
{
std::cout << "Graph Structure:" << std::endl;
std::cout << toString() << std::endl;
}
};

246
include/Robot.h Normal file
View File

@@ -0,0 +1,246 @@
#ifndef ROBOT_H
#define ROBOT_H
#include <unordered_map>
#include <kdl/chain.hpp>
#include <kdl/chainfksolverpos_recursive.hpp>
#include <kdl/chainiksolvervel_pinv.hpp>
#include <kdl/chainiksolverpos_nr.hpp>
#include <kdl/chainiksolverpos_lma.hpp> // 锟斤拷锟斤拷LMA锟斤拷锟斤拷锟酵凤拷募锟<E58B9F>
#include <kdl/frames.hpp>
#include <kdl/jntarray.hpp>
#include <string>
// 锟斤拷 Robot.h 锟斤拷锟斤拷锟斤拷
#include <vector>
#include "utils.h"
class Robot
{
private:
KDL::Chain kinematicChain;
KDL::ChainFkSolverPos_recursive *fkSolver;
KDL::ChainIkSolverVel_pinv *ikVelSolver;
KDL::ChainIkSolverPos_NR *ikSolverNR;
KDL::ChainIkSolverPos_LMA *ikSolverLMA; // 锟斤拷锟斤拷LMA锟斤拷锟斤拷锟<E68BB7>
bool m_initialized;
std::unordered_map<std::string, std::string> jointChildLinkUuidMap; // joint锟斤拷锟狡碉拷child link UUID锟斤拷映锟斤拷
// 私锟叫革拷锟斤拷锟斤拷锟斤拷
double quaternionAngleDifference(const double q1[4], const double q2[4]);
int calculateAutoSteps(const double startPose[7], const double endPose[7],
int minSteps, int maxSteps,
double positionResolution, double orientationResolution);
// 锟斤拷锟斤拷私锟叫凤拷锟斤拷
bool parseJointChildLinkUuidsFromUrdf(const std::string &urdfString);
public:
/**
* @brief 默锟较癸拷锟届函锟斤拷
*/
Robot();
/**
* @brief 锟斤拷URDF锟街凤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟<E68BB7>
* @param urdfString URDF锟斤拷式锟斤拷锟街凤拷锟斤拷
*/
explicit Robot(const std::string &urdfString);
/**
* @brief 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷源
*/
~Robot();
int numberOfJoints;
/**
* @brief 锟斤拷URDF锟街凤拷锟斤拷锟斤拷始锟斤拷锟斤拷锟斤拷锟斤拷
* @param urdfString URDF锟斤拷式锟斤拷锟街凤拷锟斤拷
* @return 锟缴癸拷锟斤拷锟斤拷true锟斤拷失锟杰凤拷锟斤拷false
*/
bool initRobot(const std::string &urdfString);
/**
* @brief 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷呕锟饺<E9949F>joint锟斤拷应锟斤拷child link UUID
* @param jointIndex joint锟斤拷锟<E68BB7> (1, 2, 3, ...)
* @return 锟斤拷应锟斤拷UUID锟街凤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷蚍祷乜锟斤拷址锟斤拷锟<E68BB7>
*/
std::string getJointUuidByIndex(int jointIndex) const;
/**
* @brief 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷呕锟饺<E9949F>joint锟斤拷锟斤拷
* @param jointIndex joint锟斤拷锟<E68BB7> (1, 2, 3, ...)
* @return joint锟斤拷锟斤拷锟街凤拷锟斤拷锟斤拷锟斤拷 "joint_1", "joint_2" 锟斤拷
*/
static std::string getJointNameByIndex(int jointIndex);
/**
* @brief 锟斤拷取锟斤拷锟叫匡拷锟斤拷joint锟斤拷锟斤拷斜锟<E6969C>
* @return 锟斤拷锟斤拷锟斤拷锟叫匡拷锟斤拷joint锟斤拷诺锟斤拷锟斤拷锟<E68BB7>
*/
std::vector<int> getAvailableJointIndices() const;
// 锟斤拷Robot.h锟斤拷锟斤拷锟斤拷
std::string findJointUuidByAnyFormat(int jointIndex) const;
json inversePoseStr(const std::string &pose_str, const std::string &q_init_str);
// 锟斤拷锟斤拷锟斤拷锟斤拷筒锟街碉拷锟斤拷锟斤拷锟斤拷锟斤拷锟截诧拷趾锟斤拷锟斤拷锟<E68BB7>
json inversePoseStr2PSteps(const std::string &pose_str, const std::string &q_init_str, const std::int32_t steps);
// 锟斤拷锟斤拷锟斤拷牡锟街<E9949F>锟戒不锟斤拷锟叫诧拷趾锟街憋拷臃锟斤拷囟锟接︼拷锟斤拷锟斤拷锟<E68BB7>
json inversePoseStrNoDifference(const std::string &pose_str, const std::string &q_init_str);
std::vector<std::vector<double>> parsePoseString(const std::string &pose_str);
std::vector<std::vector<double>> parseJointListString(const std::string &pose_str);
std::unordered_map<std::string, std::string> getJointChildLinkUuidMap() const { return jointChildLinkUuidMap; }
std::string getJointChildLinkUuid(const std::string &jointName) const;
std::vector<double> parseJointString(const std::string &joint_str);
json kinematicsForwardAllJointsList(std::vector<double> joints);
json handleKinematicsForwardAllJoints(const std::string &joints_str);
json handleKinematicsForwardAllJoints_objStates(const std::string &joints_str);
/**
* @brief 锟斤拷锟斤拷锟斤拷锟斤拷锟角凤拷锟窖筹拷始锟斤拷
* @return 锟窖筹拷始锟斤拷锟斤拷锟斤拷true
*/
bool isInitialized() const { return m_initialized; }
/**
* @brief 锟斤拷锟斤拷锟剿讹拷学锟斤拷锟<E68BB7> (NR锟斤拷锟斤拷)
* @param pose 目锟斤拷位锟剿o拷锟斤拷锟斤拷锟斤拷式[x, y, z, qx, qy, qz, qw]
* @param iniJ 锟斤拷始锟截节角度o拷锟斤拷锟斤拷锟斤拷式[6锟斤拷锟截节角讹拷]
* @param resultJoints 锟斤拷锟斤拷锟斤拷锟截节角度o拷锟斤拷锟斤拷锟斤拷式[6锟斤拷锟截节角讹拷]
* @return 锟缴癸拷锟斤拷锟斤拷true锟斤拷失锟杰凤拷锟斤拷false
*/
bool calculateIK_NR(const double pose[7], const double iniJ[6], double resultJoints[6]);
/**
* @brief 锟斤拷锟斤拷锟剿讹拷学锟斤拷锟<E68BB7> (LMA锟斤拷锟斤拷)
* @param pose 目锟斤拷位锟剿o拷锟斤拷锟斤拷锟斤拷式[x, y, z, qx, qy, qz, qw]
* @param iniJ 锟斤拷始锟截节角度o拷锟斤拷锟斤拷锟斤拷式[6锟斤拷锟截节角讹拷]
* @param resultJoints 锟斤拷锟斤拷锟斤拷锟截节角度o拷锟斤拷锟斤拷锟斤拷式[6锟斤拷锟截节角讹拷]
* @param eps 锟斤拷锟斤拷锟斤拷锟斤拷 (默锟斤拷: 1e-8)
* @param maxiter 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷 (默锟斤拷: 3000)
* @param eps_joints 锟截斤拷锟捷诧拷 (默锟斤拷: 1e-12)
* @return 锟缴癸拷锟斤拷锟斤拷true锟斤拷失锟杰凤拷锟斤拷false
*/
bool calculateIK_LMA(const double pose[7], const double iniJ[6], double resultJoints[6],
double eps = 1e-8, int maxiter = 3000, double eps_joints = 1e-12);
/**
* @brief 锟斤拷锟斤拷锟剿讹拷学锟斤拷锟<E68BB7> - TCP位锟斤拷
* @param joints 锟斤拷锟斤拷亟诮嵌龋锟斤拷锟斤拷锟斤拷锟绞絒6锟斤拷锟截节角讹拷]
* @param tcpPose 锟斤拷锟絋CP位锟剿拷锟斤拷锟斤拷锟斤拷式[x, y, z, qx, qy, qz, qw]
* @return 锟缴癸拷锟斤拷锟斤拷true锟斤拷失锟杰凤拷锟斤拷false
*/
bool calculateFK_TCP(const double joints[6], double tcpPose[7]);
/**
* @brief 锟斤拷锟斤拷锟剿讹拷学锟斤拷锟<E68BB7> - 锟斤拷锟叫关斤拷位锟斤拷
* @param joints 锟斤拷锟斤拷亟诮嵌龋锟斤拷锟斤拷锟斤拷锟绞絒6锟斤拷锟截节角讹拷]
* @param jointPoses 锟斤拷锟斤拷锟斤拷泄亟锟轿伙拷耍锟斤拷锟斤拷锟斤拷锟绞絒6*7锟斤拷元锟斤拷]
* @return 锟缴癸拷锟斤拷锟斤拷true锟斤拷失锟杰凤拷锟斤拷false
*/
bool calculateFK_AllJointsforwardKinematics(const double joints[6], double jointPoses[42]);
bool forwardKinematics(const double joints[6], double jointPoses[42]);
/**
* @brief 锟斤拷取锟斤拷锟斤拷锟斤拷锟剿讹拷锟斤拷
* @return KDL锟剿讹拷锟斤拷锟斤拷锟斤拷
*/
const KDL::Chain &getKinematicChain() const { return kinematicChain; }
/**
* @brief 锟斤拷取锟截斤拷锟斤拷锟斤拷
* @return 锟截斤拷锟斤拷锟斤拷
*/
int getNumberOfJoints() const { return kinematicChain.getNrOfJoints(); }
// 锟届迹锟芥划锟斤拷锟斤拷
/**
* @brief 锟斤拷锟斤拷锟斤拷态锟斤拷墓旒拷婊<E68BB7>锟斤拷锟斤拷锟斤拷姹撅拷锟<E68BB7>
* @param pose1 锟斤拷始位锟斤拷 [x, y, z, qx, qy, qz, qw]
* @param pose2 锟斤拷止位锟斤拷 [x, y, z, qx, qy, qz, qw]
* @param outputPoses 锟斤拷锟斤拷旒拷锟斤拷锟斤拷锟<E68BB7>
* @param npoint 锟届迹锟斤拷锟斤拷锟斤拷锟斤拷0锟斤拷示锟皆讹拷锟斤拷锟姐
* @return 实锟斤拷锟斤拷锟缴的轨迹锟斤拷锟斤拷锟斤拷锟斤拷失锟杰凤拷锟斤拷-1
*/
int trajectoryPlanning(const double pose1[7], const double pose2[7],
double outputPoses[][7], int npoint = 0);
/**
* @brief 锟斤拷锟斤拷锟斤拷态锟斤拷墓旒拷婊<E68BB7>锟斤拷锟斤拷锟斤拷姹撅拷锟斤拷锟斤拷锟斤拷vector锟斤拷
* @param pose1 锟斤拷始位锟斤拷 [x, y, z, qx, qy, qz, qw]
* @param pose2 锟斤拷止位锟斤拷 [x, y, z, qx, qy, qz, qw]
* @param outputPoses 锟斤拷锟斤拷旒拷锟絭ector锟斤拷锟斤拷锟斤拷预锟饺凤拷锟斤拷锟节存
* @param npoint 锟届迹锟斤拷锟斤拷锟斤拷锟斤拷0锟斤拷示锟皆讹拷锟斤拷锟姐
* @return 实锟斤拷锟斤拷锟缴的轨迹锟斤拷锟斤拷锟斤拷锟斤拷失锟杰凤拷锟斤拷-1
*/
int trajectoryPlanning(const double pose1[7], const double pose2[7],
std::vector<std::vector<double>> &outputPoses,
int npoint = 0);
/**
* @brief 锟斤拷锟斤拷锟斤拷态锟斤拷墓旒拷婊<E68BB7>锟斤拷vector锟芥本锟斤拷
* @param pose1 锟斤拷始位锟斤拷
* @param pose2 锟斤拷止位锟斤拷
* @param outputPoses 锟斤拷锟斤拷旒拷锟斤拷锟斤拷锟<E68BB7>
* @param npoint 锟届迹锟斤拷锟斤拷锟斤拷锟斤拷0锟斤拷示锟皆讹拷锟斤拷锟姐
* @return 实锟斤拷锟斤拷锟缴的轨迹锟斤拷锟斤拷锟斤拷锟斤拷失锟杰凤拷锟斤拷-1
*/
int trajectoryPlanning(const std::vector<double> &pose1, const std::vector<double> &pose2,
std::vector<std::vector<double>> &outputPoses, int npoint = 0);
// 锟斤拷锟竭猴拷锟斤拷
/**
* @brief 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷元锟斤拷之锟斤拷慕嵌炔锟<E78294>
* @param q1 锟斤拷元锟斤拷1 [qx, qy, qz, qw]
* @param q2 锟斤拷元锟斤拷2 [qx, qy, qz, qw]
* @return 锟角度差(锟斤拷锟饺o拷
*/
// static double quaternionAngleDifference(const double q1[4], const double q2[4]);
/**
* @brief 锟皆讹拷锟斤拷锟斤拷旒拷婊<E68BB7>锟斤拷锟斤拷锟斤拷锟<E68BB7>
* @param startPose 锟斤拷始位锟斤拷 [x, y, z, qx, qy, qz, qw]
* @param endPose 锟斤拷止位锟斤拷 [x, y, z, qx, qy, qz, qw]
* @param minSteps 锟斤拷小锟斤拷锟斤拷
* @param maxSteps 锟斤拷锟斤拷锟<E68BB7>
* @param positionResolution 位锟矫分憋拷锟绞o拷锟阶o拷
* @param orientationResolution 锟斤拷态锟街憋拷锟绞o拷锟斤拷锟饺o拷
* @return 锟狡硷拷锟侥轨迹锟斤拷锟斤拷锟斤拷
*/
// static int calculateAutoSteps(const double startPose[7], const double endPose[7],
// int minSteps = 10, int maxSteps = 100,
// double positionResolution = 0.01,
// double orientationResolution = 0.1);
// 锟斤拷取锟斤拷锟斤拷锟斤拷锟斤拷息
// const KDL::Chain& getKinematicChain() const { return kinematicChain; }
// int getNumberOfJoints() const { return kinematicChain.getNrOfJoints(); }
int calculateAutoSteps(const std::vector<double> &startPose, const std::vector<double> &endPose,
int minSteps, int maxSteps,
double positionResolution, double orientationResolution);
double quaternionAngleDifference(const std::vector<double> &q1, const std::vector<double> &q2);
/**
* @brief 锟斤拷锟斤拷锟剿讹拷学锟斤拷锟<E68BB7> (LMA锟斤拷锟斤拷) - 锟斤拷锟斤拷vector锟芥本
* @param pose 目锟斤拷位锟斤拷 [x, y, z, qx, qy, qz, qw]
* @param iniJ 锟斤拷始锟截节角讹拷 [6锟斤拷锟截节角讹拷]
* @param eps 锟斤拷锟斤拷锟斤拷锟斤拷
* @param maxiter 锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷
* @param eps_joints 锟截斤拷锟捷诧拷
* @return 锟截节角讹拷vector
*/
std::vector<double> inverse(const double pose[7], const double iniJ[6],
double eps = 1e-8, int maxiter = 3000,
double eps_joints = 1e-12);
std::vector<double> inverse(const std::vector<double> &pose,
const std::vector<double> &iniJ,
double eps = 1e-8, int maxiter = 3000,
double eps_joints = 1e-12);
std::vector<double> inverse(const double pose[7],
double eps = 1e-8, int maxiter = 3000,
double eps_joints = 1e-12);
std::vector<double> inverse(const std::vector<double> &pose,
double eps = 1e-8, int maxiter = 3000,
double eps_joints = 1e-12);
};
#endif // ROBOT_H

109
include/RobotManager.h Normal file
View File

@@ -0,0 +1,109 @@
#ifndef ROBOTMANAGER_H
#define ROBOTMANAGER_H
#include "Robot.h"
#include <string>
#include <unordered_map>
#include <mutex>
#include <vector>
#include <memory>
#include <functional>
class RobotManager
{
private:
// 机器人实例表 <uuid, Robot实例>
static std::unordered_map<std::string, std::shared_ptr<Robot>> _kinematics_table;
// URDF哈希表 <uuid, urdf_hash>
static std::unordered_map<std::string, std::string> _urdf_hashes;
// 线程安全锁
static std::recursive_mutex _lock;
/**
* @brief 验证机器人运动学实例
* @param robot 机器人实例
* @return 验证成功返回true
*/
static bool _validateKinematics(const std::shared_ptr<Robot> &robot);
public:
// 删除拷贝构造函数和赋值运算符
RobotManager() = delete;
RobotManager(const RobotManager &) = delete;
RobotManager &operator=(const RobotManager &) = delete;
/**
* @brief 初始化或更新机器人实例
* @param urdf_robot URDF描述字符串
* @param robot_uuid 机器人唯一标识符(可选)
* @param force_update 是否强制更新(忽略内容变更检查)
* @return 成功状态和操作消息
*/
static std::pair<bool, std::string> initRobot(const std::string &urdf_robot,
const std::string &robot_uuid = "",
bool force_update = true);
/**
* @brief 批量初始化机器人
* @param robot_specs {uuid: urdf} 字典
* @return 每个UUID的操作结果
*/
static std::unordered_map<std::string, std::pair<bool, std::string>>
batchInit(const std::unordered_map<std::string, std::string> &robot_specs);
/**
* @brief 获取机器人实例
* @param robot_uuid 机器人UUID
* @return 机器人实例的shared_ptr如果不存在返回nullptr
*/
static std::shared_ptr<Robot> getRobot(const std::string &robot_uuid);
/**
* @brief 移除机器人
* @param robot_uuid 机器人UUID
* @return 成功状态和操作消息
*/
static std::pair<bool, std::string> removeRobot(const std::string &robot_uuid);
/**
* @brief 列出所有机器人
* @param detail 是否返回详细信息
* @return 机器人信息字典
*/
static std::unordered_map<std::string, std::string> listRobots(bool detail = false);
/**
* @brief 获取机器人数量
* @return 当前管理的机器人数量
*/
static size_t getRobotCount();
/**
* @brief 清空所有机器人实例
*/
static void clearAll();
/**
* @brief 检查机器人是否存在
* @param robot_uuid 机器人UUID
* @return 存在返回true
*/
static bool containsRobot(const std::string &robot_uuid);
/**
* @brief 线程安全的操作执行
* @param func 要执行的操作函数
* @return 操作结果
*/
template <typename Func, typename... Args>
static auto executeSafely(Func &&func, Args &&...args)
-> decltype(func(std::forward<Args>(args)...))
{
std::lock_guard<std::recursive_mutex> lock(_lock);
return func(std::forward<Args>(args)...);
}
};
#endif // ROBOTMANAGER_H

View File

@@ -0,0 +1,97 @@
// SharedGeometry.h
#ifndef SHARED_GEOMETRY_H
#define SHARED_GEOMETRY_H
#include <string>
#include <vector>
#include <cmath>
#include <sstream>
#include <iomanip>
#include "QuadrupedRobotSimulation/OPERATION.h"
// 2D向量类
class Vector2D
{
public:
double X;
double Y;
Vector2D();
Vector2D(double x, double y);
// 运算符重载
Vector2D operator+(const Vector2D &other) const;
Vector2D operator-(const Vector2D &other) const;
Vector2D operator*(double scalar) const;
// 几何运算
double distanceTo(const Vector2D &other) const;
double length() const;
Vector2D normalized() const;
// 静态方法
static Vector2D Zero();
static double Distance(const Vector2D &v1, const Vector2D &v2);
double Length() const { return length(); }
Vector2D Normalize() const { return normalized(); }
// 叉积和点积
double Cross(const Vector2D &other) const;
double Dot(const Vector2D &other) const;
};
// 姿态类(简化版)
class Pose7
{
public:
double tx;
double ty;
double tz;
double qx;
double qy;
double qz;
double qw;
Pose7();
};
// 姿态计算器 - 兼顾两个程序的需求
class PoseCalculator
{
public:
/**
* 计算两个2D点之间的位置和姿态四元数
* 适用于CrankSliderMechanism
*/
static Pose7 CalculatePoseAndQuaternion(const Vector2D &start, const Vector2D &end);
/**
* 计算两个2D点之间的位置和姿态四元数
* 返回double[7]数组,顺序为: [x, y, z, qw, qx, qy, qz]
* 适用于BaseClass程序
*/
static std::vector<double> CalculatePoseAndQuaternionArray(double x1, double y1, double x2, double y2);
/**
* 毫米转米
*/
static double MMToM(double MM);
/**
* 四舍五入辅助函数
*/
static double Round(double value, int decimals = 6);
/**
* 数字转字符串
*/
static std::string ToString(double value, int decimals = 6);
/**
* 计算姿态并返回C_ObjStates对象如果需要
*/
static C_ObjStates CalculatePoseAndQuaternion_C_ObjStates(const std::string &i,
double x1, double y1,
double x2, double y2);
};
#endif // SHARED_GEOMETRY_H

265
include/URDFStrings.h Normal file
View File

@@ -0,0 +1,265 @@
namespace URDFStrings
{
const char *abb120_urdf = R"(<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from /home/xtark/ABB_ws/src/abb_experimental/abb_irb120_support/urdf/irb120_3_58.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<robot name="abb_irb120_3_58" xmlns:xacro="http://ros.org/wiki/xacro" uuid="9D7EAEF4-1AAB-499E-8783-B6CE016BC6D1">
<!-- Conversion were obtained from http://www.e-paint.co.uk/Lab_values.asp
unless otherwise stated. -->
<!-- link list -->
<link name="link_6" uuid="D9A71933-B7FA-4A77-805F-F7C404101CB1">
<inertial>
<mass value="6.215" />
<origin rpy="0 0 0" xyz="-0.04204 8.01E-05 0.07964" />
<inertia ixx="0.0247272" ixy="-8.0784E-05" ixz="0.00130902" iyy="0.0491285" iyz="-8.0419E-06" izz="0.0472376" />
</inertial>
<visual>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/visual/base_link.stl" />
</geometry>
<material name="">
<color rgba="0.7372549 0.3490196 0.1607843 1" />
</material>
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/collision/base_link.stl" />
</geometry>
<material name="">
<color rgba="1 1 0 1" />
</material>
</collision>
</link>
<link name="base_link" uuid="9D7EAEF4-1AAB-499E-8783-B6CE016BC6D1">
<inertial>
<mass value="6.215" />
<origin rpy="0 0 0" xyz="-0.04204 8.01E-05 0.07964" />
<inertia ixx="0.0247272" ixy="-8.0784E-05" ixz="0.00130902" iyy="0.0491285" iyz="-8.0419E-06" izz="0.0472376" />
</inertial>
<visual>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/visual/base_link.stl" />
</geometry>
<material name="">
<color rgba="0.7372549 0.3490196 0.1607843 1" />
</material>
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/collision/base_link.stl" />
</geometry>
<material name="">
<color rgba="1 1 0 1" />
</material>
</collision>
</link>
<link name="link_1" uuid="0A049A00-6C1F-4748-A22A-6B5942B09430">
<inertial>
<mass value="6.215" />
<origin rpy="0 0 0" xyz="-0.04204 8.01E-05 0.07964" />
<inertia ixx="0.0247272" ixy="-8.0784E-05" ixz="0.00130902" iyy="0.0491285" iyz="-8.0419E-06" izz="0.0472376" />
</inertial>
<visual>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/visual/base_link.stl" />
</geometry>
<material name="">
<color rgba="0.7372549 0.3490196 0.1607843 1" />
</material>
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/collision/base_link.stl" />
</geometry>
<material name="">
<color rgba="1 1 0 1" />
</material>
</collision>
</link>
<link name="link_2" uuid="F07C2A76-A13F-4475-B936-181FD8DBF986">
<inertial>
<mass value="6.215" />
<origin rpy="0 0 0" xyz="-0.04204 8.01E-05 0.07964" />
<inertia ixx="0.0247272" ixy="-8.0784E-05" ixz="0.00130902" iyy="0.0491285" iyz="-8.0419E-06" izz="0.0472376" />
</inertial>
<visual>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/visual/base_link.stl" />
</geometry>
<material name="">
<color rgba="0.7372549 0.3490196 0.1607843 1" />
</material>
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/collision/base_link.stl" />
</geometry>
<material name="">
<color rgba="1 1 0 1" />
</material>
</collision>
</link>
<link name="link_3" uuid="94295448-DD21-4A87-A80F-F65B85AB861E">
<inertial>
<mass value="6.215" />
<origin rpy="0 0 0" xyz="-0.04204 8.01E-05 0.07964" />
<inertia ixx="0.0247272" ixy="-8.0784E-05" ixz="0.00130902" iyy="0.0491285" iyz="-8.0419E-06" izz="0.0472376" />
</inertial>
<visual>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/visual/base_link.stl" />
</geometry>
<material name="">
<color rgba="0.7372549 0.3490196 0.1607843 1" />
</material>
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/collision/base_link.stl" />
</geometry>
<material name="">
<color rgba="1 1 0 1" />
</material>
</collision>
</link>
<link name="link_4" uuid="964D5694-ACC3-4C30-93F3-066D1FA04952">
<inertial>
<mass value="6.215" />
<origin rpy="0 0 0" xyz="-0.04204 8.01E-05 0.07964" />
<inertia ixx="0.0247272" ixy="-8.0784E-05" ixz="0.00130902" iyy="0.0491285" iyz="-8.0419E-06" izz="0.0472376" />
</inertial>
<visual>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/visual/base_link.stl" />
</geometry>
<material name="">
<color rgba="0.7372549 0.3490196 0.1607843 1" />
</material>
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/collision/base_link.stl" />
</geometry>
<material name="">
<color rgba="1 1 0 1" />
</material>
</collision>
</link>
<link name="link_5" uuid="243AAD5C-4E64-4E9E-A9FA-E79600045F08">
<inertial>
<mass value="6.215" />
<origin rpy="0 0 0" xyz="-0.04204 8.01E-05 0.07964" />
<inertia ixx="0.0247272" ixy="-8.0784E-05" ixz="0.00130902" iyy="0.0491285" iyz="-8.0419E-06" izz="0.0472376" />
</inertial>
<visual>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/visual/base_link.stl" />
</geometry>
<material name="">
<color rgba="0.7372549 0.3490196 0.1607843 1" />
</material>
</visual>
<collision>
<origin rpy="0 0 0" xyz="0 0 0" />
<geometry>
<mesh filename="package://abb_irb120_support/meshes/irb120_3_58/collision/base_link.stl" />
</geometry>
<material name="">
<color rgba="1 1 0 1" />
</material>
</collision>
</link>
<!-- end of link list -->
<!-- joint list -->
<joint name="joint_6" type="revolute" innerId="8E926C36-2177-41F4-BA1C-8E34589BF818">
<origin rpy="0 0 0" xyz="0.072 0 0" />
<parent link="link_5" uuid="243AAD5C-4E64-4E9E-A9FA-E79600045F08" />
<child link="link_6" uuid="D9A71933-B7FA-4A77-805F-F7C404101CB1" />
<limit effort="0" lower="-6.28318548202515" upper="6.28318548202515" velocity="1.39626336097717" />
<axis xyz="1 0 0" />
<dynamics damping="0.0" friction="0.0" />
</joint>
<joint name="joint_1" type="revolute" innerId="45B6400D-AE70-4FE0-910A-6F8962B4F792">
<origin rpy="0 0 0" xyz="0 0 0" />
<parent link="base_link" uuid="9D7EAEF4-1AAB-499E-8783-B6CE016BC6D1" />
<child link="link_1" uuid="0A049A00-6C1F-4748-A22A-6B5942B09430" />
<limit effort="0" lower="-6.28318548202515" upper="6.28318548202515" velocity="1.39626336097717" />
<axis xyz="0 0 1" />
<dynamics damping="0.0" friction="0.0" />
</joint>
<joint name="joint_2" type="revolute" innerId="35A4A784-26D1-4DBA-BAEF-740B6E2278AB">
<origin rpy="0 0 0" xyz="0 0 0.29" />
<parent link="link_1" uuid="0A049A00-6C1F-4748-A22A-6B5942B09430" />
<child link="link_2" uuid="F07C2A76-A13F-4475-B936-181FD8DBF986" />
<limit effort="0" lower="-6.28318548202515" upper="6.28318548202515" velocity="1.39626336097717" />
<axis xyz="0 1 0" />
<dynamics damping="0.0" friction="0.0" />
</joint>
<joint name="joint_3" type="revolute" innerId="BBAD98ED-4240-4E21-8620-C6D448303F9B">
<origin rpy="0 0 0" xyz="0 0 0.27" />
<parent link="link_2" uuid="F07C2A76-A13F-4475-B936-181FD8DBF986" />
<child link="link_3" uuid="94295448-DD21-4A87-A80F-F65B85AB861E" />
<limit effort="0" lower="-6.28318548202515" upper="6.28318548202515" velocity="1.39626336097717" />
<axis xyz="0 1 0" />
<dynamics damping="0.0" friction="0.0" />
</joint>
<joint name="joint_4" type="revolute" innerId="1A0AD00D-9676-49F1-BB15-852516029946">
<origin rpy="0 0 0" xyz="0.134 0 0.07" />
<parent link="link_3" uuid="94295448-DD21-4A87-A80F-F65B85AB861E" />
<child link="link_4" uuid="964D5694-ACC3-4C30-93F3-066D1FA04952" />
<limit effort="0" lower="-6.28318548202515" upper="6.28318548202515" velocity="1.39626336097717" />
<axis xyz="1 0 0" />
<dynamics damping="0.0" friction="0.0" />
</joint>
<joint name="joint_5" type="revolute" innerId="29B7FB0E-32B5-4216-A3E4-95EA7767B3B8">
<origin rpy="0 0 0" xyz="0.168 0 0" />
<parent link="link_4" uuid="964D5694-ACC3-4C30-93F3-066D1FA04952" />
<child link="link_5" uuid="243AAD5C-4E64-4E9E-A9FA-E79600045F08" />
<limit effort="0" lower="-6.28318548202515" upper="6.28318548202515" velocity="1.39626336097717" />
<axis xyz="0 1 0" />
<dynamics damping="0.0" friction="0.0" />
</joint>
<!-- end of joint list -->
<!-- ROS-Industrial 'base' frame: base_link to ABB World Coordinates transform -->
<link name="base" uuidBase="39fc08ad-6f2e-4fc5-8bcc-dd6e35918a31" />
<joint name="base_link-base" type="fixed">
<origin rpy="0 0 0" xyz="0 0 0" />
<parent link="base" />
<child link="base_link" />
</joint>
<!-- ROS-Industrial 'flange' frame: attachment point for EEF models -->
<link name="flange" />
<joint name="joint_6-flange" type="fixed">
<origin rpy="0 0 0" xyz="0 0 0" />
<parent link="link_6" />
<child link="flange" />
</joint>
<!-- ROS-Industrial 'tool0' frame: all-zeros tool frame -->
<link name="tool0" uuidTool="5b570726-e374-4d8a-882e-60c803f37ac0" />
<joint name="link_6-tool0" type="fixed">
<origin rpy="0 0 0" xyz="0 0 0" />
<parent link="flange" />
<child link="tool0" />
</joint>
<gazebo>
<plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
<robotNamespace>/</robotNamespace>
</plugin>
</gazebo>
</robot>
)";
}

436
include/function_metadata.h Normal file
View File

@@ -0,0 +1,436 @@
#ifndef FUNCTION_METADATA_H
#define FUNCTION_METADATA_H
#include <string>
#include <vector>
#include <map>
#include <any>
#include <functional>
#include <memory>
#include <algorithm>
#include <cctype>
#include <sstream> // 添加这行
// 参数类型枚举
enum class ParamType
{
INT,
FLOAT,
DOUBLE,
BOOL,
STRING,
INT_ARRAY,
FLOAT_ARRAY,
VOID_PTR,
UNKNOWN
};
// 参数信息结构
struct ParamInfo
{
std::string name;
ParamType type;
std::any default_value;
bool is_optional;
ParamInfo(const std::string &n, ParamType t, std::any dv = {}, bool opt = false)
: name(n), type(t), default_value(dv), is_optional(opt) {}
// 获取类型名称
std::string getTypeName() const
{
switch (type)
{
case ParamType::INT:
return "int";
case ParamType::FLOAT:
return "float";
case ParamType::DOUBLE:
return "double";
case ParamType::BOOL:
return "bool";
case ParamType::STRING:
return "string";
case ParamType::INT_ARRAY:
return "int[]";
case ParamType::FLOAT_ARRAY:
return "float[]";
case ParamType::VOID_PTR:
return "void*";
default:
return "unknown";
}
}
// 类型转换
template <typename T>
T convert(const std::any &value) const
{
try
{
if constexpr (std::is_same_v<T, int>)
{
if (value.type() == typeid(int))
return std::any_cast<int>(value);
if (value.type() == typeid(double))
return static_cast<int>(std::any_cast<double>(value));
if (value.type() == typeid(float))
return static_cast<int>(std::any_cast<float>(value));
if (value.type() == typeid(std::string))
{
try
{
return std::stoi(std::any_cast<std::string>(value));
}
catch (...)
{
return 0;
}
}
return std::any_cast<T>(value);
}
else if constexpr (std::is_same_v<T, float>)
{
if (value.type() == typeid(float))
return std::any_cast<float>(value);
if (value.type() == typeid(double))
return static_cast<float>(std::any_cast<double>(value));
if (value.type() == typeid(int))
return static_cast<float>(std::any_cast<int>(value));
if (value.type() == typeid(std::string))
{
try
{
return std::stof(std::any_cast<std::string>(value));
}
catch (...)
{
return 0.0f;
}
}
return std::any_cast<T>(value);
}
else if constexpr (std::is_same_v<T, std::string>)
{
if (value.type() == typeid(std::string))
return std::any_cast<std::string>(value);
// 其他类型转换为字符串
std::stringstream ss;
if (value.type() == typeid(int))
ss << std::any_cast<int>(value);
else if (value.type() == typeid(float))
ss << std::any_cast<float>(value);
else if (value.type() == typeid(double))
ss << std::any_cast<double>(value);
else if (value.type() == typeid(bool))
ss << (std::any_cast<bool>(value) ? "true" : "false");
else
return "";
return ss.str();
}
else if constexpr (std::is_same_v<T, bool>)
{
if (value.type() == typeid(bool))
return std::any_cast<bool>(value);
if (value.type() == typeid(int))
return std::any_cast<int>(value) != 0;
if (value.type() == typeid(std::string))
{
std::string str = std::any_cast<std::string>(value);
std::string lower_str = str;
std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(),
[](unsigned char c)
{ return std::tolower(c); });
return lower_str == "true" || lower_str == "1" || lower_str == "yes" || lower_str == "on";
}
return false;
}
else
{
return std::any_cast<T>(value);
}
}
catch (const std::bad_any_cast &)
{
return T();
}
}
};
// 函数信息结构
struct FunctionInfo
{
std::string name;
std::string description;
std::vector<ParamInfo> params;
std::function<std::any(const std::vector<std::any> &)> handler;
// 参数名称映射,支持多个名称
std::map<std::string, std::string> param_aliases;
FunctionInfo(const std::string &n, const std::string &desc = "")
: name(n), description(desc) {}
// 添加参数
FunctionInfo &addParam(const std::string &name, ParamType type,
std::any default_value = {}, bool optional = false)
{
params.emplace_back(name, type, default_value, optional);
return *this;
}
// 添加参数别名
FunctionInfo &addAlias(const std::string &original, const std::vector<std::string> &aliases)
{
for (const auto &alias : aliases)
{
param_aliases[alias] = original;
}
return *this;
}
// 设置处理器
template <typename Func>
FunctionInfo &setHandler(Func &&func)
{
handler = std::forward<Func>(func);
return *this;
}
// 获取规范化的参数名
std::string getCanonicalName(const std::string &input_name) const
{
// 检查别名
auto it = param_aliases.find(input_name);
if (it != param_aliases.end())
{
return it->second;
}
// 检查直接匹配(大小写不敏感)
std::string lower_input = toLower(input_name);
for (const auto &param : params)
{
std::string lower_param = toLower(param.name);
if (lower_param == lower_input)
{
return param.name;
}
}
return input_name; // 如果没有找到,返回原名称
}
// 验证参数
bool validateParams(const std::map<std::string, std::any> &input_params,
std::string &error_msg) const
{
// 检查必需参数
for (const auto &param : params)
{
if (!param.is_optional)
{
bool found = false;
for (const auto &input : input_params)
{
if (getCanonicalName(input.first) == param.name)
{
found = true;
break;
}
}
if (!found)
{
error_msg = "Missing required parameter: " + param.name;
return false;
}
}
}
return true;
}
private:
static std::string toLower(const std::string &str)
{
std::string result = str;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c)
{ return ::towlower(c); });
return result;
}
};
// 函数注册表
class FunctionRegistry
{
private:
std::map<std::string, std::shared_ptr<FunctionInfo>> functions_;
FunctionRegistry() = default;
public:
static FunctionRegistry &instance()
{
static FunctionRegistry instance;
return instance;
}
// 禁止复制
FunctionRegistry(const FunctionRegistry &) = delete;
FunctionRegistry &operator=(const FunctionRegistry &) = delete;
// 注册函数
void registerFunction(const std::shared_ptr<FunctionInfo> &func_info)
{
functions_[func_info->name] = func_info;
}
// 获取函数
std::shared_ptr<FunctionInfo> getFunction(const std::string &name)
{
// 直接查找
auto it = functions_.find(name);
if (it != functions_.end())
{
return it->second;
}
// 大小写不敏感查找
std::string lower_name = toLower(name);
for (const auto &[func_name, func_info] : functions_)
{
std::string lower_func = toLower(func_name);
if (lower_func == lower_name)
{
return func_info;
}
}
return nullptr;
}
// 获取所有函数
const std::map<std::string, std::shared_ptr<FunctionInfo>> &getAllFunctions() const
{
return functions_;
}
// 自动推导参数类型
ParamType deduceParamType(const std::any &value)
{
if (value.type() == typeid(int))
return ParamType::INT;
if (value.type() == typeid(float))
return ParamType::FLOAT;
if (value.type() == typeid(double))
return ParamType::DOUBLE;
if (value.type() == typeid(bool))
return ParamType::BOOL;
if (value.type() == typeid(std::string))
return ParamType::STRING;
if (value.type() == typeid(std::vector<int>))
return ParamType::INT_ARRAY;
if (value.type() == typeid(std::vector<float>))
return ParamType::FLOAT_ARRAY;
if (value.type() == typeid(void *))
return ParamType::VOID_PTR;
return ParamType::UNKNOWN;
}
// 智能参数匹配
std::map<std::string, std::any> smartMatchParams(
const std::shared_ptr<FunctionInfo> &func_info,
const std::map<std::string, std::any> &input_params)
{
std::map<std::string, std::any> matched_params;
// 1. 首先处理输入参数
for (const auto &[input_name, input_value] : input_params)
{
std::string canonical_name = func_info->getCanonicalName(input_name);
// 查找对应的参数定义
auto param_it = std::find_if(func_info->params.begin(), func_info->params.end(),
[&canonical_name](const ParamInfo &param)
{
return param.name == canonical_name;
});
if (param_it != func_info->params.end())
{
// 类型转换
std::any converted_value;
switch (param_it->type)
{
case ParamType::INT:
converted_value = param_it->convert<int>(input_value);
break;
case ParamType::FLOAT:
converted_value = param_it->convert<float>(input_value);
break;
case ParamType::STRING:
converted_value = param_it->convert<std::string>(input_value);
break;
case ParamType::BOOL:
converted_value = param_it->convert<bool>(input_value);
break;
default:
converted_value = input_value; // 保持原类型
}
matched_params[param_it->name] = converted_value;
}
}
// 2. 填充默认值
for (const auto &param : func_info->params)
{
if (matched_params.find(param.name) == matched_params.end())
{
if (!param.default_value.has_value() && !param.is_optional)
{
// 必需参数没有提供值,使用类型默认值
switch (param.type)
{
case ParamType::INT:
matched_params[param.name] = 0;
break;
case ParamType::FLOAT:
matched_params[param.name] = 0.0f;
break;
case ParamType::STRING:
matched_params[param.name] = std::string();
break;
case ParamType::BOOL:
matched_params[param.name] = false;
break;
default:
// 空值
break;
}
}
else if (param.default_value.has_value())
{
matched_params[param.name] = param.default_value;
}
}
}
return matched_params;
}
private:
static std::string toLower(const std::string &str)
{
std::string result = str;
std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c)
{ return ::towlower(c); });
return result;
}
};
#endif // FUNCTION_METADATA_H

30
include/math_utils.h Normal file
View File

@@ -0,0 +1,30 @@
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
#ifdef __cplusplus
extern "C"
{
#endif
// 基础数学运算
int add(int a, int b);
int subtract(int a, int b);
float multiply(float a, float b);
float divide(float a, float b);
int fibonacci(int n);
// 内存操作
void *create_buffer(int size);
void destroy_buffer(void *p);
// 数组运算
int compute_sum(int *arr, int size);
// 字符串操作
const char *get_greeting();
#ifdef __cplusplus
}
#endif
#endif // MATH_UTILS_H

View File

@@ -0,0 +1,100 @@
#ifndef SMART_JSON_WRAPPER_H
#define SMART_JSON_WRAPPER_H
#include "function_metadata.h"
#include "math_utils.h"
#include <string>
#include <map>
#include <any>
#include <chrono>
#include <sstream>
#include <regex>
#include <cstring>
// JSON 响应结构
struct SmartResponse
{
bool success = true;
int code = 0;
std::string msg;
std::string req_code;
std::string req_cmd;
std::any res_data;
double execution_time = 0.0;
std::map<std::string, std::string> execution_info;
// 转换为 JSON 字符串
std::string toJson() const;
// 创建成功响应
static SmartResponse createSuccess(const std::string &req_code,
const std::string &req_cmd,
const std::any &data = {});
// 创建错误响应
static SmartResponse createError(const std::string &req_code,
const std::string &req_cmd,
int code,
const std::string &msg);
};
// 智能 JSON 处理器
class SmartJsonProcessor
{
private:
// 注册所有数学函数
void registerMathFunctions();
// 智能类型推断
std::any inferJsonValue(const std::string &key, const std::string &value_str);
// 解析数组
std::vector<int> parseIntArray(const std::string &array_str);
std::vector<float> parseFloatArray(const std::string &array_str);
// 字符串处理
static std::string trim(const std::string &str);
static std::vector<std::string> split(const std::string &str, char delimiter);
public:
SmartJsonProcessor();
~SmartJsonProcessor();
// JSON 解析
std::map<std::string, std::any> parseJsonParams(const std::string &json_str);
// 处理 JSON 请求
SmartResponse processRequest(const std::string &json_request);
// 获取函数列表
std::map<std::string, std::shared_ptr<FunctionInfo>> getAvailableFunctions() const;
// 获取函数信息
std::string getFunctionInfo(const std::string &func_name) const;
};
// WASM 导出函数
extern "C"
{
const char *init_func();
// 智能处理 JSON 请求
const char *func(const char *json_request);
// 智能处理 JSON 请求
const char *smart_process_json(const char *json_request);
// 获取可用函数列表
const char *smart_get_function_list();
// 获取函数详情
const char *smart_get_function_info(const char *func_name);
// 测试智能匹配
const char *smart_test_match(const char *json_request);
// 释放字符串
void smart_free_string(const char *str);
// 获取版本信息
const char *smart_get_version();
}
#endif // SMART_JSON_WRAPPER_H

287
include/spc_core.h Normal file
View File

@@ -0,0 +1,287 @@
#ifndef SPC_CORE_H
#define SPC_CORE_H
#include <iostream>
#include <vector>
#include <map>
#include <cmath>
#include <string>
#include <stdexcept>
#include <algorithm>
#include <memory>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <fstream>
// 使用 nlohmann/json 库
#include "nlohmann/json.hpp"
using json = nlohmann::json;
// ==================== 前向声明 ====================
class SpcDataXR;
class SpcDataXS;
class SpcDataCpk;
class SpcTestData;
// class ApiResponseSpc;
class SpcRequestParam;
// ==================== 常量定义 ====================
const int MAX_SUBGROUP_SIZE = 25;
const int MIN_SUBGROUP_SIZE = 2;
const int DEFAULT_DECIMALS = 3;
// ==================== SPC 系数结构 ====================
struct SpcCoefficient
{
int ID;
int NUM;
double A;
double A2;
double A3;
double B3;
double B4;
double B5;
double B6;
double D1;
double D2;
double D3;
double D4;
double C4;
double C4_1;
double L_D1;
double L_D1_1;
// 添加默认构造函数
SpcCoefficient() : ID(0), NUM(0), A(0), A2(0), A3(0), B3(0),
B4(0), B5(0), B6(0), D1(0), D2(0), D3(0),
D4(0), C4(0), C4_1(0), L_D1(0), L_D1_1(0) {}
SpcCoefficient(int id, int num, double a, double a2, double a3, double b3,
double b4, double b5, double b6, double d1, double d2,
double d3, double d4, double c4, double c4_1, double l_d1, double l_d1_1);
};
// ==================== SPC 系数表类 ====================
class SpcCoefficients
{
private:
static std::map<int, SpcCoefficient> coefficientDict;
static void Initialize();
public:
static const SpcCoefficient &GetBySubgroupSize(int subgroupSize);
static double GetA2(int subgroupSize);
static double GetA3(int subgroupSize);
static double GetD3(int subgroupSize);
static double GetD4(int subgroupSize);
static double GetB3(int subgroupSize);
static double GetB4(int subgroupSize);
static double GetC4(int subgroupSize);
static double GetL_D1(int subgroupSize);
};
// ==================== 工具函数 ====================
namespace SpcUtils
{
double Round(double value, int decimals = DEFAULT_DECIMALS);
double Mean(const std::vector<double> &values);
double Max(const std::vector<double> &values);
double Min(const std::vector<double> &values);
double Range(const std::vector<double> &values);
double StandardDeviation(const std::vector<double> &values);
double StandardDeviationPopulation(const std::vector<double> &values);
std::string GetCurrentTimestamp();
}
// ==================== SPC 数据类 ====================
class SpcDataXR
{
public:
int n; // 子组大小
int k; // 子组个数
double CL_X; // X图中心线
double UCL_X; // X图上控制限
double LCL_X; // X图下控制限
double CL_R; // R图中心线
double UCL_R; // R图上控制限
double LCL_R; // R图下控制限
std::vector<double> CL_Xk; // 各子组平均值
std::vector<double> CL_Rk; // 各子组极差
SpcDataXR();
json ToJson() const;
static SpcDataXR FromJson(const json &j);
};
class SpcDataXS
{
public:
int n; // 子组大小
int k; // 子组个数
double CL_X; // X图中心线
double UCL_X; // X图上控制限
double LCL_X; // X图下控制限
double CL_S; // S图中心线
double UCL_S; // S图上控制限
double LCL_S; // S图下控制限
std::vector<double> CL_Xk; // 各子组平均值
std::vector<double> CL_Sk; // 各子组标准差
SpcDataXS();
json ToJson() const;
static SpcDataXS FromJson(const json &j);
};
class SpcDataCpk
{
public:
int n; // 子组大小
int k; // 子组个数
double SL; // 特征值中值
double USL; // 规格上限
double LSL; // 规格下限
double Singma; // 组内过程标准差的估计值
double SingmaS; // 子组标准差的平均值
double Ca; // 过程准确度
double Cp; // 过程精密度
double CPU; // 能力指数上限
double CPL; // 能力指数下限
double CR; // 稳定过程的能力比值
double Cpk; // 过程能力指数
double Pp; // 性能指数
double PPU; // 性能指数上限
double PPL; // 性能指数下限
double PR; // 性能比率
double Ppk; // 性能指数
double ProcessSpread; // 全距
double GroupWidth; // 组距
int GroupCount; // 分组数
double ValueMax; // 最大值
double ValueMin; // 最小值
std::vector<double> Xk; // 组中点
std::vector<double> XkUp; // 组上界
std::vector<double> XkDown; // 组下界
std::vector<double> Yk; // 组频率百分比
std::vector<double> YkCount; // 组频数
std::vector<double> NormalDistributionX; // 正态分布X坐标
std::vector<double> NormalDistributionY; // 正态分布Y坐标
SpcDataCpk();
json ToJson() const;
static SpcDataCpk FromJson(const json &j);
};
// ==================== 统一的 SPC 计算结果 JSON 结构 ====================
class SpcResultJson
{
public:
SpcDataXR XR;
SpcDataXS XS;
SpcDataCpk Cpk;
std::string Timestamp;
std::string Version;
SpcResultJson();
json ToJson() const;
static SpcResultJson FromJson(const json &j);
};
// ==================== SPC 计算器 ====================
class SpcCalculator
{
private:
static void CalculateHistogramData(const std::vector<double> &data, SpcDataCpk &result);
static void CalculateNormalDistributionCurve(double mean, double sigma, SpcDataCpk &result);
public:
static json Spc(const json &param);
static SpcDataXR CalculateXR(const std::vector<double> &data, int subgroupSize);
static SpcDataXS CalculateXS(const std::vector<double> &data, int subgroupSize);
static SpcDataCpk CalculateCpk(const std::vector<double> &data, int subgroupSize, double usl, double lsl);
static json CalculateAllToJson(const std::vector<double> &data, int subgroupSize, double usl, double lsl);
static void RoundSpcData(SpcDataXR &xr, SpcDataXS &xs, SpcDataCpk &cpk, int decimals = DEFAULT_DECIMALS);
static void RoundSpcDataXR(SpcDataXR &data, int decimals = DEFAULT_DECIMALS);
static void RoundSpcDataXS(SpcDataXS &data, int decimals = DEFAULT_DECIMALS);
static void RoundSpcDataCpk(SpcDataCpk &data, int decimals = DEFAULT_DECIMALS);
static double CalculateCp(const std::vector<double> &data, int subgroupSize, double usl, double lsl);
static double CalculatePp(const std::vector<double> &data, int subgroupSize, double usl, double lsl);
static double CalculateCpu(const std::vector<double> &data, int subgroupSize, double usl);
static double CalculateCpl(const std::vector<double> &data, int subgroupSize, double lsl);
static double CalculateXbarbar(const std::vector<double> &data, int subgroupSize);
static double CalculateRbar(const std::vector<double> &data, int subgroupSize);
static double CalculateSbar(const std::vector<double> &data, int subgroupSize);
};
// ==================== 直方图计算器 ====================
class HistogramCalculator
{
public:
static void CalculateHistogram(const std::vector<double> &data, int numBins,
std::vector<int> &frequencies, std::vector<double> &cumulativePercentages);
static double CalculateBinWidth(const std::vector<double> &data, int numBins);
};
// ==================== API 响应和请求类 ====================
class SpcTestData
{
public:
int n; // 子组大小
int k; // 子组个数
double usl; // 特征值上限
double lsl; // 特征值下限
std::vector<double> x; // 测量数据数组
SpcTestData();
json ToJson() const;
static SpcTestData FromJson(const json &j);
};
class SpcRequestParam : public SpcTestData
{
// 可以添加额外的请求参数
};
// class ApiResponseSpc
// {
// public:
// bool success;
// int code;
// std::string msg;
// std::string req_code;
// std::string req_from;
// std::string req_cmd;
// std::shared_ptr<SpcRequestParam> req_param;
// ApiResponseSpc();
// json ToJson() const;
// static ApiResponseSpc FromJson(const json &j);
// };
// ==================== SPC 数据处理工具 ====================
// class SpcDataProcessor
// {
// public:
// static ApiResponseSpc DeserializeApiResponseSpc(const std::string &jsonStr);
// static SpcTestData ExtractSpcTestData(const ApiResponseSpc &response);
// static ApiResponseSpc ValidateResponse(const ApiResponseSpc &response); // 添加这行
// };
// ==================== 示例数据 ====================
namespace Spc_Data_TestData
{
extern const int n;
extern const int k;
extern const double USL;
extern const double LSL;
extern const std::vector<double> X;
}
// ==================== 示例函数 ====================
void RunJsonExample_5_30();
void RunSpcExample();
#endif // SPC_CORE_H

89
include/utils.h Normal file
View File

@@ -0,0 +1,89 @@
#ifndef UTILS_H
#define UTILS_H
#include <string>
#include <chrono>
#include "nlohmann/json.hpp"
// // ǰ<><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD> httplib <20><> Response <20><>
// namespace httplib {
// class Response;
// }
using json = nlohmann::json;
namespace utils
{
// ʱ<><CAB1><EFBFBD><EFBFBD>غ<EFBFBD><D8BA><EFBFBD>
std::string get_current_time();
std::string get_current_timestamp();
// JSON <20><>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD>
json create_error_response(int code, const std::string &message, const std::string &details = "");
json create_success_response(const json &data = {}, const std::string &message = "Success");
// UTF-8 <20><>֤
bool is_valid_utf8(const std::string &str);
std::string sanitize_utf8(const std::string &str);
// API <20><>Ӧ<EFBFBD><D3A6>ʽ
json create_api_response(bool success, int code, const std::string &msg,
const std::string &req_code = "", const std::string &req_from = "",
const std::string &req_cmd = "", const json &res_data = json::object());
// Base64 <20><><EFBFBD><EFBFBD><EFBFBD>URDF<44><46><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
std::string base64_decode(const std::string &encoded_string);
std::string base64_to_urdf(const std::string &base64_urdf);
bool save_base64_urdf_to_file(const std::string &base64_urdf, const std::string &filename);
bool validate_urdf_base64(const std::string &base64_urdf);
bool save_urdf_string_to_file(const std::string &urdf_content, const std::string &filename);
} // namespace utils
class StringUtils
{
public:
/**
* @brief 将包含一个分隔符的字符串拆分成两部分
* @param str 要拆分的字符串
* @param delimiter 分隔符,默认为'_'
* @return std::pair<std::string, std::string> 包含两个部分的pair
* 第一个元素是分隔符前的部分,第二个是分隔符后的部分
* 如果未找到分隔符,第二个元素为空字符串
*/
static std::pair<std::string, std::string> splitByDelimiter(
const std::string &str,
char delimiter = '_');
/**
* @brief 专门拆分"A_B"格式的字符串
* @param str 要拆分的字符串
* @return std::pair<std::string, std::string> 包含两个部分的pair
*/
static std::pair<std::string, std::string> splitA_B(const std::string &str);
/**
* @brief 将字符串按分隔符拆分成两个部分,支持引用参数返回
* @param str 要拆分的字符串
* @param part1 返回第一部分
* @param part2 返回第二部分
* @param delimiter 分隔符,默认为'_'
* @return bool 如果找到分隔符返回true否则返回false
*/
static bool splitToTwoParts(
const std::string &str,
std::string &part1,
std::string &part2,
char delimiter = '_');
/**
* @brief 严格拆分,必须包含且只包含一个分隔符
* @param str 要拆分的字符串
* @param delimiter 分隔符,默认为'_'
* @return std::pair<std::string, std::string> 包含两个部分的pair
* @throws std::invalid_argument 如果没有找到分隔符或找到多个分隔符
*/
static std::pair<std::string, std::string> splitStrict(
const std::string &str,
char delimiter = '_');
};
#endif // UTILS_H