// // Created by lgv on 2026/3/2. // /** * @file s_curve.h * @brief 严格点到点位置 S 曲线轨迹生成器 * * 实现标准 7 段式位置 S 曲线速度剖面: * 1. 加加速度上升段(加速度逐渐增大) * 2. 匀加速段 * 3. 加加速度下降段(加速度逐渐降到 0) * 4. 匀速巡航段 * 5. 加加速度下降段(减速度逐渐增大) * 6. 匀减速段 * 7. 加加速度上升段(减速度逐渐降到 0) * * 本类只负责严格点到点 profile 规划与采样,不负责实时目标跟踪。 */ #pragma once #include #include #include namespace cmvr { /** * @brief 单次点到点运动的 S 曲线剖面参数 */ struct SCurveProfile { // 7 个阶段的持续时间 double t1; // 加加速度上升时间(加速阶段) double t2; // 匀加速时间 double t3; // 加加速度下降时间(加速阶段结束) double t4; // 匀速时间(巡航) double t5; // 加加速度下降时间(减速阶段) double t6; // 匀减速时间 double t7; // 加加速度上升时间(减速阶段结束) double total_time; // 运动约束 double j_max; // 最大加加速度 (rad/s³) double a_max; // 最大加速度 (rad/s²) double v_max; // 最大速度 (rad/s) // 运动参数 double distance; // 运动总距离 double direction; // +1 或 -1 double v_cruise; // 实际达到的巡航速度 double a_limit; // 实际达到的加速度上限 // 初始条件 double p0; // 初始位置 double v0; // 初始速度 double a0; // 初始加速度 double vf; // 终止速度 SCurveProfile() : t1(0), t2(0), t3(0), t4(0), t5(0), t6(0), t7(0) , total_time(0) , j_max(50.0), a_max(10.0), v_max(3.0) , distance(0), direction(1.0), v_cruise(0), a_limit(0) , p0(0), v0(0), a0(0), vf(0) {} }; /** * @brief 严格点到点位置 S 曲线规划器 */ class SCurve { public: /** * @brief 构造函数(带运动约束) * @param max_velocity 最大速度 (rad/s) * @param max_acceleration 最大加速度 (rad/s²) * @param max_jerk 最大加加速度 (rad/s³) */ SCurve(double max_velocity = 3.0, double max_acceleration = 10.0, double max_jerk = 50.0); /** * @brief 设置运动约束 */ void setConstraints(double max_velocity, double max_acceleration, double max_jerk); /** * @brief 获取当前运动约束 */ void getConstraints(double& max_velocity, double& max_acceleration, double& max_jerk) const; /** * @brief 计算点到点运动的完整 S 曲线剖面 * @param start_position 起始位置 * @param end_position 终止位置 * @param start_velocity 起始速度(默认 0) * @param end_velocity 终止速度(默认 0) * @return 计算得到的剖面参数 */ SCurveProfile calculateProfile(double start_position, double end_position, double start_velocity = 0.0, double end_velocity = 0.0); /** * @brief 给定剖面下,获取时刻 t 的位置 * @param profile S 曲线剖面 * @param t 从起点开始的时间 * @return 时刻 t 的位置 */ double getPositionAtTime(const SCurveProfile& profile, double t) const; /** * @brief 给定剖面下,获取时刻 t 的速度 * @param profile S 曲线剖面 * @param t 从起点开始的时间 * @return 时刻 t 的速度 */ double getVelocityAtTime(const SCurveProfile& profile, double t) const; /** * @brief 给定剖面下,获取时刻 t 的加速度 * @param profile S 曲线剖面 * @param t 从起点开始的时间 * @return 时刻 t 的加速度 */ double getAccelerationAtTime(const SCurveProfile& profile, double t) const; /** * @brief 给定剖面下,获取时刻 t 的加加速度 * @param profile S 曲线剖面 * @param t 从起点开始的时间 * @return 时刻 t 的加加速度 */ double getJerkAtTime(const SCurveProfile& profile, double t) const; /** * @brief 按固定时间间隔生成轨迹点 * @param profile S 曲线剖面 * @param dt 轨迹点时间间隔 * @param positions 输出:每个时间点的位置 * @param velocities 输出:每个时间点的速度 * @param accelerations 输出:每个时间点的加速度 */ void generateTrajectory(const SCurveProfile& profile, double dt, std::vector& positions, std::vector& velocities, std::vector& accelerations) const; private: double max_velocity_; double max_acceleration_; double max_jerk_; static constexpr double EPSILON = 1e-9; static constexpr double VELOCITY_THRESHOLD = 1e-6; double computeSegmentJerk(const SCurveProfile& profile, double t) const; void calculateShortProfile(SCurveProfile& profile) const; void calculateLongProfile(SCurveProfile& profile) const; }; } // namespace cmvr