123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- /**
- ******************************************************************************
- * @file : heading_diff_ctrl_c.cpp
- * @author : wangyingjie
- * @brief : None
- * @attention : None
- * @date : 2025/5/23
- ******************************************************************************
- */
- #include "heading_diff_ctrl_c.h"
- //// 小船控制结构体
- //typedef struct
- //{
- // studio_pid heading_pid; // 方位角PID控制器
- // studio_point_c target; // 目标点
- // double base_throttle; // 基础油门
- // double left_throttle; // 左侧油门
- // double right_throttle; // 右侧油门
- //} diff_ctrl;
- // 初始化小船控制器
- void init_diff_ctrl(diff_ctrl *controller,
- const studio_point_c *target,
- double base_throttle, // 输入范围0~1.0
- double Kp,
- double Ki,
- double Kd)
- {
- init_pid(&controller->heading_pid, 0, 0, Kp, Ki, Kd, 1.0, 0.3);
- controller->target = *target;
- controller->base_throttle = base_throttle;
- controller->left_throttle = base_throttle;
- controller->right_throttle = base_throttle;
- }
- void reset_diff_ctrl_goal(diff_ctrl* controller, const studio_point_c* target)
- {
- controller->target = *target;
- set_goal(&controller->heading_pid, 0);
- }
- // 正确计算最短路径误差(返回-180~180°)
- double calculate_heading_error(double target_deg, double current_deg)
- {
- double error = target_deg - current_deg;
- error = fmod(error + 360.0, 360.0); // 转0~360°
- if (error > 180.0)
- {
- error -= 360.0;
- }
- return error;
- }
- double update_boat(diff_ctrl *controller, const studio_point_c *current_pos, double current_heading_deg)
- {
- // 1. 计算目标方位角(确保函数正确)
- const double target_deg = azimuth_angle_gcs_c(current_pos, &controller->target);
- // 2. 计算最短路径误差
- double error = calculate_heading_error(target_deg, current_heading_deg);
- double steer = 0.0;
- // 3. PID控制
- if (fabs(error) > 1.0) // 仅当误差超过1度时进行纠偏
- {
- set_goal(&controller->heading_pid, 0);
- steer = compute_pid(&controller->heading_pid, error);
- }
- else
- {
- }
- // 4. 差速控制(关键修正)
- controller->left_throttle = controller->base_throttle - steer;
- controller->right_throttle = controller->base_throttle + steer;
- // 5. 限幅保护
- controller->left_throttle = fmax(0.0, fmin(1.0, controller->left_throttle));
- controller->right_throttle = fmax(0.0, fmin(1.0, controller->right_throttle));
- return distance_squared_gcs_c(current_pos, &controller->target);
- }
- void simulate_movement(studio_point_c *current_pos, double *current_heading, double left_throttle, double right_throttle)
- {
- const double dt = 0.1; // 时间间隔(秒)
- const double max_speed = 2; // 最大速度(米/秒)
- const double turn_rate = 40; // 转向速率(度/秒 per 差速百分比)
- // 保存原始位置用于计算位移
- const studio_point_c original_pos = *current_pos;
- // 1. 计算航向变化 ---------------------------------------------
- double steer_diff = left_throttle - right_throttle;
- *current_heading += turn_rate * steer_diff * dt;
- *current_heading = fmod(*current_heading + 360.0, 360.0);
- // 2. 计算位移量(米)------------------------------------------
- double avg_throttle = (left_throttle + right_throttle) / 2.0;
- double speed = max_speed * avg_throttle;
- // 将航向角转换为弧度
- double radian = *current_heading * AO_M_PI / 180.0;
- // 计算东向和北向位移(单位:米)
- const double delta_east = speed * sin(radian) * dt; // 东向位移(+东/-西)
- const double delta_north = speed * cos(radian) * dt; // 北向位移(+北/-南)
- // 3. 通过投影转换更新位置 -------------------------------------
- *current_pos = lonlat_move_by(&original_pos, delta_east, delta_north);
- }
|