混合A*源码解读(c++)

基于ros中通过slam建立的栅格地图,使用混合A*进行路径规划。
首先是run_hybrid_astar.cpp:

#include "hybrid_a_star/hybrid_a_star_flow.h"
#include "3rd/backward.hpp"
#include <ros/ros.h>namespace backward {
backward::SignalHandling sh;
}int main(int argc, char **argv) {ros::init(argc, argv, "run_hybrid_astar");ros::NodeHandle node_handle("~");HybridAStarFlow kinodynamic_astar_flow(node_handle);ros::Rate rate(10);while (ros::ok()) {kinodynamic_astar_flow.Run();ros::spinOnce();rate.sleep();}ros::shutdown();return 0;
}

创建了一个实例kinodynamic_astar_flow,以固定频率运行算法并处理ROS事件。
hybrid_a_star.cpp:

#include "hybrid_a_star/hybrid_a_star.h"
#include "hybrid_a_star/display_tools.h"
#include "hybrid_a_star/timer.h"
#include "hybrid_a_star/trajectory_optimizer.h"#include <iostream>
// 参数分别为:steering_angle: 最大转向角度,转化为弧度使用。
// steering_angle_discrete_num: 转向角度的离散数量,控制转向角度的分辨率。
// segment_length: 从一个节点到另一个节点的路径段长度。
// segment_length_discrete_num: 路径段长度的离散数量,影响路径的平滑度和搜索的精度。
// wheel_base: 车辆的轴距,用于计算车辆转弯时的动态约束。
// steering_penalty, reversing_penalty, steering_change_penalty: 分别对应转向、倒车和转向变化的惩罚因子,用于在成本计算中对这些行为进行惩罚,以生成更符合实际驾驶情况的路径。
// shot_distance: 射线距离,用于在距离目标状态一定范围内时,采用解析解法(Reeds-Shepp路径)直接连接起点和终点。
HybridAStar::HybridAStar(double steering_angle, int steering_angle_discrete_num, double segment_length,int segment_length_discrete_num, double wheel_base, double steering_penalty,double reversing_penalty, double steering_change_penalty, double shot_distance,int grid_size_phi) {wheel_base_ = wheel_base;segment_length_ = segment_length;steering_radian_ = steering_angle * M_PI / 180.0; // angle to radiansteering_discrete_num_ = steering_angle_discrete_num;steering_radian_step_size_ = steering_radian_ / steering_discrete_num_;move_step_size_ = segment_length / segment_length_discrete_num;segment_length_discrete_num_ = static_cast<int>(segment_length_discrete_num);steering_penalty_ = steering_penalty;steering_change_penalty_ = steering_change_penalty;reversing_penalty_ = reversing_penalty;shot_distance_ = shot_distance;CHECK_EQ(static_cast<float>(segment_length_discrete_num_ * move_step_size_), static_cast<float>(segment_length_))<< "The segment length must be divisible by the step size. segment_length: "<< segment_length_ << " | step_size: " << move_step_size_;// rs曲线的计算rs_path_ptr_ = std::make_shared<RSPath>(wheel_base_ / std::tan(steering_radian_));tie_breaker_ = 1.0 + 1e-3;STATE_GRID_SIZE_PHI_ = grid_size_phi;ANGULAR_RESOLUTION_ = 360.0 / STATE_GRID_SIZE_PHI_ * M_PI / 180.0;
}HybridAStar::~HybridAStar() {ReleaseMemory();
}// Init 函数:
// 初始化地图参数,包括地图的边界和分辨率。
// 初始化状态节点地图,用于记录搜索过程中的每个状态。
// 状态节点图和栅格图,需要根据接收到的地图信息进行重新处理
void HybridAStar::Init(double x_lower, double x_upper, double y_lower, double y_upper,double state_grid_resolution, double map_grid_resolution) {SetVehicleShape(4.7, 2.0, 1.3); // 车辆参数,给定车辆长度宽度和后轴到车位的距离来定义。map_x_lower_ = x_lower;map_x_upper_ = x_upper;map_y_lower_ = y_lower;map_y_upper_ = y_upper;STATE_GRID_RESOLUTION_ = state_grid_resolution;MAP_GRID_RESOLUTION_ = map_grid_resolution;STATE_GRID_SIZE_X_ = std::floor((map_x_upper_ - map_x_lower_) / STATE_GRID_RESOLUTION_);STATE_GRID_SIZE_Y_ = std::floor((map_y_upper_ - map_y_lower_) / STATE_GRID_RESOLUTION_);MAP_GRID_SIZE_X_ = std::floor((map_x_upper_ - map_x_lower_) / MAP_GRID_RESOLUTION_);MAP_GRID_SIZE_Y_ = std::floor((map_y_upper_ - map_y_lower_) / MAP_GRID_RESOLUTION_);if (map_data_) {delete[] map_data_;map_data_ = nullptr;}map_data_ = new uint8_t[MAP_GRID_SIZE_X_ * MAP_GRID_SIZE_Y_];if (state_node_map_) {for (int i = 0; i < STATE_GRID_SIZE_X_; ++i) {if (state_node_map_[i] == nullptr)continue;for (int j = 0; j < STATE_GRID_SIZE_Y_; ++j) {if (state_node_map_[i][j] == nullptr)continue;for (int k = 0; k < STATE_GRID_SIZE_PHI_; ++k) {if (state_node_map_[i][j][k] != nullptr) {delete state_node_map_[i][j][k];state_node_map_[i][j][k] = nullptr;}}delete[] state_node_map_[i][j];state_node_map_[i][j] = nullptr;}delete[] state_node_map_[i];state_node_map_[i] = nullptr;}delete[] state_node_map_;state_node_map_ = nullptr;}state_node_map_ = new StateNode::Ptr **[STATE_GRID_SIZE_X_];for (int i = 0; i < STATE_GRID_SIZE_X_; ++i) {state_node_map_[i] = new StateNode::Ptr *[STATE_GRID_SIZE_Y_];for (int j = 0; j < STATE_GRID_SIZE_Y_; ++j) {state_node_map_[i][j] = new StateNode::Ptr[STATE_GRID_SIZE_PHI_];for (int k = 0; k < STATE_GRID_SIZE_PHI_; ++k) {state_node_map_[i][j][k] = nullptr;}}}
}// LineCheck 是一个低级函数,用于执行直线上的障碍物检测,通常被CheckCollision调用。
inline bool HybridAStar::LineCheck(double x0, double y0, double x1, double y1) {bool steep = (std::abs(y1 - y0) > std::abs(x1 - x0));if (steep) {std::swap(x0, y0);std::swap(y1, x1);}if (x0 > x1) {std::swap(x0, x1);std::swap(y0, y1);}auto delta_x = x1 - x0;auto delta_y = std::abs(y1 - y0);auto delta_error = delta_y / delta_x;decltype(delta_x) error = 0;decltype(delta_x) y_step;auto yk = y0;if (y0 < y1) {y_step = 1;} else {y_step = -1;}auto N = static_cast<unsigned int>(x1 - x0);for (unsigned int i = 0; i < N; ++i) {if (steep) {if (HasObstacle(Vec2i(yk, x0 + i * 1.0))|| BeyondBoundary(Vec2d(yk * MAP_GRID_RESOLUTION_,(x0 + i) * MAP_GRID_RESOLUTION_))) {return false;}} else {if (HasObstacle(Vec2i(x0 + i * 1.0, yk))|| BeyondBoundary(Vec2d((x0 + i) * MAP_GRID_RESOLUTION_,yk * MAP_GRID_RESOLUTION_))) {return false;}}error += delta_error;if (error >= 0.5) {yk += y_step;error = error - 1.0;}}return true;
}// CheckCollision 用于检测车辆沿着给定路径是否与障碍物发生碰撞。
bool HybridAStar::CheckCollision(const double &x, const double &y, const double &theta) {Timer timer;Mat2d R;R << std::cos(theta), -std::sin(theta),std::sin(theta), std::cos(theta);MatXd transformed_vehicle_shape;transformed_vehicle_shape.resize(8, 1);for (unsigned int i = 0; i < 4u; ++i) {transformed_vehicle_shape.block<2, 1>(i * 2, 0)= R * vehicle_shape_.block<2, 1>(i * 2, 0) + Vec2d(x, y);}Vec2i transformed_pt_index_0 = Coordinate2MapGridIndex(transformed_vehicle_shape.block<2, 1>(0, 0));Vec2i transformed_pt_index_1 = Coordinate2MapGridIndex(transformed_vehicle_shape.block<2, 1>(2, 0));Vec2i transformed_pt_index_2 = Coordinate2MapGridIndex(transformed_vehicle_shape.block<2, 1>(4, 0));Vec2i transformed_pt_index_3 = Coordinate2MapGridIndex(transformed_vehicle_shape.block<2, 1>(6, 0));double y1, y0, x1, x0;// pt1 -> pt0x0 = static_cast<double>(transformed_pt_index_0.x());y0 = static_cast<double>(transformed_pt_index_0.y());x1 = static_cast<double>(transformed_pt_index_1.x());y1 = static_cast<double>(transformed_pt_index_1.y());if (!LineCheck(x1, y1, x0, y0)) {return false;}// pt2 -> pt1x0 = static_cast<double>(transformed_pt_index_1.x());y0 = static_cast<double>(transformed_pt_index_1.y());x1 = static_cast<double>(transformed_pt_index_2.x());y1 = static_cast<double>(transformed_pt_index_2.y());if (!LineCheck(x1, y1, x0, y0)) {return false;}// pt3 -> pt2x0 = static_cast<double>(transformed_pt_index_2.x());y0 = static_cast<double>(transformed_pt_index_2.y());x1 = static_cast<double>(transformed_pt_index_3.x());y1 = static_cast<double>(transformed_pt_index_3.y());if (!LineCheck(x1, y1, x0, y0)) {return false;}// pt0 -> pt3x0 = static_cast<double>(transformed_pt_index_0.x());y0 = static_cast<double>(transformed_pt_index_0.y());x1 = static_cast<double>(transformed_pt_index_3.x());y1 = static_cast<double>(transformed_pt_index_3.y());if (!LineCheck(x0, y0, x1, y1)) {return false;}check_collision_use_time += timer.End();num_check_collision++;return true;
}bool HybridAStar::HasObstacle(const int grid_index_x, const int grid_index_y) const {return (grid_index_x >= 0 && grid_index_x < MAP_GRID_SIZE_X_&& grid_index_y >= 0 && grid_index_y < MAP_GRID_SIZE_Y_&& (map_data_[grid_index_y * MAP_GRID_SIZE_X_ + grid_index_x] == 1));
}bool HybridAStar::HasObstacle(const Vec2i &grid_index) const {int grid_index_x = grid_index[0];int grid_index_y = grid_index[1];return (grid_index_x >= 0 && grid_index_x < MAP_GRID_SIZE_X_&& grid_index_y >= 0 && grid_index_y < MAP_GRID_SIZE_Y_&& (map_data_[grid_index_y * MAP_GRID_SIZE_X_ + grid_index_x] == 1));
}void HybridAStar::SetObstacle(unsigned int x, unsigned int y) {if (x < 0u || x > static_cast<unsigned int>(MAP_GRID_SIZE_X_)|| y < 0u || y > static_cast<unsigned int>(MAP_GRID_SIZE_Y_)) {return;}map_data_[x + y * MAP_GRID_SIZE_X_] = 1;
}void HybridAStar::SetObstacle(const double pt_x, const double pt_y) {if (pt_x < map_x_lower_ || pt_x > map_x_upper_ ||pt_y < map_y_lower_ || pt_y > map_y_upper_) {return;}int grid_index_x = static_cast<int>((pt_x - map_x_lower_) / MAP_GRID_RESOLUTION_);int grid_index_y = static_cast<int>((pt_y - map_y_lower_) / MAP_GRID_RESOLUTION_);map_data_[grid_index_x + grid_index_y * MAP_GRID_SIZE_X_] = 1;
}// 定义车辆形状,用于碰撞检测。车辆被假设为矩形,通过给定车辆长度、宽度和后轴到车尾的距离来定义。
void HybridAStar::SetVehicleShape(double length, double width, double rear_axle_dist) {vehicle_shape_.resize(8);vehicle_shape_.block<2, 1>(0, 0) = Vec2d(-rear_axle_dist, width / 2);vehicle_shape_.block<2, 1>(2, 0) = Vec2d(length - rear_axle_dist, width / 2);vehicle_shape_.block<2, 1>(4, 0) = Vec2d(length - rear_axle_dist, -width / 2);vehicle_shape_.block<2, 1>(6, 0) = Vec2d(-rear_axle_dist, -width / 2);const double step_size = move_step_size_;const auto N_length = static_cast<unsigned int>(length / step_size);const auto N_width = static_cast<unsigned int> (width / step_size);vehicle_shape_discrete_.resize(2, (N_length + N_width) * 2u);const Vec2d edge_0_normalized = (vehicle_shape_.block<2, 1>(2, 0)- vehicle_shape_.block<2, 1>(0, 0)).normalized();for (unsigned int i = 0; i < N_length; ++i) {vehicle_shape_discrete_.block<2, 1>(0, i + N_length)= vehicle_shape_.block<2, 1>(4, 0) - edge_0_normalized * i * step_size;vehicle_shape_discrete_.block<2, 1>(0, i)= vehicle_shape_.block<2, 1>(0, 0) + edge_0_normalized * i * step_size;}const Vec2d edge_1_normalized = (vehicle_shape_.block<2, 1>(4, 0)- vehicle_shape_.block<2, 1>(2, 0)).normalized();for (unsigned int i = 0; i < N_width; ++i) {vehicle_shape_discrete_.block<2, 1>(0, (2 * N_length) + i)= vehicle_shape_.block<2, 1>(2, 0) + edge_1_normalized * i * step_size;vehicle_shape_discrete_.block<2, 1>(0, (2 * N_length) + i + N_width)= vehicle_shape_.block<2, 1>(6, 0) - edge_1_normalized * i * step_size;}
}__attribute__((unused)) Vec2d HybridAStar::CoordinateRounding(const Vec2d &pt) const {return MapGridIndex2Coordinate(Coordinate2MapGridIndex(pt));
}Vec2d HybridAStar::MapGridIndex2Coordinate(const Vec2i &grid_index) const {Vec2d pt;pt.x() = ((double) grid_index[0] + 0.5) * MAP_GRID_RESOLUTION_ + map_x_lower_;pt.y() = ((double) grid_index[1] + 0.5) * MAP_GRID_RESOLUTION_ + map_y_lower_;return pt;
}Vec3i HybridAStar::State2Index(const Vec3d &state) const {Vec3i index;index[0] = std::min(std::max(int((state[0] - map_x_lower_) / STATE_GRID_RESOLUTION_), 0), STATE_GRID_SIZE_X_ - 1);index[1] = std::min(std::max(int((state[1] - map_y_lower_) / STATE_GRID_RESOLUTION_), 0), STATE_GRID_SIZE_Y_ - 1);index[2] = std::min(std::max(int((state[2] - (-M_PI)) / ANGULAR_RESOLUTION_), 0), STATE_GRID_SIZE_PHI_ - 1);return index;
}Vec2i HybridAStar::Coordinate2MapGridIndex(const Vec2d &pt) const {Vec2i grid_index;grid_index[0] = int((pt[0] - map_x_lower_) / MAP_GRID_RESOLUTION_);grid_index[1] = int((pt[1] - map_y_lower_) / MAP_GRID_RESOLUTION_);return grid_index;
}// 生成当前节点的所有可能邻居节点,并检查它们是否可行(没有碰撞,没有越界)。
void HybridAStar::GetNeighborNodes(const StateNode::Ptr &curr_node_ptr,std::vector<StateNode::Ptr> &neighbor_nodes) {neighbor_nodes.clear();for (int i = -steering_discrete_num_; i <= steering_discrete_num_; ++i) {VectorVec3d intermediate_state;bool has_obstacle = false;double x = curr_node_ptr->state_.x();double y = curr_node_ptr->state_.y();double theta = curr_node_ptr->state_.z();const double phi = i * steering_radian_step_size_;// forwardfor (int j = 1; j <= segment_length_discrete_num_; j++) {DynamicModel(move_step_size_, phi, x, y, theta);intermediate_state.emplace_back(Vec3d(x, y, theta));if (!CheckCollision(x, y, theta)) {has_obstacle = true;break;}}Vec3i grid_index = State2Index(intermediate_state.back());if (!BeyondBoundary(intermediate_state.back().head(2)) && !has_obstacle) {auto neighbor_forward_node_ptr = new StateNode(grid_index);neighbor_forward_node_ptr->intermediate_states_ = intermediate_state;neighbor_forward_node_ptr->state_ = intermediate_state.back();neighbor_forward_node_ptr->steering_grade_ = i;neighbor_forward_node_ptr->direction_ = StateNode::FORWARD;neighbor_nodes.push_back(neighbor_forward_node_ptr);}// backwardhas_obstacle = false;intermediate_state.clear();x = curr_node_ptr->state_.x();y = curr_node_ptr->state_.y();theta = curr_node_ptr->state_.z();for (int j = 1; j <= segment_length_discrete_num_; j++) {DynamicModel(-move_step_size_, phi, x, y, theta);intermediate_state.emplace_back(Vec3d(x, y, theta));if (!CheckCollision(x, y, theta)) {has_obstacle = true;break;}}if (!BeyondBoundary(intermediate_state.back().head(2)) && !has_obstacle) {grid_index = State2Index(intermediate_state.back());auto neighbor_backward_node_ptr = new StateNode(grid_index);neighbor_backward_node_ptr->intermediate_states_ = intermediate_state;neighbor_backward_node_ptr->state_ = intermediate_state.back();neighbor_backward_node_ptr->steering_grade_ = i;neighbor_backward_node_ptr->direction_ = StateNode::BACKWARD;neighbor_nodes.push_back(neighbor_backward_node_ptr);}}
}// 用于根据车辆动力学模型(如简化的自行车模型)更新车辆状态。
void HybridAStar::DynamicModel(const double &step_size, const double &phi,double &x, double &y, double &theta) const {x = x + step_size * std::cos(theta);y = y + step_size * std::sin(theta);theta = Mod2Pi(theta + step_size / wheel_base_ * std::tan(phi));
}double HybridAStar::Mod2Pi(const double &x) {double v = fmod(x, 2 * M_PI);if (v < -M_PI) {v += 2.0 * M_PI;} else if (v > M_PI) {v -= 2.0 * M_PI;}return v;
}bool HybridAStar::BeyondBoundary(const Vec2d &pt) const {return pt.x() < map_x_lower_ || pt.x() > map_x_upper_ || pt.y() < map_y_lower_ || pt.y() > map_y_upper_;
}// ComputeG 和 ComputeH 函数:
// 分别计算从起始节点到当前节点的实际成本(g成本)和从当前节点到目标节点的启发式成本(h成本)。
// 这两个成本用于评估节点的总成本(f成本 = g成本 + h成本)。
double HybridAStar::ComputeH(const StateNode::Ptr &current_node_ptr,const StateNode::Ptr &terminal_node_ptr) {double h;// L2
//    h = (current_node_ptr->state_.head(2) - terminal_node_ptr->state_.head(2)).norm();// L1h = (current_node_ptr->state_.head(2) - terminal_node_ptr->state_.head(2)).lpNorm<1>();if (h < 3.0 * shot_distance_) {h = rs_path_ptr_->Distance(current_node_ptr->state_.x(), current_node_ptr->state_.y(),current_node_ptr->state_.z(),terminal_node_ptr->state_.x(), terminal_node_ptr->state_.y(),terminal_node_ptr->state_.z());}return h;
}double HybridAStar::ComputeG(const StateNode::Ptr &current_node_ptr,const StateNode::Ptr &neighbor_node_ptr) const {double g;if (neighbor_node_ptr->direction_ == StateNode::FORWARD) {if (neighbor_node_ptr->steering_grade_ != current_node_ptr->steering_grade_) {if (neighbor_node_ptr->steering_grade_ == 0) {g = segment_length_ * steering_change_penalty_;} else {g = segment_length_ * steering_change_penalty_ * steering_penalty_;}} else {if (neighbor_node_ptr->steering_grade_ == 0) {g = segment_length_;} else {g = segment_length_ * steering_penalty_;}}} else {if (neighbor_node_ptr->steering_grade_ != current_node_ptr->steering_grade_) {if (neighbor_node_ptr->steering_grade_ == 0) {g = segment_length_ * steering_change_penalty_ * reversing_penalty_;} else {g = segment_length_ * steering_change_penalty_ * steering_penalty_ * reversing_penalty_;}} else {if (neighbor_node_ptr->steering_grade_ == 0) {g = segment_length_ * reversing_penalty_;} else {g = segment_length_ * steering_penalty_ * reversing_penalty_;}}}return g;
}// Search 函数:
// 实现混合A*算法的主要搜索逻辑。
// 输入起始状态和目标状态,输出是否找到路径。
// 使用优先队列(基于f成本的多重映射)管理开放集,以保证总是首先扩展最有希望的节点。
bool HybridAStar::Search(const Vec3d &start_state, const Vec3d &goal_state) {Timer search_used_time;double neighbor_time = 0.0, compute_h_time = 0.0, compute_g_time = 0.0;const Vec3i start_grid_index = State2Index(start_state);const Vec3i goal_grid_index = State2Index(goal_state);auto goal_node_ptr = new StateNode(goal_grid_index);goal_node_ptr->state_ = goal_state;goal_node_ptr->direction_ = StateNode::NO;goal_node_ptr->steering_grade_ = 0;auto start_node_ptr = new StateNode(start_grid_index);start_node_ptr->state_ = start_state;start_node_ptr->steering_grade_ = 0;start_node_ptr->direction_ = StateNode::NO;start_node_ptr->node_status_ = StateNode::IN_OPENSET;start_node_ptr->intermediate_states_.emplace_back(start_state);start_node_ptr->g_cost_ = 0.0;start_node_ptr->f_cost_ = ComputeH(start_node_ptr, goal_node_ptr);state_node_map_[start_grid_index.x()][start_grid_index.y()][start_grid_index.z()] = start_node_ptr;state_node_map_[goal_grid_index.x()][goal_grid_index.y()][goal_grid_index.z()] = goal_node_ptr;openset_.clear();openset_.insert(std::make_pair(0, start_node_ptr));std::vector<StateNode::Ptr> neighbor_nodes_ptr;StateNode::Ptr current_node_ptr;StateNode::Ptr neighbor_node_ptr;int count = 0;while (!openset_.empty()) {current_node_ptr = openset_.begin()->second;current_node_ptr->node_status_ = StateNode::IN_CLOSESET;openset_.erase(openset_.begin());if ((current_node_ptr->state_.head(2) - goal_node_ptr->state_.head(2)).norm() <= shot_distance_) {double rs_length = 0.0;if (AnalyticExpansions(current_node_ptr, goal_node_ptr, rs_length)) {terminal_node_ptr_ = goal_node_ptr;StateNode::Ptr grid_node_ptr = terminal_node_ptr_->parent_node_;while (grid_node_ptr != nullptr) {grid_node_ptr = grid_node_ptr->parent_node_;path_length_ = path_length_ + segment_length_;}path_length_ = path_length_ - segment_length_ + rs_length;std::cout << "ComputeH use time(ms): " << compute_h_time << std::endl;std::cout << "check collision use time(ms): " << check_collision_use_time << std::endl;std::cout << "GetNeighborNodes use time(ms): " << neighbor_time << std::endl;std::cout << "average time of check collision(ms): "<< check_collision_use_time / num_check_collision<< std::endl;ROS_INFO("\033[1;32m --> Time in Hybrid A star is %f ms, path length: %f  \033[0m\n",search_used_time.End(), path_length_);check_collision_use_time = 0.0;num_check_collision = 0.0;return true;}}Timer timer_get_neighbor;GetNeighborNodes(current_node_ptr, neighbor_nodes_ptr);neighbor_time = neighbor_time + timer_get_neighbor.End();for (unsigned int i = 0; i < neighbor_nodes_ptr.size(); ++i) {neighbor_node_ptr = neighbor_nodes_ptr[i];Timer timer_compute_g;const double neighbor_edge_cost = ComputeG(current_node_ptr, neighbor_node_ptr);compute_g_time = compute_g_time + timer_get_neighbor.End();Timer timer_compute_h;const double current_h = ComputeH(current_node_ptr, goal_node_ptr) * tie_breaker_;compute_h_time = compute_h_time + timer_compute_h.End();const Vec3i &index = neighbor_node_ptr->grid_index_;if (state_node_map_[index.x()][index.y()][index.z()] == nullptr) {neighbor_node_ptr->g_cost_ = current_node_ptr->g_cost_ + neighbor_edge_cost;neighbor_node_ptr->parent_node_ = current_node_ptr;neighbor_node_ptr->node_status_ = StateNode::IN_OPENSET;neighbor_node_ptr->f_cost_ = neighbor_node_ptr->g_cost_ + current_h;openset_.insert(std::make_pair(neighbor_node_ptr->f_cost_, neighbor_node_ptr));state_node_map_[index.x()][index.y()][index.z()] = neighbor_node_ptr;continue;} else if (state_node_map_[index.x()][index.y()][index.z()]->node_status_ == StateNode::IN_OPENSET) {double g_cost_temp = current_node_ptr->g_cost_ + neighbor_edge_cost;if (state_node_map_[index.x()][index.y()][index.z()]->g_cost_ > g_cost_temp) {neighbor_node_ptr->g_cost_ = g_cost_temp;neighbor_node_ptr->f_cost_ = g_cost_temp + current_h;neighbor_node_ptr->parent_node_ = current_node_ptr;neighbor_node_ptr->node_status_ = StateNode::IN_OPENSET;/// TODO: This will cause a memory leak//delete state_node_map_[index.x()][index.y()][index.z()];state_node_map_[index.x()][index.y()][index.z()] = neighbor_node_ptr;} else {delete neighbor_node_ptr;}continue;} else if (state_node_map_[index.x()][index.y()][index.z()]->node_status_ == StateNode::IN_CLOSESET) {delete neighbor_node_ptr;continue;}}count++;if (count > 50000000) {ROS_WARN("Exceeded the number of iterations, the search failed");return false;}}return false;
}VectorVec4d HybridAStar::GetSearchedTree() {VectorVec4d tree;Vec4d point_pair;visited_node_number_ = 0;for (int i = 0; i < STATE_GRID_SIZE_X_; ++i) {for (int j = 0; j < STATE_GRID_SIZE_Y_; ++j) {for (int k = 0; k < STATE_GRID_SIZE_PHI_; ++k) {if (state_node_map_[i][j][k] == nullptr || state_node_map_[i][j][k]->parent_node_ == nullptr) {continue;}const unsigned int number_states = state_node_map_[i][j][k]->intermediate_states_.size() - 1;for (unsigned int l = 0; l < number_states; ++l) {point_pair.head(2) = state_node_map_[i][j][k]->intermediate_states_[l].head(2);point_pair.tail(2) = state_node_map_[i][j][k]->intermediate_states_[l + 1].head(2);tree.emplace_back(point_pair);}point_pair.head(2) = state_node_map_[i][j][k]->intermediate_states_[0].head(2);point_pair.tail(2) = state_node_map_[i][j][k]->parent_node_->state_.head(2);tree.emplace_back(point_pair);visited_node_number_++;}}}return tree;
}// 清理动态分配的内存,避免内存泄漏。
void HybridAStar::ReleaseMemory() {if (map_data_ != nullptr) {delete[] map_data_;map_data_ = nullptr;}if (state_node_map_) {for (int i = 0; i < STATE_GRID_SIZE_X_; ++i) {if (state_node_map_[i] == nullptr)continue;for (int j = 0; j < STATE_GRID_SIZE_Y_; ++j) {if (state_node_map_[i][j] == nullptr)continue;for (int k = 0; k < STATE_GRID_SIZE_PHI_; ++k) {if (state_node_map_[i][j][k] != nullptr) {delete state_node_map_[i][j][k];state_node_map_[i][j][k] = nullptr;}}delete[] state_node_map_[i][j];state_node_map_[i][j] = nullptr;}delete[] state_node_map_[i];state_node_map_[i] = nullptr;}delete[] state_node_map_;state_node_map_ = nullptr;}terminal_node_ptr_ = nullptr;
}__attribute__((unused)) double HybridAStar::GetPathLength() const {return path_length_;
}VectorVec3d HybridAStar::GetPath() const {VectorVec3d path;std::vector<StateNode::Ptr> temp_nodes;StateNode::Ptr state_grid_node_ptr = terminal_node_ptr_;while (state_grid_node_ptr != nullptr) {temp_nodes.emplace_back(state_grid_node_ptr);state_grid_node_ptr = state_grid_node_ptr->parent_node_;}std::reverse(temp_nodes.begin(), temp_nodes.end());for (const auto &node: temp_nodes) {path.insert(path.end(), node->intermediate_states_.begin(),node->intermediate_states_.end());}return path;
}void HybridAStar::Reset() {if (state_node_map_) {for (int i = 0; i < STATE_GRID_SIZE_X_; ++i) {if (state_node_map_[i] == nullptr)continue;for (int j = 0; j < STATE_GRID_SIZE_Y_; ++j) {if (state_node_map_[i][j] == nullptr)continue;for (int k = 0; k < STATE_GRID_SIZE_PHI_; ++k) {if (state_node_map_[i][j][k] != nullptr) {delete state_node_map_[i][j][k];state_node_map_[i][j][k] = nullptr;}}}}}path_length_ = 0.0;terminal_node_ptr_ = nullptr;
}bool HybridAStar::AnalyticExpansions(const StateNode::Ptr &current_node_ptr,const StateNode::Ptr &goal_node_ptr, double &length) {VectorVec3d rs_path_poses = rs_path_ptr_->GetRSPath(current_node_ptr->state_,goal_node_ptr->state_,move_step_size_, length);for (const auto &pose: rs_path_poses)if (BeyondBoundary(pose.head(2)) || !CheckCollision(pose.x(), pose.y(), pose.z())) {return false;};goal_node_ptr->intermediate_states_ = rs_path_poses;goal_node_ptr->parent_node_ = current_node_ptr;auto begin = goal_node_ptr->intermediate_states_.begin();goal_node_ptr->intermediate_states_.erase(begin);return true;
}

这里面首先定义了构造函数HybridAStar:
steering_angle:最大的转向角度
steering_angle_distance_num:转向角度的离散数量,控制转向角度的分辨率的。
segment_length:一个节点到另一个节点的路径段长度。
segment_length_discrete_num:路径离散长度的离散数量,影响路径平滑度和搜索的精度。
wheel_base:轴距,用于计算转弯的动态约束。
steering_penalty,reversing_penalty,steering_change_panalty,转向,倒车和转向变化的惩罚因子
shot_distance:射线距离,用于在距离目标状态一定范围内时,采用解析法(RS路径)直接连接起点和终点

下一个重要的就是hybrid_a_star_flow.cpp:

#include "hybrid_a_star/hybrid_a_star_flow.h"#include <nav_msgs/Path.h>
#include <visualization_msgs/Marker.h>
#include <visualization_msgs/MarkerArray.h>
#include <tf/transform_datatypes.h>
#include <tf/transform_broadcaster.h>double Mod2Pi(const double &x) {double v = fmod(x, 2 * M_PI);if (v < -M_PI) {v += 2.0 * M_PI;} else if (v > M_PI) {v -= 2.0 * M_PI;}return v;
}HybridAStarFlow::HybridAStarFlow(ros::NodeHandle &nh) {double steering_angle = nh.param("planner/steering_angle", 10);int steering_angle_discrete_num = nh.param("planner/steering_angle_discrete_num", 1);double wheel_base = nh.param("planner/wheel_base", 1.0);double segment_length = nh.param("planner/segment_length", 1.6);int segment_length_discrete_num = nh.param("planner/segment_length_discrete_num", 8);double steering_penalty = nh.param("planner/steering_penalty", 1.05);double steering_change_penalty = nh.param("planner/steering_change_penalty", 1.5);double reversing_penalty = nh.param("planner/reversing_penalty", 2.0);double shot_distance = nh.param("planner/shot_distance", 5.0);// std::make_shared是什么?kinodynamic_astar_searcher_ptr_ = std::make_shared<HybridAStar>(steering_angle, steering_angle_discrete_num, segment_length, segment_length_discrete_num, wheel_base,steering_penalty, reversing_penalty, steering_change_penalty, shot_distance);costmap_sub_ptr_ = std::make_shared<CostMapSubscriber>(nh, "/map", 1);init_pose_sub_ptr_ = std::make_shared<InitPoseSubscriber2D>(nh, "/initialpose", 1);goal_pose_sub_ptr_ = std::make_shared<GoalPoseSubscriber2D>(nh, "/move_base_simple/goal", 1);path_pub_ = nh.advertise<nav_msgs::Path>("searched_path", 1);searched_tree_pub_ = nh.advertise<visualization_msgs::Marker>("searched_tree", 1);vehicle_path_pub_ = nh.advertise<visualization_msgs::MarkerArray>("vehicle_path", 1);has_map_ = false;
}void HybridAStarFlow::Run() {ReadData();  // 从订阅的话题中读取成本地图、初始位置、目标位置,并存储到对应的队列中。// 如果没有地图数据,则直接返回。如果有地图数据,但地图还未初始化,则使用最新的成本地图初始化混合A*搜索器,并设置障碍物。// if (!has_map_) {//     if (costmap_deque_.empty()) {//         return;//     }//     current_costmap_ptr_ = costmap_deque_.front();//     costmap_deque_.pop_front();//     const double map_resolution = 0.2;//     kinodynamic_astar_searcher_ptr_->Init(//             current_costmap_ptr_->info.origin.position.x,//             1.0 * current_costmap_ptr_->info.width * current_costmap_ptr_->info.resolution,//             current_costmap_ptr_->info.origin.position.y,//             1.0 * current_costmap_ptr_->info.height * current_costmap_ptr_->info.resolution,//             current_costmap_ptr_->info.resolution,//             map_resolution//     );//     unsigned int map_w = std::floor(current_costmap_ptr_->info.width / map_resolution);//     unsigned int map_h = std::floor(current_costmap_ptr_->info.height / map_resolution);//     for (unsigned int w = 0; w < map_w; ++w) {//         for (unsigned int h = 0; h < map_h; ++h) {//             auto x = static_cast<unsigned int> ((w + 0.5) * map_resolution//                                                 / current_costmap_ptr_->info.resolution);//             auto y = static_cast<unsigned int> ((h + 0.5) * map_resolution//                                                 / current_costmap_ptr_->info.resolution);//             if (current_costmap_ptr_->data[y * current_costmap_ptr_->info.width + x]) {//                 kinodynamic_astar_searcher_ptr_->SetObstacle(w, h);//             }//         }//     }//     has_map_ = true;// }// costmap_deque_.clear();// test 3.8:  not finish
//     if (!has_map_) {
//     if (costmap_deque_.empty()) {
//         return;
//     }//     current_costmap_ptr_ = costmap_deque_.front();
//     costmap_deque_.pop_front();//     // 假定新的分辨率是原始分辨率的一半,例如0.05米/格
//     const double new_resolution = 0.02; // 新的更细分辨率
//     const double original_resolution = current_costmap_ptr_->info.resolution;
//     const double scale_factor = original_resolution / new_resolution; // 计算缩放因子//     // 使用新的分辨率初始化kinodynamic_astar_searcher_ptr_
//     kinodynamic_astar_searcher_ptr_->Init(
//             current_costmap_ptr_->info.origin.position.x,
//             1.0 * current_costmap_ptr_->info.width * original_resolution, // 保持物理尺寸不变
//             current_costmap_ptr_->info.origin.position.y,
//             1.0 * current_costmap_ptr_->info.height * original_resolution, // 保持物理尺寸不变
//             new_resolution, // 使用新的分辨率
//             new_resolution // 新的地图分辨率也应该是这个值
//     );//     unsigned int map_w = std::round(current_costmap_ptr_->info.width * scale_factor);
//     unsigned int map_h = std::round(current_costmap_ptr_->info.height * scale_factor);
//     for (unsigned int w = 0; w < map_w; ++w) {
//         for (unsigned int h = 0; h < map_h; ++h) {
//             auto x = static_cast<unsigned int> (w / scale_factor);
//             auto y = static_cast<unsigned int> (h / scale_factor);//             if (current_costmap_ptr_->data[y * current_costmap_ptr_->info.width + x]) {
//                 kinodynamic_astar_searcher_ptr_->SetObstacle(w, h);
//             }
//         }
//     }
//     has_map_ = true;
// }
// costmap_deque_.clear();// test 3.7_1:  if (!has_map_) {if (costmap_deque_.empty()) {return;}current_costmap_ptr_ = costmap_deque_.front();costmap_deque_.pop_front();double map_resolution = current_costmap_ptr_->info.resolution;kinodynamic_astar_searcher_ptr_->Init(current_costmap_ptr_->info.origin.position.x,1.0 * current_costmap_ptr_->info.width * map_resolution,current_costmap_ptr_->info.origin.position.y,1.0 * current_costmap_ptr_->info.height * map_resolution,map_resolution,map_resolution // 这里同样使用地图的实际分辨率);// 使用实际的分辨率计算映射的宽度和高度unsigned int map_w = current_costmap_ptr_->info.width;unsigned int map_h = current_costmap_ptr_->info.height;for (unsigned int w = 0; w < map_w; ++w) {for (unsigned int h = 0; h < map_h; ++h) {// 在这里,我们不再需要根据重新计算的分辨率调整索引// 直接使用原始索引if (current_costmap_ptr_->data[h * map_w + w]) {kinodynamic_astar_searcher_ptr_->SetObstacle(w, h);}}}has_map_ = true;}costmap_deque_.clear();// // test 3.7_2:  // // remap search grid // if (!has_map_) {//     if (costmap_deque_.empty()) {//         return;//     }//     current_costmap_ptr_ = costmap_deque_.front();//     costmap_deque_.pop_front();//     // const double map_resolution = 0.1;  // why not from /map //     double map_resolution = current_costmap_ptr_->info.resolution;//     kinodynamic_astar_searcher_ptr_->Init(//             current_costmap_ptr_->info.origin.position.x,//             1.0 * current_costmap_ptr_->info.width * current_costmap_ptr_->info.resolution,//             current_costmap_ptr_->info.origin.position.y,//             1.0 * current_costmap_ptr_->info.height * current_costmap_ptr_->info.resolution,//             current_costmap_ptr_->info.resolution,//             map_resolution//     );//     unsigned int map_w = std::floor(current_costmap_ptr_->info.width / map_resolution);//     unsigned int map_h = std::floor(current_costmap_ptr_->info.height / map_resolution);//     for (unsigned int w = 0; w < map_w; ++w) {//         for (unsigned int h = 0; h < map_h; ++h) {//             auto x = static_cast<unsigned int> ((w + 0.5) * map_resolution//                                                 / current_costmap_ptr_->info.resolution);//             auto y = static_cast<unsigned int> ((h + 0.5) * map_resolution//                                                 / current_costmap_ptr_->info.resolution);//             if (current_costmap_ptr_->data[y * current_costmap_ptr_->info.width + x]) {//                 kinodynamic_astar_searcher_ptr_->SetObstacle(w, h);//             }//         }//     }//     has_map_ = true;// }// costmap_deque_.clear();while (HasStartPose() && HasGoalPose()) {InitPoseData();double start_yaw = tf::getYaw(current_init_pose_ptr_->pose.pose.orientation);double goal_yaw = tf::getYaw(current_goal_pose_ptr_->pose.orientation);Vec3d start_state = Vec3d(current_init_pose_ptr_->pose.pose.position.x,current_init_pose_ptr_->pose.pose.position.y,start_yaw);Vec3d goal_state = Vec3d(current_goal_pose_ptr_->pose.position.x,current_goal_pose_ptr_->pose.position.y,goal_yaw);if (kinodynamic_astar_searcher_ptr_->Search(start_state, goal_state)) {auto path = kinodynamic_astar_searcher_ptr_->GetPath();PublishPath(path);PublishVehiclePath(path, 4.0, 2.0, 5u);PublishSearchedTree(kinodynamic_astar_searcher_ptr_->GetSearchedTree());nav_msgs::Path path_ros;geometry_msgs::PoseStamped pose_stamped;for (const auto &pose: path) {pose_stamped.header.frame_id = "world";pose_stamped.pose.position.x = pose.x();pose_stamped.pose.position.y = pose.y();pose_stamped.pose.position.z = 0.0;pose_stamped.pose.orientation = tf::createQuaternionMsgFromRollPitchYaw(0, 0, pose.z());path_ros.poses.emplace_back(pose_stamped);}path_ros.header.frame_id = "world";path_ros.header.stamp = ros::Time::now();static tf::TransformBroadcaster transform_broadcaster;for (const auto &pose: path_ros.poses) {tf::Transform transform;transform.setOrigin(tf::Vector3(pose.pose.position.x, pose.pose.position.y, 0.0));tf::Quaternion q;q.setX(pose.pose.orientation.x);q.setY(pose.pose.orientation.y);q.setZ(pose.pose.orientation.z);q.setW(pose.pose.orientation.w);transform.setRotation(q);transform_broadcaster.sendTransform(tf::StampedTransform(transform,ros::Time::now(), "world","ground_link"));ros::Duration(0.05).sleep();}}// debug
//        std::cout << "visited nodes: " << kinodynamic_astar_searcher_ptr_->GetVisitedNodesNumber() << std::endl;kinodynamic_astar_searcher_ptr_->Reset();}
}void HybridAStarFlow::ReadData() {costmap_sub_ptr_->ParseData(costmap_deque_);init_pose_sub_ptr_->ParseData(init_pose_deque_);goal_pose_sub_ptr_->ParseData(goal_pose_deque_);
}void HybridAStarFlow::InitPoseData() {current_init_pose_ptr_ = init_pose_deque_.front();init_pose_deque_.pop_front();current_goal_pose_ptr_ = goal_pose_deque_.front();goal_pose_deque_.pop_front();
}bool HybridAStarFlow::HasGoalPose() {return !goal_pose_deque_.empty();
}bool HybridAStarFlow::HasStartPose() {return !init_pose_deque_.empty();
}void HybridAStarFlow::PublishPath(const VectorVec3d &path) {nav_msgs::Path nav_path;geometry_msgs::PoseStamped pose_stamped;for (const auto &pose: path) {pose_stamped.header.frame_id = "world";pose_stamped.pose.position.x = pose.x();pose_stamped.pose.position.y = pose.y();pose_stamped.pose.position.z = 0.0;pose_stamped.pose.orientation = tf::createQuaternionMsgFromYaw(pose.z());nav_path.poses.emplace_back(pose_stamped);}nav_path.header.frame_id = "world";nav_path.header.stamp = timestamp_;path_pub_.publish(nav_path);
}void HybridAStarFlow::PublishVehiclePath(const VectorVec3d &path, double width,double length, unsigned int vehicle_interval = 5u) {visualization_msgs::MarkerArray vehicle_array;for (unsigned int i = 0; i < path.size(); i += vehicle_interval) {visualization_msgs::Marker vehicle;if (i == 0) {vehicle.action = 3;}vehicle.header.frame_id = "world";vehicle.header.stamp = ros::Time::now();vehicle.type = visualization_msgs::Marker::CUBE;vehicle.id = static_cast<int>(i / vehicle_interval);vehicle.scale.x = width;vehicle.scale.y = length;vehicle.scale.z = 0.01;vehicle.color.a = 0.1;vehicle.color.r = 1.0;vehicle.color.b = 0.0;vehicle.color.g = 0.0;vehicle.pose.position.x = path[i].x();vehicle.pose.position.y = path[i].y();vehicle.pose.position.z = 0.0;vehicle.pose.orientation = tf::createQuaternionMsgFromYaw(path[i].z());vehicle_array.markers.emplace_back(vehicle);}vehicle_path_pub_.publish(vehicle_array);
}void HybridAStarFlow::PublishSearchedTree(const VectorVec4d &searched_tree) {visualization_msgs::Marker tree_list;tree_list.header.frame_id = "world";tree_list.header.stamp = ros::Time::now();tree_list.type = visualization_msgs::Marker::LINE_LIST;tree_list.action = visualization_msgs::Marker::ADD;tree_list.ns = "searched_tree";tree_list.scale.x = 0.02;tree_list.color.a = 1.0;tree_list.color.r = 0;tree_list.color.g = 0;tree_list.color.b = 0;tree_list.pose.orientation.w = 1.0;tree_list.pose.orientation.x = 0.0;tree_list.pose.orientation.y = 0.0;tree_list.pose.orientation.z = 0.0;geometry_msgs::Point point;for (const auto &i: searched_tree) {point.x = i.x();point.y = i.y();point.z = 0.0;tree_list.points.emplace_back(point);point.x = i.z();point.y = i.w();point.z = 0.0;tree_list.points.emplace_back(point);}searched_tree_pub_.publish(tree_list);
}

1.参数的含义如下:
steering_angle: 最大转向角度,转化为弧度使用。
steering_angle_discrete_num: 转向角度的离散数量,控制转向角度的分辨率。
segment_length: 从一个节点到另一个节点的路径段长度。
segment_length_discrete_num: 路径段长度的离散数量,影响路径的平滑度和搜索的精度。
wheel_base: 车辆的轴距,用于计算车辆转弯时的动态约束。
steering_penalty, reversing_penalty, steering_change_penalty: 分别对应转向、倒车和转向变化的惩罚因子,用于在成本计算中对这些行为进行惩罚,以生成更符合实际驾驶情况的路径。
shot_distance: 射线距离,用于在距离目标状态一定范围内时,采用解析解法(Reeds-Shepp路径)直接连接起点和终点。
添加:车辆参数(这是自己添加的,主要影响障碍物检测等)
vehicle_length
vehicle_width
rear_axle_to_back

2.源代码中的小bug:
unsigned int map_w = std::floor(current_costmap_ptr_->info.width / map_resolution);
unsigned int map_h = std::floor(current_costmap_ptr_->info.height / map_resolution);

------->
unsigned int map_w = std::floor(current_costmap_ptr_->info.width *current_costmap_ptr_->info.resolution / map_resolution);
unsigned int map_h = std::floor(current_costmap_ptr_->info.height *current_costmap_ptr_->info.resolution/ map_resolution);

std::make_shared被用于创建四个不同类型对象的共享指针:
kinodynamic_astar_searcher_ptr_ 是 HybridAStar 类型的共享指针,用于执行混合A*搜索算法。
hybrid的算法解读到这里基本就可以先使用了。

效果:
在这里插入图片描述
有人也对他进行了改进,一个是加到了ros导航里面,正好这几天准备好好学习一下。还有一个是优化了起点终点的设置逻辑,这个我应该要按照自己的来,调度系统要的应该就是一系列的途经点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/742308.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

带钢切割控制液压比例阀放大器

比例阀控制器放大器放大板技术是电液比例控制系统中的重要组成部分&#xff0c;它负责对比例阀进行精确控制&#xff0c;以实现对液压系统中流量、压力等参数的精细调节。可以实现对液压流量或压力的精确控制&#xff0c;从而使系统以更高的精度和更快的响应速度执行各种操作。…

以102flowers数据集为例训练ResNet50模型

以102flowers数据集为例训练ResNet50模型 使用飞桨高阶API&#xff0c;使用最少的代码量&#xff0c;实现在102flowers数据集训练ResNet50模型。同时可以一条命令修改成Mnist、Cifar10、Cifar100等数据集&#xff0c;换成其它模型也是只需要一句话代码。 数据集介绍 102flowe…

Zoho Mail有微信小程序啦!从微信就能直接收发邮件

Zoho Mail有微信小程序啦&#xff01;从微信就能直接收发邮件。可实现&#xff1a;从微信直接查看邮件、撰写新邮件、回复邮件。对于那些想从手机访问Zoho Mail企业邮箱来收发邮件&#xff0c;但又不想下载Zoho Mail 的手机app来占用手机存储的用户来说&#xff0c;微信小程序实…

Celery知识

celery介绍 # celery 的概念&#xff1a; * 翻译过来是芹菜 * 官网&#xff1a;https://docs.celeryq.dev/en/stable/ # 是分布式的异步任务框架&#xff1a; 分布式&#xff1a;一个任务&#xff0c;拆成多个任务在不同机器上做 异步任务&#xff1a;后台执行…

【开源】SpringBoot框架开发软件学院思政案例库系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统管理员2.2 普通教师 三、系统展示四、核心代码4.1 查询思政案例4.2 审核思政案例4.3 查询思政课程4.4 思政案例点赞4.5 新增思政案例评语 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的软件学…

Mysql8.0.30数据data目录文件解释

数据库内存和磁盘架构 data目录展示 [rootDESKTOP-9ADRUGP data]# pwd /usr/local/software/mysql/3312/data [rootDESKTOP-9ADRUGP data]# ls -l total 96616 -rw-r----- 1 systemd-coredump input 56 Jul 24 2023 auto.cnf -rw-r----- 1 systemd-coredump input 30…

数据库基础理论知识

1.基本概念 数据(Data)&#xff1a;数据库存储的基本对象。数字、字符串、图形、图像、音频、视频等数据库(DB)&#xff1a;在计算机内&#xff0c;永久存储、有组织、可共享的数据集合数据库管理系统(DBMS)&#xff1a;管理数据库的系统软件数据库系统(DBS)&#xff1a;DBDBM…

浏览器的工作原理

从输入一个url到页面加载完成&#xff0c;中间都发生了什么&#xff1f; 参考原文地址 首先在浏览器地址栏输入一个地址并回车之后&#xff0c; 1. DNS查找 浏览器会进行DNS查找&#xff0c;把域名https://example.com转化为真实的IP地址10.29.33.xx&#xff0c;根据IP地址找…

linux驱动——中断

1.Cortex-A系列的中断的简介 中断的基本概念&#xff1a;(interrupt) 中断本质上是系统内部的异常机制,当中断产生之后&#xff0c;他会停下当前正在执行的任务&#xff0c;转而去做其他的事情,在停下当前正在执行的任务之前,要先入栈&#xff08;保护现场,其他的事情做完之后…

Mysql/Redis缓存一致性

如何保证MySQL和Redis的缓存一致。从理论到实战。总结6种来感受一下。 理论知识 不好的方案 1.先写MySQL&#xff0c;再写Redis 图解说明: 这是一幅时序图&#xff0c;描述请求的先后调用顺序&#xff1b; 黄色的线是请求A&#xff0c;黑色的线是请求B&#xff1b; 黄色的…

TYPE C模拟耳机POP音产生缘由

关于耳机插拔的POP音问题&#xff0c;小白在之前的文章中讲述过关于3.5mm耳机的POP音产生原因。其实这类插拔问题的POP音不仅仅存在于3.5mm耳机&#xff0c;就连现在主流的Type C模拟耳机的插拔也存在此问题&#xff0c;今天小白就来讲一讲这类耳机产生POP音的缘由。 耳机左右…

两个笔记本如何将一个笔记本作为另一个笔记本的拓展屏

需求是有两个笔记本&#xff0c;一个笔记本闲置&#xff0c;另一个笔记本是主力本。想将另一个闲置的笔记本连接到主力本上作为拓展屏使用。网上搜了好久&#xff0c;有一些人提到了&#xff0c;也有一些视频但是文章比较少。简单总结一下吧 上述需求有两种方式 第一种&#x…

浅谈Redis 的 保护模式(protected-mode)

今天在一台服务器上面部署了redis,发现始终无法用工具远程连接,项目里面是正常的,就是工具不行,防火墙也关闭了.折腾了一会才突然想起来,是不是触发了保护模式. 什么时候触发保护模式protected-mode: 同时满足以下两个: 1.bind未指定ip 2.未配置密码 解决方案: 编辑redis…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的交通标志识别系统详解(深度学习模型+UI界面代码+训练数据集)

摘要&#xff1a;本篇博客详细介绍了利用深度学习构建交通标志识别系统的过程&#xff0c;并提供了完整的实现代码。该系统采用了先进的YOLOv8算法&#xff0c;并与YOLOv7、YOLOv6、YOLOv5等早期版本进行了性能评估对比&#xff0c;分析了性能指标如mAP、F1 Score等。文章深入探…

计算机组成原理实验报告1 | 实验1.1 运算器实验(键盘方式)

本文整理自博主大学本科《计算机组成原理》课程自己完成的实验报告。 —— *实验环境为学校机房实验箱。 目录 一、实验目的 二、实验内容 三、实验步骤及实验结果 Ⅰ、单片机键盘操作方式实验 1、实验连线&#xff08;键盘实验&#xff09; 2、实验过程 四、实验结果的…

代码随想录-java-栈与队列总结

栈&#xff08;Stack&#xff09;&#xff1a;是只允许在一端进行插入或删除的线性表。栈是一种线性表&#xff0c;限定这种线性表只能在某一端进行插入和删除操作。进行操作的这一端称为栈顶。 队列&#xff08;Queue&#xff09;是只允许在一端进行插入操作&#xff0c;而在另…

Python使用FastAPI提供图片缩略图生成接口

使用pillow的thumbnail生成缩略图时&#xff0c;会保持原图的宽高比&#xff1b;使用的opencv的resize则不会 具体代码如下&#xff1a; #!/usr/bin/env python import re import sys from enum import Enum from io import BytesIO from pathlib import Path from typing im…

汇编课设——秒表2

1. 设计要求 基于 51 开发板,利用键盘作为按键输入,将数码管作为显示输出,实现电子秒表。 功能要求: (1)计时精度达到百分之一秒; (2)能按键记录下5次时间并通过按键回看 (3)设置时间,实现倒计时,时间到,数码管闪烁 10 次,并激发蜂鸣器,可通过按键解除。 2. 设计思…

思科网络中如何进行动态NAT配置

一、什么是动态NAT&#xff1f;动态NAT与静态NAT的区别是什么&#xff1f; &#xff08;1&#xff09;动态NAT&#xff08;Network Address Translation&#xff09;是一种网络地址转换技术&#xff0c;它会动态地将内部私有网络中的局域网IP地址映射为公共IP地址&#xff0c;…

Hack The Box-Codify

目录 信息收集 rustscan nmap dirsearch WEB 提权 get user get root 信息收集 rustscan ┌──(root㉿ru)-[~/kali/hackthebox] └─# rustscan -b 2250 10.10.11.239 --range0-65535 --ulimit4500 -- -A -sC .----. .-. .-. .----..---. .----. .---. .--. .-. …