#include #include #include #include #include #include #include #include #include #include #include #include "logger/logger.h" #include "rclcpp/rclcpp.hpp" #include "sweeper_interfaces/msg/can_frame.hpp" #include "sweeper_interfaces/msg/fu.hpp" #include "sweeper_interfaces/msg/mc_ctrl.hpp" #include "sweeper_interfaces/msg/pl.hpp" #include "sweeper_interfaces/msg/rtk.hpp" #include "sweeper_interfaces/msg/sub.hpp" using namespace std; using namespace std::chrono; // ================== RTK全局变量 ================== system_clock::time_point last_rtk_time; const duration rtk_timeout = duration(0.5); struct struct_rtk { double lon; double lat; double direction; double speed; int reliability; }; struct_rtk g_rtk; // ================== GPS转相对坐标的常数 ================== #define Lat_Origin 32.045062 #define Lon_Origin 118.845200366 #define deg_rad (0.01745329252) #define R_LATI (6378137) #define R_LONT (5407872) // ================== 枚举定义 ================== const int EMPTY = 0; const int OBSTACLE = 1; const int VEHICLE = 2; int is_start = 0; // ================== 路点结构体 ================== struct Waypoint { double x, y; int speed; double lon, lat; // 路点的绝对坐标(GPS) Waypoint() : x(0), y(0), speed(300), lon(0), lat(0) {} Waypoint(double px, double py, int s = 300, double plon = 0, double plat = 0) : x(px), y(py), speed(s), lon(plon), lat(plat) { } }; // ================== 障碍物分析结构体 ================== struct ObstacleAnalysis { bool has_front_critical = false; bool has_front_area = false; bool has_left_critical = false; bool has_right_critical = false; int obstacle_distance = -1; int obstacle_width = 0; int left_edge = -1, right_edge = -1; int free_space_left = 0; int free_space_right = 0; int calculateSafeDistance(int speed) const { return std::max(3, speed / 400 + 2); } bool needEmergencyBrake(int speed) const { if (!has_front_critical) return false; return obstacle_distance <= calculateSafeDistance(speed); } }; // ================== GPS坐标转换函数 ================== // 计算两点间距离(米) double ntzx_GPS_length(double lonti1, double lati1, double lonti2, double lati2) { double x, y, length; x = (R_LONT) * (lonti2 - lonti1) * deg_rad; y = (R_LATI) * (lati2 - lati1) * deg_rad; length = sqrt(x * x + y * y); return length; } // GPS转相对坐标(米) // Cur_navAngle: 当前航向角(度) // Cur_lonti, Cur_lati: 当前位置GPS坐标 // Dest_lonti, Dest_lati: 目标位置GPS坐标 // x_diff, y_diff: 输出的相对坐标(米) int ntzx_GPS_posit(double Cur_navAngle, double Cur_lonti, double Cur_lati, double Dest_lonti, double Dest_lati, double* x_diff, double* y_diff) { double Navi_rad, x, y; float k1, k2, k3, k4; Navi_rad = Cur_navAngle * deg_rad; x = (Dest_lonti - Cur_lonti) * deg_rad * R_LONT; y = (Dest_lati - Cur_lati) * deg_rad * R_LATI; k1 = cos(Navi_rad); k2 = (-1) * sin(Navi_rad); k3 = (-1) * k2; k4 = k1; *x_diff = x * k1 + y * k2; *y_diff = x * k3 + y * k4; return 0; } // ================== 状态机核心类 ================== class StateMachine { public: enum State { NORMAL, WAITING, LATERAL_SHIFT, PARALLEL_MOVE }; StateMachine() { current_state_ = NORMAL; } void setState(State new_state) { if (new_state != current_state_) { exit(current_state_); current_state_ = new_state; enter(new_state); } } void execute() {} State getCurrentState() const { return current_state_; } std::string getStateString() const { switch (current_state_) { case NORMAL: return "正常行驶"; case WAITING: return "等待决策"; case LATERAL_SHIFT: return "横向偏移"; case PARALLEL_MOVE: return "平行前进"; default: return "未知状态"; } } ObstacleAnalysis obstacle_analysis; int publish_speed = 0; float publish_angle = 0.0f; int counter = 0; int direction = 0; std::vector angle_history; rclcpp::Time start_time; bool start_time_set = false; private: State current_state_; void enter(State state) { switch (state) { case NORMAL: counter = 0; direction = 0; break; case WAITING: publish_speed = 0; publish_angle = 0.0f; counter = 0; break; case LATERAL_SHIFT: publish_speed = 300; counter = 0; break; case PARALLEL_MOVE: publish_speed = 300; counter = 0; break; default: break; } } void exit(State state) {} }; // ================== FU节点类 ================== class fu_node : public rclcpp::Node { public: fu_node(std::string name) : Node(name), state_machine_(std::make_unique()) { LOG_INFO("%s节点已经启动.", name.c_str()); // 初始化最后接收时间为启动时间(避免初始状态直接超时) last_rtk_time = system_clock::now(); // ======== 参数声明 ======== this->declare_parameter("enable_obstacle_stop", true); this->declare_parameter("enable_obstacle_avoid", true); this->declare_parameter("enable_visualize_grid", true); this->declare_parameter("FRONT_STOP_ZONE_ROWS", 3); this->declare_parameter("REAR_STOP_ZONE_ROWS", 1); this->declare_parameter("LEFT_STOP_ZONE_COLS", 3); this->declare_parameter("RIGHT_STOP_ZONE_COLS", 3); this->declare_parameter("front_area_extend", 7); this->declare_parameter("left_area_extend", 2); this->declare_parameter("right_area_extend", 2); this->declare_parameter("waypoint_tolerance", 2.0); this->declare_parameter("lateral_offset", 2); this->declare_parameter("parallel_distance", 3); this->declare_parameter("avoid_able_width", 6); this->declare_parameter("min_free_space", 6); // ======== 参数读取 ======== this->get_parameter("enable_obstacle_stop", enable_obstacle_stop_); this->get_parameter("enable_obstacle_avoid", enable_obstacle_avoid_); this->get_parameter("enable_visualize_grid", enable_visualize_grid_); this->get_parameter("FRONT_STOP_ZONE_ROWS", FRONT_STOP_ZONE_ROWS_); this->get_parameter("REAR_STOP_ZONE_ROWS", REAR_STOP_ZONE_ROWS_); this->get_parameter("LEFT_STOP_ZONE_COLS", LEFT_STOP_ZONE_COLS_); this->get_parameter("RIGHT_STOP_ZONE_COLS", RIGHT_STOP_ZONE_COLS_); this->get_parameter("front_area_extend", front_area_extend_); this->get_parameter("left_area_extend", left_area_extend_); this->get_parameter("right_area_extend", right_area_extend_); this->get_parameter("waypoint_tolerance", waypoint_tolerance_); this->get_parameter("lateral_offset", lateral_offset_); this->get_parameter("parallel_distance", parallel_distance_); this->get_parameter("avoid_able_width", avoid_able_width_); this->get_parameter("min_free_space", min_free_space_); parameter_callback_handle_ = this->add_on_set_parameters_callback(std::bind(&fu_node::parameter_callback, this, std::placeholders::_1)); // ======== 订阅者初始化 ======== subscription_grid = this->create_subscription( "grid_raw", 10, std::bind(&fu_node::gridCallback, this, std::placeholders::_1)); msg_subscribe_pl = this->create_subscription( "pl_message", 10, std::bind(&fu_node::msg_callback_pl, this, std::placeholders::_1)); msg_subscribe_rtk = this->create_subscription( "rtk_message", 10, std::bind(&fu_node::msg_callback_rtk, this, std::placeholders::_1)); // ======== 发布者初始化 ======== pub_mc = this->create_publisher("auto_mc_ctrl", 10); // ======== 定时器初始化 ======== timer_ = this->create_wall_timer(std::chrono::milliseconds(20), std::bind(&fu_node::timer_callback, this)); // ======== 初始化 ======== avoiding_obstacle_ = false; current_waypoint_idx_ = 0; vehicle_min_x_ = -1; vehicle_max_x_ = -1; vehicle_min_y_ = -1; vehicle_max_y_ = -1; node_clock_ = this->get_clock(); front_stop_zone_ = {0, 0, 0, 0}; rear_stop_zone_ = {0, 0, 0, 0}; left_stop_zone_ = {0, 0, 0, 0}; right_stop_zone_ = {0, 0, 0, 0}; LOG_INFO( "\n---------- FU节点参数配置 ----------\n 遇障停车: %s\n 绕障: %s\n 栅格可视化: %s\n" " 路点容差: %.2f米\n 横向偏移: %d栅格\n 平行距离: %d栅格\n" " 可绕宽度: %d栅格\n 最小空闲: %d栅格\n--------------------------------------------\n", (enable_obstacle_stop_ ? "开启" : "关闭"), (enable_obstacle_avoid_ ? "开启" : "关闭"), (enable_visualize_grid_ ? "是" : "否"), waypoint_tolerance_, lateral_offset_, parallel_distance_, avoid_able_width_, min_free_space_); } private: std::unique_ptr state_machine_; rclcpp::Clock::SharedPtr node_clock_; // ======== 配置参数 ======== bool enable_obstacle_stop_, enable_obstacle_avoid_, enable_visualize_grid_; int FRONT_STOP_ZONE_ROWS_, REAR_STOP_ZONE_ROWS_; int LEFT_STOP_ZONE_COLS_, RIGHT_STOP_ZONE_COLS_; int front_area_extend_, left_area_extend_, right_area_extend_; double waypoint_tolerance_; int lateral_offset_, parallel_distance_, avoid_able_width_, min_free_space_; rclcpp::Node::OnSetParametersCallbackHandle::SharedPtr parameter_callback_handle_; // ======== 规划层消息缓存 ======== double pl_x_ = 0.0, pl_y_ = 0.0; int pl_speed_ = 0; // ======== 栅格检测结果 ======== bool obstacle_in_front_ = false, obstacle_in_rear_ = false; bool obstacle_in_left_ = false, obstacle_in_right_ = false; bool obstacle_in_front_area_ = false; int obstacle_left_edge_ = -1, obstacle_right_edge_ = -1; int obstacle_max_x_ = 100; int free_space_left_ = 0, free_space_right_ = 0; // ======== 自车位置 ======== int vehicle_min_x_, vehicle_max_x_, vehicle_min_y_, vehicle_max_y_; // ======== 安全区结构体 ======== struct SafetyZone { int min_x, max_x, min_y, max_y; }; SafetyZone front_stop_zone_, rear_stop_zone_, left_stop_zone_, right_stop_zone_; // ======== 避障相关 ======== bool avoiding_obstacle_; std::vector avoidance_waypoints_; int current_waypoint_idx_; std::vector> cached_grid_; bool grid_data_valid_ = false; rclcpp::Time last_grid_time_; // ======== 发布者和订阅者 ======== rclcpp::Publisher::SharedPtr pub_mc; rclcpp::Subscription::SharedPtr subscription_grid; rclcpp::Subscription::SharedPtr msg_subscribe_pl; rclcpp::Subscription::SharedPtr msg_subscribe_rtk; rclcpp::TimerBase::SharedPtr timer_; // ======== 参数回调 ======== rcl_interfaces::msg::SetParametersResult parameter_callback(const std::vector& parameters) { rcl_interfaces::msg::SetParametersResult result; result.successful = true; for (const auto& param : parameters) { if (param.get_name() == "enable_obstacle_stop") { enable_obstacle_stop_ = param.as_bool(); LOG_INFO("[参数更新] 遇障停车: %s", enable_obstacle_stop_ ? "开启" : "关闭"); } else if (param.get_name() == "enable_obstacle_avoid") { enable_obstacle_avoid_ = param.as_bool(); LOG_INFO("[参数更新] 自主绕障: %s", enable_obstacle_avoid_ ? "开启" : "关闭"); if (!enable_obstacle_avoid_) { state_machine_->setState(StateMachine::NORMAL); avoiding_obstacle_ = false; avoidance_waypoints_.clear(); } } else if (param.get_name() == "waypoint_tolerance") waypoint_tolerance_ = param.as_double(); else if (param.get_name() == "lateral_offset") lateral_offset_ = param.as_int(); else if (param.get_name() == "parallel_distance") parallel_distance_ = param.as_int(); else if (param.get_name() == "avoid_able_width") avoid_able_width_ = param.as_int(); else if (param.get_name() == "min_free_space") min_free_space_ = param.as_int(); } return result; } // ======== RTK回调 ======== void msg_callback_rtk(const sweeper_interfaces::msg::Rtk::SharedPtr msg) { last_rtk_time = system_clock::now(); g_rtk.reliability = (msg->p_quality == 4 && msg->h_quality == 4) ? 1 : 0; g_rtk.lat = msg->lat; g_rtk.lon = msg->lon; g_rtk.direction = msg->head; } // ======== 角度计算 ======== float calculate_the_angle(double target_x, double target_y) { if (target_x == 0) return 90.0f; float angle_f = atan2(target_y, target_x) * 180 / M_PI; float steering_angle = (angle_f <= 90.0f) ? 90.0f - angle_f : -(angle_f - 90.0f); // 计算阶段就限制角度范围 return std::clamp(steering_angle, -50.0f, 50.0f); } // ======== 自车位置检测 ======== void findVehicleRectangle(const std::vector>& grid) { vehicle_min_x_ = vehicle_max_x_ = vehicle_min_y_ = vehicle_max_y_ = -1; for (size_t i = 0; i < grid.size(); ++i) { for (size_t j = 0; j < grid[i].size(); ++j) { if (grid[i][j] == VEHICLE) { if (vehicle_min_x_ == -1 || (int)i < vehicle_min_x_) vehicle_min_x_ = i; if (vehicle_max_x_ == -1 || (int)i > vehicle_max_x_) vehicle_max_x_ = i; if (vehicle_min_y_ == -1 || (int)j < vehicle_min_y_) vehicle_min_y_ = j; if (vehicle_max_y_ == -1 || (int)j > vehicle_max_y_) vehicle_max_y_ = j; } } } if (vehicle_min_x_ != -1 && vehicle_max_x_ != -1 && vehicle_min_y_ != -1 && vehicle_max_y_ != -1) { calculateSafetyZones(grid.size(), grid[0].size()); } } // ======== 安全区计算 ======== void calculateSafetyZones(int grid_height, int grid_width) { front_stop_zone_ = {max(0, vehicle_min_x_ - FRONT_STOP_ZONE_ROWS_), vehicle_min_x_ - 1, vehicle_min_y_, vehicle_max_y_}; rear_stop_zone_ = {vehicle_max_x_ + 1, min(grid_height - 1, vehicle_max_x_ + REAR_STOP_ZONE_ROWS_), vehicle_min_y_, vehicle_max_y_}; left_stop_zone_ = {vehicle_min_x_, vehicle_max_x_, max(0, vehicle_min_y_ - LEFT_STOP_ZONE_COLS_), vehicle_min_y_ - 1}; right_stop_zone_ = {vehicle_min_x_, vehicle_max_x_, vehicle_max_y_ + 1, min(grid_width - 1, vehicle_max_y_ + RIGHT_STOP_ZONE_COLS_)}; } // ======== 栅格回调 ======== void gridCallback(const std_msgs::msg::Int32MultiArray::SharedPtr msg) { last_grid_time_ = node_clock_->now(); if (msg->layout.dim.size() != 2) { LOG_ERROR("栅格地图消息维度无效!"); return; } size_t height = msg->layout.dim[0].size; size_t width = msg->layout.dim[1].size; if (msg->data.size() != height * width) { LOG_ERROR("栅格地图数据长度不匹配!期望%zu,实际%zu", height * width, msg->data.size()); return; } std::vector> grid(height, std::vector(width)); for (size_t i = 0; i < height; ++i) for (size_t j = 0; j < width; ++j) grid[i][j] = msg->data[i * width + j]; findVehicleRectangle(grid); analyzeObstacles(grid); if (enable_visualize_grid_) visualizeGridInTerminal(grid); cacheGridData(grid); // 立即执行紧急停车检查(高优先级) updateObstacleAnalysis(); if (enable_obstacle_stop_ && is_start) { if (state_machine_->obstacle_analysis.has_front_critical) { state_machine_->publish_speed = 0; state_machine_->publish_angle = 0.0f; state_machine_->setState(StateMachine::WAITING); publishControlCommand(true); // 立即发布带刹车的停车指令 LOG_WARN("[紧急停车] 栅格回调中检测到前方障碍物,立即停车!"); } } } // ======== 栅格缓存 ======== void cacheGridData(const std::vector>& grid) { cached_grid_ = grid; grid_data_valid_ = true; } // ======== 障碍物分析 ======== void analyzeObstacles(const std::vector>& grid) { obstacle_in_front_ = obstacle_in_rear_ = obstacle_in_left_ = obstacle_in_right_ = false; obstacle_in_front_area_ = false; obstacle_left_edge_ = obstacle_right_edge_ = -1; free_space_left_ = free_space_right_ = 0; obstacle_max_x_ = 100; if (vehicle_min_x_ == -1) return; // 检测前方必停区障碍物 bool found_front_obstacle = false; for (int i = front_stop_zone_.max_x; i >= front_stop_zone_.min_x && !found_front_obstacle; --i) for (int j = front_stop_zone_.min_y; j <= front_stop_zone_.max_y; ++j) if ((size_t)i < grid.size() && (size_t)j < grid[0].size() && grid[i][j] == OBSTACLE) { obstacle_in_front_ = true; found_front_obstacle = true; break; } // 检测后方必停区障碍物 for (int i = rear_stop_zone_.min_x; i <= rear_stop_zone_.max_x; ++i) for (int j = rear_stop_zone_.min_y; j <= rear_stop_zone_.max_y; ++j) if ((size_t)i < grid.size() && (size_t)j < grid[0].size() && grid[i][j] == OBSTACLE) { obstacle_in_rear_ = true; break; } // 检测左侧必停区障碍物 for (int i = left_stop_zone_.min_x; i <= left_stop_zone_.max_x; ++i) for (int j = left_stop_zone_.min_y; j <= left_stop_zone_.max_y; ++j) if ((size_t)i < grid.size() && (size_t)j < grid[0].size() && grid[i][j] == OBSTACLE) { obstacle_in_left_ = true; break; } // 检测右侧必停区障碍物 for (int i = right_stop_zone_.min_x; i <= right_stop_zone_.max_x; ++i) for (int j = right_stop_zone_.min_y; j <= right_stop_zone_.max_y; ++j) if ((size_t)i < grid.size() && (size_t)j < grid[0].size() && grid[i][j] == OBSTACLE) { obstacle_in_right_ = true; break; } // 检测前方扩展区域障碍物 int front_area_min_x = max(0, vehicle_min_x_ - front_area_extend_); int front_area_max_x = vehicle_min_x_ - 1; int front_area_min_y = max(0, vehicle_min_y_ - left_area_extend_); int front_area_max_y = min((int)grid[0].size() - 1, vehicle_max_y_ + right_area_extend_); int leftmost_obstacle = -1, rightmost_obstacle = -1; for (size_t i = front_area_min_x; i <= (size_t)front_area_max_x; ++i) { for (size_t j = front_area_min_y; j <= (size_t)front_area_max_y; ++j) { if (grid[i][j] == OBSTACLE) { obstacle_in_front_area_ = true; if (leftmost_obstacle == -1 || (int)j < leftmost_obstacle) leftmost_obstacle = j; if (rightmost_obstacle == -1 || (int)j > rightmost_obstacle) rightmost_obstacle = j; int distance = vehicle_min_x_ - (int)i; if (distance < obstacle_max_x_) obstacle_max_x_ = distance; } } } // 计算绕障空间 calculateAvoidanceSpace(grid, leftmost_obstacle, rightmost_obstacle); } // ======== 绕障空间计算 ======== void calculateAvoidanceSpace(const std::vector>& grid, int core_left_obstacle, int core_right_obstacle) { if (!obstacle_in_front_area_) { free_space_left_ = left_area_extend_ + (vehicle_max_y_ - vehicle_min_y_ + 1); free_space_right_ = right_area_extend_ + (vehicle_max_y_ - vehicle_min_y_ + 1); obstacle_left_edge_ = obstacle_right_edge_ = -1; return; } obstacle_left_edge_ = core_left_obstacle; obstacle_right_edge_ = core_right_obstacle; size_t avoidance_min_x = (size_t)max(0, vehicle_min_x_ - front_area_extend_); size_t avoidance_max_x = (size_t)vehicle_min_x_ - 1; // 计算左侧空闲空间 int left_check_start = max(0, vehicle_min_y_ - left_area_extend_); int left_check_end = obstacle_left_edge_ - 1; free_space_left_ = calculateSpaceInDirection(grid, avoidance_min_x, avoidance_max_x, left_check_start, left_check_end); // 计算右侧空闲空间 int right_check_start = obstacle_right_edge_ + 1; int right_check_end = min((int)grid[0].size() - 1, vehicle_max_y_ + right_area_extend_); free_space_right_ = calculateSpaceInDirection(grid, avoidance_min_x, avoidance_max_x, right_check_start, right_check_end); } // ======== 方向空闲空间计算 ======== int calculateSpaceInDirection(const std::vector>& grid, size_t min_x, size_t max_x, int check_start_y, int check_end_y) { if (check_start_y > check_end_y) return 0; int available_space = 0; for (int j = check_start_y; j <= check_end_y; ++j) { if (j < 0 || j >= (int)grid[0].size()) break; bool column_clear = true; for (size_t i = min_x; i <= max_x; ++i) { if (i >= grid.size() || grid[i][j] == OBSTACLE) { column_clear = false; break; } } if (column_clear) available_space++; else break; } return available_space; } // ======== 栅格可视化 ======== void visualizeGridInTerminal(const std::vector>& grid) { std::stringstream ss; ss << " ----------栅格地图可视化---------- " << endl; ss << " " << string(grid[0].size(), '-') << endl; ss << " "; for (size_t i = 0; i < grid[0].size(); i++) ss << (i % 10); ss << endl; for (size_t i = 0; i < grid.size(); i++) { ss << (i < 10 ? " " : "") << i << "|"; for (size_t j = 0; j < grid[i].size(); j++) { bool in_front = (i >= front_stop_zone_.min_x && i <= front_stop_zone_.max_x && j >= front_stop_zone_.min_y && j <= front_stop_zone_.max_y); bool in_left = (i >= left_stop_zone_.min_x && i <= left_stop_zone_.max_x && j >= left_stop_zone_.min_y && j <= left_stop_zone_.max_y); bool in_right = (i >= right_stop_zone_.min_x && i <= right_stop_zone_.max_x && j >= right_stop_zone_.min_y && j <= right_stop_zone_.max_y); if (grid[i][j] == OBSTACLE) ss << "@"; else if (grid[i][j] == VEHICLE) ss << "V"; else if (in_front) ss << "F"; else if (in_left) ss << "L"; else if (in_right) ss << "R"; else ss << "."; } ss << "|" << endl; } ss << " " << string(grid[0].size(), '-') << endl; LOG_INFO("%s", ss.str().c_str()); } // ======== 规划层消息回调 ======== void msg_callback_pl(const sweeper_interfaces::msg::Pl::SharedPtr msg) { pl_x_ = msg->x; pl_y_ = msg->y; pl_speed_ = (int)msg->speed; is_start = msg->is_start; LOG_INFO("[规划层消息回调] 目标点位置: x -- %.2f , y -- %.2f", pl_x_, pl_y_); } // ======== 绕障路点规划 ======== void planAvoidanceWaypoints(int avoid_direction) { avoidance_waypoints_.clear(); const double GRID_RESOLUTION = 0.3; const int SAFE_GRID_GAP = 1; const int AVOID_SPEED = 300; Waypoint point_lateral_shift; Waypoint point_parallel_forward; double actual_lateral_offset_m = 0.0; int lateral_offset_grid_num = 0; const int stage1_forward_grid = state_machine_->obstacle_analysis.obstacle_distance; const int stage2_forward_grid = parallel_distance_; const double stage1_forward_m = stage1_forward_grid * GRID_RESOLUTION; const double stage2_forward_m = stage2_forward_grid * GRID_RESOLUTION; // 计算横向偏移量 if (avoid_direction == -1) { lateral_offset_grid_num = (vehicle_max_y_ - state_machine_->obstacle_analysis.left_edge) + SAFE_GRID_GAP; actual_lateral_offset_m = -1 * lateral_offset_grid_num * GRID_RESOLUTION; } else if (avoid_direction == 1) { lateral_offset_grid_num = (state_machine_->obstacle_analysis.right_edge - vehicle_min_y_) + SAFE_GRID_GAP; actual_lateral_offset_m = 1 * lateral_offset_grid_num * GRID_RESOLUTION; } // 相对坐标 double relative_x_1 = actual_lateral_offset_m; double relative_y_1 = stage1_forward_m; double relative_x_2 = actual_lateral_offset_m; double relative_y_2 = stage2_forward_m; // 转换为绝对GPS坐标 double abs_lon_1, abs_lat_1, abs_lon_2, abs_lat_2; rtk_relative_to_gps(relative_x_1, relative_y_1, g_rtk.direction, g_rtk.lon, g_rtk.lat, &abs_lon_1, &abs_lat_1); rtk_relative_to_gps(relative_x_2, relative_y_2, g_rtk.direction, g_rtk.lon, g_rtk.lat, &abs_lon_2, &abs_lat_2); // 构建路点 point_lateral_shift = Waypoint(relative_x_1, relative_y_1, AVOID_SPEED, abs_lon_1, abs_lat_1); point_parallel_forward = Waypoint(relative_x_2, relative_y_2, AVOID_SPEED, abs_lon_2, abs_lat_2); avoidance_waypoints_.push_back(point_lateral_shift); avoidance_waypoints_.push_back(point_parallel_forward); current_waypoint_idx_ = 0; avoiding_obstacle_ = true; state_machine_->setState(StateMachine::LATERAL_SHIFT); LOG_INFO("[绕障规划] 方向:%s | 路点1 GPS(%.6f,%.6f) | 路点2 GPS(%.6f,%.6f)", avoid_direction == -1 ? "左" : "右", abs_lon_1, abs_lat_1, abs_lon_2, abs_lat_2); } // ======== 相对坐标转GPS绝对坐标 ======== void rtk_relative_to_gps(double rel_x, double rel_y, double cur_heading, double cur_lon, double cur_lat, double* dest_lon, double* dest_lat) { double Navi_rad = cur_heading * deg_rad; // 逆向旋转矩阵:从车体坐标系转回地理坐标系 float k1 = cos(Navi_rad); float k2 = sin(Navi_rad); float k3 = -sin(Navi_rad); float k4 = cos(Navi_rad); // 地理坐标增量 double delta_x = rel_x * k1 + rel_y * k3; // 东向增量 double delta_y = rel_x * k2 + rel_y * k4; // 北向增量 // 转换为GPS坐标增量 double delta_lon = delta_x / (deg_rad * R_LONT); double delta_lat = delta_y / (deg_rad * R_LATI); *dest_lon = cur_lon + delta_lon; *dest_lat = cur_lat + delta_lat; LOG_INFO("[相对转GPS] 相对(%.2f,%.2f) -> GPS增量(%.8f,%.8f) -> 目标(%.6f,%.6f)", rel_x, rel_y, delta_lon, delta_lat, *dest_lon, *dest_lat); } // ======== 路点到达判断 ======== // 返回值:1=到达 0=未到达 -1=RTK信号丢失(需要停车) int waypointReached(const Waypoint& target) { // 验证RTK信号质量 auto now = system_clock::now(); duration time_since_last = now - last_rtk_time; if (g_rtk.reliability != 0 && time_since_last <= rtk_timeout) { // RTK信号良好:使用绝对坐标判断 double distance = ntzx_GPS_length(g_rtk.lon, g_rtk.lat, target.lon, target.lat); LOG_INFO("[路点判断] RTK信号良好 | 当前GPS(%.6f,%.6f) | 目标GPS(%.6f,%.6f) | 距离: %.2f m | 容差: %.2f m", g_rtk.lon, g_rtk.lat, target.lon, target.lat, distance, waypoint_tolerance_); return distance < waypoint_tolerance_ ? 1 : 0; } else { // RTK信号丢失:无法安全判断 if (time_since_last > rtk_timeout) { LOG_ERROR("[路点判断] RTK超时(%.2fs),信号丢失,停车退出绕障!", time_since_last.count()); } else { LOG_ERROR("[路点判断] RTK信号差(可靠性=%d),停车退出绕障!", g_rtk.reliability); } return -1; } } // ======== 路点跟踪执行 ======== void executeWaypointTracking() { if (current_waypoint_idx_ >= (int)avoidance_waypoints_.size()) { avoiding_obstacle_ = false; current_waypoint_idx_ = 0; avoidance_waypoints_.clear(); state_machine_->setState(StateMachine::NORMAL); LOG_INFO("[绕障完成] 所有路点跟踪完毕,恢复全局规划控制"); return; } Waypoint& target = avoidance_waypoints_[current_waypoint_idx_]; // 计算目标方向角: float target_angle = calculate_the_angle(target.x, target.y); state_machine_->publish_angle = target_angle; state_machine_->publish_speed = target.speed; LOG_INFO("[路点跟踪] 路点%d/%d | 相对坐标(%.2f,%.2f) | 目标方向: %.2f度", current_waypoint_idx_ + 1, (int)avoidance_waypoints_.size(), target.x, target.y, target_angle); // 检查路点到达情况 int reached = waypointReached(target); if (reached == -1) { // RTK信号丢失,立即停车并退出绕障 state_machine_->publish_speed = 0; state_machine_->publish_angle = 0.0f; state_machine_->setState(StateMachine::WAITING); avoiding_obstacle_ = false; current_waypoint_idx_ = 0; avoidance_waypoints_.clear(); LOG_ERROR("[绕障中止] RTK信号丢失,停车并退出绕障!"); return; } else if (reached == 1) { // 已到达路点,切换到下一个 current_waypoint_idx_++; if (current_waypoint_idx_ < (int)avoidance_waypoints_.size()) { state_machine_->setState(StateMachine::PARALLEL_MOVE); LOG_INFO("[路点跟踪] 已到达路点%d,切换到路点%d", current_waypoint_idx_, current_waypoint_idx_ + 1); } else { avoiding_obstacle_ = false; current_waypoint_idx_ = 0; avoidance_waypoints_.clear(); state_machine_->setState(StateMachine::NORMAL); LOG_INFO("[绕障完成] 所有路点跟踪完毕,恢复全局规划控制"); return; } } else { // 未到达路点,继续前往 state_machine_->setState(StateMachine::LATERAL_SHIFT); } // 安全检查:前方必停区有障碍物则立即停车 if (state_machine_->obstacle_analysis.has_front_critical) { state_machine_->publish_speed = 0; state_machine_->publish_angle = 0.0f; state_machine_->setState(StateMachine::WAITING); LOG_WARN("[绕障安全] 路点跟踪中检测到前方必停区障碍物,立即停车"); // 立即发布停车指令(带刹车) publishControlCommand(true); avoiding_obstacle_ = false; current_waypoint_idx_ = 0; avoidance_waypoints_.clear(); return; } } // ======== 可绕障判断 ======== bool canAvoidObstacle() const { if (state_machine_->obstacle_analysis.obstacle_width <= 0 || state_machine_->obstacle_analysis.obstacle_width > avoid_able_width_) { LOG_INFO("[绕障判断] 障碍物宽度%d栅格,超过可绕最大宽度%d栅格,不可绕", state_machine_->obstacle_analysis.obstacle_width, avoid_able_width_); return false; } bool left_ok = state_machine_->obstacle_analysis.free_space_left >= min_free_space_; bool right_ok = state_machine_->obstacle_analysis.free_space_right >= min_free_space_; LOG_INFO("[绕障判断] 左侧空闲%d栅格,右侧空闲%d栅格,最小需求%d栅格 | 左可绕:%s,右可绕:%s", state_machine_->obstacle_analysis.free_space_left, state_machine_->obstacle_analysis.free_space_right, min_free_space_, left_ok ? "是" : "否", right_ok ? "是" : "否"); return left_ok || right_ok; } // ======== 绕障方向选择 ======== int selectOptimalAvoidDirection() const { if (state_machine_->obstacle_analysis.free_space_left > state_machine_->obstacle_analysis.free_space_right) return -1; else if (state_machine_->obstacle_analysis.free_space_right > state_machine_->obstacle_analysis.free_space_left) return 1; else return (pl_x_ > 0) ? 1 : -1; } // ======== 更新障碍物分析 ======== void updateObstacleAnalysis() { state_machine_->obstacle_analysis.has_front_critical = obstacle_in_front_; state_machine_->obstacle_analysis.has_front_area = obstacle_in_front_area_; state_machine_->obstacle_analysis.has_left_critical = obstacle_in_left_; state_machine_->obstacle_analysis.has_right_critical = obstacle_in_right_; state_machine_->obstacle_analysis.obstacle_distance = (obstacle_max_x_ > 0) ? obstacle_max_x_ : -1; state_machine_->obstacle_analysis.left_edge = obstacle_left_edge_; state_machine_->obstacle_analysis.right_edge = obstacle_right_edge_; state_machine_->obstacle_analysis.free_space_left = free_space_left_; state_machine_->obstacle_analysis.free_space_right = free_space_right_; if (obstacle_left_edge_ != -1 && obstacle_right_edge_ != -1) { state_machine_->obstacle_analysis.obstacle_width = obstacle_right_edge_ - obstacle_left_edge_ + 1; } LOG_INFO("[障碍物分析] 距离:%d栅格 | 宽度:%d栅格 | 左边缘:%d | 右边缘:%d", state_machine_->obstacle_analysis.obstacle_distance, state_machine_->obstacle_analysis.obstacle_width, state_machine_->obstacle_analysis.left_edge, state_machine_->obstacle_analysis.right_edge); } // ======== 紧急停车执行 ======== bool executeEmergencyStop() { if (!enable_obstacle_stop_) return false; // 检查栅格数据新鲜度(超过500ms认为数据过期) auto now = node_clock_->now(); auto grid_age = (now - last_grid_time_).seconds(); if (grid_age > 0.5) { LOG_WARN("[紧急停车] 栅格数据过期(%.3fs),执行安全停车!", grid_age); state_machine_->publish_speed = 0; state_machine_->publish_angle = 0.0f; state_machine_->setState(StateMachine::WAITING); return true; } if (state_machine_->obstacle_analysis.has_front_critical) { state_machine_->publish_speed = 0; state_machine_->publish_angle = 0.0f; state_machine_->setState(StateMachine::WAITING); LOG_WARN("[紧急停车] 前方必停区检测到障碍物,执行紧急停车"); return true; } return false; } // ======== 定时器回调(主逻辑) ======== void timer_callback() { // 更新障碍物分析 updateObstacleAnalysis(); // 开始清扫任务 if (is_start) { // 紧急停车优先级最高 if (executeEmergencyStop()) { publishControlCommand(true); // 紧急停车使用刹车 return; } // PL速度为0,停车 if (pl_speed_ == 0) { state_machine_->publish_speed = 0; state_machine_->publish_angle = 0; LOG_INFO("PL速度为0,已停车"); publishControlCommand(); return; } // 若之前处于WAITING状态,且现在没有障碍物且RTK信号良好,恢复到NORMAL状态 auto now = system_clock::now(); duration time_since_last_rtk = now - last_rtk_time; bool rtk_signal_good = (g_rtk.reliability != 0 && time_since_last_rtk <= rtk_timeout); if (state_machine_->getCurrentState() == StateMachine::WAITING && !state_machine_->obstacle_analysis.has_front_critical && rtk_signal_good) { state_machine_->setState(StateMachine::NORMAL); LOG_INFO("[状态恢复] 障碍物已消失且RTK信号良好,恢复正常行驶状态"); } // 绕障逻辑 if (enable_obstacle_avoid_) { if (avoiding_obstacle_) { // 正在绕障,执行路点跟踪 executeWaypointTracking(); } else if (state_machine_->obstacle_analysis.has_front_area && canAvoidObstacle()) { // 需要开始绕障 int avoid_dir = selectOptimalAvoidDirection(); planAvoidanceWaypoints(avoid_dir); LOG_INFO("[启动绕障] 开始%s侧绕障", avoid_dir == -1 ? "左" : "右"); } else if (state_machine_->getCurrentState() != StateMachine::NORMAL) { // 无需绕障,恢复正常状态 state_machine_->setState(StateMachine::NORMAL); } } // 正常行驶逻辑 if (state_machine_->getCurrentState() == StateMachine::NORMAL) { state_machine_->publish_speed = 800; state_machine_->publish_angle = calculate_the_angle(pl_x_, pl_y_); } // 发布控制指令 publishControlCommand(); } } // ======== 发布控制指令 ======== void publishControlCommand(bool emergency_brake = false) { auto message = sweeper_interfaces::msg::McCtrl(); message.sweep = true; message.brake = emergency_brake ? 1 : 0; // 紧急停车时启用刹车 message.gear = 2; message.angle_speed = 800; // 转速限制 message.rpm = std::clamp(state_machine_->publish_speed, 0, 800); message.angle = std::clamp(state_machine_->publish_angle, -50.0f, 50.0f); pub_mc->publish(message); if (emergency_brake) { LOG_WARN("[控制发布] 紧急刹车!状态:%s | 转速:%d | 转向角度:%.1f° | 刹车:%d", state_machine_->getStateString().c_str(), message.rpm, message.angle, message.brake); } else { LOG_INFO("[控制发布] 状态:%s | 转速:%d | 转向角度:%.1f°", state_machine_->getStateString().c_str(), message.rpm, message.angle); } } }; // ======== 主函数 ======== int main(int argc, char** argv) { logger::Logger::Init("fu", "./nodes_log"); rclcpp::init(argc, argv); auto node = std::make_shared("fu_node"); rclcpp::spin(node); rclcpp::shutdown(); logger::Logger::Shutdown(); return 0; }