【Apollo学习笔记】——规划模块TASK之RULE_BASED_STOP_DECIDER
文章目录
- 前言
- RULE_BASED_STOP_DECIDER相关配置
- RULE_BASED_STOP_DECIDER总体流程
- StopOnSidePass
- CheckClearDone
- CheckSidePassStop
- IsPerceptionBlocked
- IsClearToChangeLane
- CheckSidePassStop
- BuildStopDecision
- ELSE:涉及到的一些其他函数
- NormalizeAngle
- SelfRotate
- CheckLaneChangeUrgency
- AddPathEndStop
- 参考
前言
在Apollo星火计划学习笔记——Apollo路径规划算法原理与实践与【Apollo学习笔记】——Planning模块讲到……Stage::Process的PlanOnReferenceLine
函数会依次调用task_list中的TASK,本文将会继续以LaneFollow为例依次介绍其中的TASK部分究竟做了哪些工作。由于个人能力所限,文章可能有纰漏的地方,还请批评斧正。
在modules/planning/conf/scenario/lane_follow_config.pb.txt
配置文件中,我们可以看到LaneFollow所需要执行的所有task。
stage_config: {stage_type: LANE_FOLLOW_DEFAULT_STAGEenabled: truetask_type: LANE_CHANGE_DECIDERtask_type: PATH_REUSE_DECIDERtask_type: PATH_LANE_BORROW_DECIDERtask_type: PATH_BOUNDS_DECIDERtask_type: PIECEWISE_JERK_PATH_OPTIMIZERtask_type: PATH_ASSESSMENT_DECIDERtask_type: PATH_DECIDERtask_type: RULE_BASED_STOP_DECIDERtask_type: SPEED_BOUNDS_PRIORI_DECIDERtask_type: SPEED_HEURISTIC_OPTIMIZERtask_type: SPEED_DECIDERtask_type: SPEED_BOUNDS_FINAL_DECIDERtask_type: PIECEWISE_JERK_SPEED_OPTIMIZER# task_type: PIECEWISE_JERK_NONLINEAR_SPEED_OPTIMIZERtask_type: RSS_DECIDER
本文将继续介绍LaneFollow的第8个TASK——RULE_BASED_STOP_DECIDER
基于规则的停止决策是规划模块的任务,属于task中的decider类别。基于规则的停止决策根据一些规则来设置停止标志。
RULE_BASED_STOP_DECIDER相关配置
modules/planning/conf/planning_config.pb.txt
default_task_config: {task_type: RULE_BASED_STOP_DECIDERrule_based_stop_decider_config {max_adc_stop_speed: 0.5max_valid_stop_distance: 1.0search_beam_length: 20.0search_beam_radius_intensity: 0.08search_range: 3.14is_block_angle_threshold: 0.5}
}
modules/planning/proto/task_config.proto
// RuleBasedStopDeciderConfigmessage RuleBasedStopDeciderConfig {optional double max_adc_stop_speed = 1 [default = 0.3];optional double max_valid_stop_distance = 2 [default = 0.5];optional double search_beam_length = 3 [default = 5.0];optional double search_beam_radius_intensity = 4 [default = 0.08];optional double search_range = 5 [default = 3.14];optional double is_block_angle_threshold = 6 [default = 1.57];optional double approach_distance_for_lane_change = 10 [default = 80.0];optional double urgent_distance_for_lane_change = 11 [default = 50.0];
}
RULE_BASED_STOP_DECIDER总体流程
-
输入
apollo::common::Status RuleBasedStopDecider::Process(Frame *const frame, ReferenceLineInfo *const reference_line_info)
输入是frame和reference_line_info。 -
输出
输出保存到reference_line_info中。
代码流程及框架
Process中的代码流程如下图所示。
apollo::common::Status RuleBasedStopDecider::Process(Frame *const frame, ReferenceLineInfo *const reference_line_info) {// 1. Rule_based stop for side pass onto reverse laneStopOnSidePass(frame, reference_line_info);// 2. Rule_based stop for urgent lane changeif (FLAGS_enable_lane_change_urgency_checking) {CheckLaneChangeUrgency(frame);}// 3. Rule_based stop at path end positionAddPathEndStop(frame, reference_line_info);return Status::OK();
}
主要核心的函数就是StopOnSidePass
、CheckLaneChangeUrgency
以及AddPathEndStop
,接着分别对三者进行剖析。
StopOnSidePass
void RuleBasedStopDecider::StopOnSidePass(Frame *const frame, ReferenceLineInfo *const reference_line_info) {static bool check_clear;// 默认falsestatic common::PathPoint change_lane_stop_path_point;// 获取path dataconst PathData &path_data = reference_line_info->path_data();double stop_s_on_pathdata = 0.0;// 找到"self"类型的路径,returnif (path_data.path_label().find("self") != std::string::npos) {check_clear = false;change_lane_stop_path_point.Clear();return;}// CheckClearDone:Check if needed to check clear again for side pass// 如果check_clear为true,且CheckClearDone成功。设置check_clear为falseif (check_clear &&CheckClearDone(*reference_line_info, change_lane_stop_path_point)) {check_clear = false;}// CheckSidePassStop:Check if necessary to set stop fence used for nonscenario side pass// 如果check_clear为false,CheckSidePassStop为trueif (!check_clear &&CheckSidePassStop(path_data, *reference_line_info, &stop_s_on_pathdata)) {// 如果障碍物没有阻塞且可以换道,直接returnif (!LaneChangeDecider::IsPerceptionBlocked(*reference_line_info,rule_based_stop_decider_config_.search_beam_length(),rule_based_stop_decider_config_.search_beam_radius_intensity(),rule_based_stop_decider_config_.search_range(),rule_based_stop_decider_config_.is_block_angle_threshold()) &&LaneChangeDecider::IsClearToChangeLane(reference_line_info)) {return;}// 检查adc是否停在了stop fence前,否返回trueif (!CheckADCStop(path_data, *reference_line_info, stop_s_on_pathdata)) {// 设置stop fence,成功就执行 check_clear = true;if (!BuildSidePassStopFence(path_data, stop_s_on_pathdata,&change_lane_stop_path_point, frame,reference_line_info)) {AERROR << "Set side pass stop fail";}} else {if (LaneChangeDecider::IsClearToChangeLane(reference_line_info)) {check_clear = true;}}}
}
CheckClearDone
// Check if needed to check clear again for side pass
bool RuleBasedStopDecider::CheckClearDone(const ReferenceLineInfo &reference_line_info,const common::PathPoint &stop_point) {// 获取ADC的SL坐标const double adc_front_edge_s = reference_line_info.AdcSlBoundary().end_s();const double adc_back_edge_s = reference_line_info.AdcSlBoundary().start_s();const double adc_start_l = reference_line_info.AdcSlBoundary().start_l();const double adc_end_l = reference_line_info.AdcSlBoundary().end_l();double lane_left_width = 0.0;double lane_right_width = 0.0;reference_line_info.reference_line().GetLaneWidth((adc_front_edge_s + adc_back_edge_s) / 2.0, &lane_left_width,&lane_right_width);SLPoint stop_sl_point;// 获取停止点的SL坐标reference_line_info.reference_line().XYToSL(stop_point, &stop_sl_point);// use distance to last stop point to determine if needed to check clear// againif (adc_back_edge_s > stop_sl_point.s()) {if (adc_start_l > -lane_right_width || adc_end_l < lane_left_width) {return true;}}return false;
}
CheckSidePassStop
// @brief Check if necessary to set stop fence used for nonscenario side pass
bool RuleBasedStopDecider::CheckSidePassStop(const PathData &path_data, const ReferenceLineInfo &reference_line_info,double *stop_s_on_pathdata) {const std::vector<std::tuple<double, PathData::PathPointType, double>>&path_point_decision_guide = path_data.path_point_decision_guide();// 初始化类型PathData::PathPointType last_path_point_type =PathData::PathPointType::UNKNOWN;// 遍历 path_point_decision_guidefor (const auto &point_guide : path_point_decision_guide) {// 若上一点在车道内,这一点在逆行车道上if (last_path_point_type == PathData::PathPointType::IN_LANE &&std::get<1>(point_guide) ==PathData::PathPointType::OUT_ON_REVERSE_LANE) {*stop_s_on_pathdata = std::get<0>(point_guide);// Approximate the stop fence s based on the vehicle positionconst auto &vehicle_config =common::VehicleConfigHelper::Instance()->GetConfig();const double ego_front_to_center =vehicle_config.vehicle_param().front_edge_to_center();common::PathPoint stop_pathpoint;// 获取stop pointif (!path_data.GetPathPointWithRefS(*stop_s_on_pathdata,&stop_pathpoint)) {AERROR << "Can't get stop point on path data";return false;}const double ego_theta = stop_pathpoint.theta();Vec2d shift_vec{ego_front_to_center * std::cos(ego_theta),ego_front_to_center * std::sin(ego_theta)};// stop_fence的位置const Vec2d stop_fence_pose =shift_vec + Vec2d(stop_pathpoint.x(), stop_pathpoint.y());double stop_l_on_pathdata = 0.0;const auto &nearby_path = reference_line_info.reference_line().map_path();nearby_path.GetNearestPoint(stop_fence_pose, stop_s_on_pathdata,&stop_l_on_pathdata);return true;}last_path_point_type = std::get<1>(point_guide);}return false;
}
IsPerceptionBlocked
参数解释:
search_beam_length
扫描长度
search_beam_radius_intensity
扫描间隔
search_range
依据ADC中心的扫描范围
is_block_angle_threshold
筛选障碍物所占角度大小的阈值
bool LaneChangeDecider::IsPerceptionBlocked(const ReferenceLineInfo& reference_line_info,const double search_beam_length, const double search_beam_radius_intensity,const double search_range, const double is_block_angle_threshold) {// search_beam_length: 20.0 //is the length of scanning beam// search_beam_radius_intensity: 0.08 //is the resolution of scanning// search_range: 3.14 //is the scanning range centering at ADV heading// is_block_angle_threshold: 0.5 //is the threshold to tell how big a block angle range is perception blocking// 获取车辆状态、位置、航向角const auto& vehicle_state = reference_line_info.vehicle_state();const common::math::Vec2d adv_pos(vehicle_state.x(), vehicle_state.y());const double adv_heading = vehicle_state.heading();// 遍历障碍物for (auto* obstacle :reference_line_info.path_decision().obstacles().Items()) {// NormalizeAngle将给定的角度值规范化到一个特定的范围内(-π到π之间)double left_most_angle =common::math::NormalizeAngle(adv_heading + 0.5 * search_range);double right_most_angle =common::math::NormalizeAngle(adv_heading - 0.5 * search_range);bool right_most_found = false;// 跳过虚拟障碍物if (obstacle->IsVirtual()) {ADEBUG << "skip one virtual obstacle";continue;}// 获取障碍物多边形const auto& obstacle_polygon = obstacle->PerceptionPolygon();// 按角度进行搜索for (double search_angle = 0.0; search_angle < search_range;search_angle += search_beam_radius_intensity) {common::math::Vec2d search_beam_end(search_beam_length, 0.0);const double beam_heading = common::math::NormalizeAngle(adv_heading - 0.5 * search_range + search_angle);// search_beam_end绕adv_pos旋转beam_heading角度search_beam_end.SelfRotate(beam_heading);search_beam_end += adv_pos;// 构造线段common::math::LineSegment2d search_beam(adv_pos, search_beam_end);// 判断最右边界是否找到,并更新右边界角度if (!right_most_found && obstacle_polygon.HasOverlap(search_beam)) {right_most_found = true;right_most_angle = beam_heading;}// 如果最右边界已找到,且障碍物的感知多边形与搜索光束无重叠,则更新左边界角度并跳出循环。if (right_most_found && !obstacle_polygon.HasOverlap(search_beam)) {left_most_angle = beam_heading;break;}}// 如果最右边界未找到,则继续处理下一个障碍物。(说明该障碍物不在搜索范围内)if (!right_most_found) {// obstacle is not in search rangecontinue;}// 判断阈值,过滤掉小的障碍物if (std::fabs(common::math::NormalizeAngle(left_most_angle - right_most_angle)) > is_block_angle_threshold) {return true;}}return false;
}
IsClearToChangeLane
这个在【Apollo学习笔记】——规划模块TASK之LANE_CHANGE_DECIDER已经有过介绍。
CheckSidePassStop
// @brief Check if necessary to set stop fence used for nonscenario side pass
bool RuleBasedStopDecider::CheckSidePassStop(const PathData &path_data, const ReferenceLineInfo &reference_line_info,double *stop_s_on_pathdata) {const std::vector<std::tuple<double, PathData::PathPointType, double>>&path_point_decision_guide = path_data.path_point_decision_guide();// 初始化类型PathData::PathPointType last_path_point_type =PathData::PathPointType::UNKNOWN;// 遍历 path_point_decision_guidefor (const auto &point_guide : path_point_decision_guide) {// 若上一点在车道内,这一点在逆行车道上if (last_path_point_type == PathData::PathPointType::IN_LANE &&std::get<1>(point_guide) ==PathData::PathPointType::OUT_ON_REVERSE_LANE) {*stop_s_on_pathdata = std::get<0>(point_guide);// Approximate the stop fence s based on the vehicle positionconst auto &vehicle_config =common::VehicleConfigHelper::Instance()->GetConfig();const double ego_front_to_center =vehicle_config.vehicle_param().front_edge_to_center();common::PathPoint stop_pathpoint;// 获取stop pointif (!path_data.GetPathPointWithRefS(*stop_s_on_pathdata,&stop_pathpoint)) {AERROR << "Can't get stop point on path data";return false;}const double ego_theta = stop_pathpoint.theta();Vec2d shift_vec{ego_front_to_center * std::cos(ego_theta),ego_front_to_center * std::sin(ego_theta)};// stop_fence的位置const Vec2d stop_fence_pose =shift_vec + Vec2d(stop_pathpoint.x(), stop_pathpoint.y());double stop_l_on_pathdata = 0.0;const auto &nearby_path = reference_line_info.reference_line().map_path();nearby_path.GetNearestPoint(stop_fence_pose, stop_s_on_pathdata,&stop_l_on_pathdata);return true;}last_path_point_type = std::get<1>(point_guide);}return false;
}
BuildStopDecision
/** @brief: build virtual obstacle of stop wall, and add STOP decision*/
int BuildStopDecision(const std::string& stop_wall_id, const double stop_line_s,const double stop_distance,const StopReasonCode& stop_reason_code,const std::vector<std::string>& wait_for_obstacles,const std::string& decision_tag, Frame* const frame,ReferenceLineInfo* const reference_line_info) {CHECK_NOTNULL(frame);CHECK_NOTNULL(reference_line_info);// 检查停止线是否在参考线上const auto& reference_line = reference_line_info->reference_line();if (!WithinBound(0.0, reference_line.Length(), stop_line_s)) {AERROR << "stop_line_s[" << stop_line_s << "] is not on reference line";return 0;}// create virtual stop wallconst auto* obstacle =frame->CreateStopObstacle(reference_line_info, stop_wall_id, stop_line_s);if (!obstacle) {AERROR << "Failed to create obstacle [" << stop_wall_id << "]";return -1;}const Obstacle* stop_wall = reference_line_info->AddObstacle(obstacle);if (!stop_wall) {AERROR << "Failed to add obstacle[" << stop_wall_id << "]";return -1;}// build stop decisionconst double stop_s = stop_line_s - stop_distance;const auto& stop_point = reference_line.GetReferencePoint(stop_s);const double stop_heading =reference_line.GetReferencePoint(stop_s).heading();ObjectDecisionType stop;auto* stop_decision = stop.mutable_stop();stop_decision->set_reason_code(stop_reason_code);stop_decision->set_distance_s(-stop_distance);stop_decision->set_stop_heading(stop_heading);stop_decision->mutable_stop_point()->set_x(stop_point.x());stop_decision->mutable_stop_point()->set_y(stop_point.y());stop_decision->mutable_stop_point()->set_z(0.0);for (size_t i = 0; i < wait_for_obstacles.size(); ++i) {stop_decision->add_wait_for_obstacle(wait_for_obstacles[i]);}auto* path_decision = reference_line_info->path_decision();path_decision->AddLongitudinalDecision(decision_tag, stop_wall->Id(), stop);return 0;
}
ELSE:涉及到的一些其他函数
NormalizeAngle
NormalizeAngle
将给定的角度值规范化到一个特定的范围内(-π到π之间)
double NormalizeAngle(const double angle) {double a = std::fmod(angle + M_PI, 2.0 * M_PI);if (a < 0.0) {a += (2.0 * M_PI);}return a - M_PI;
}
SelfRotate
将向量绕原点旋转 a n g l e angle angle角。
void Vec2d::SelfRotate(const double angle) {double tmp_x = x_;x_ = x_ * cos(angle) - y_ * sin(angle);y_ = tmp_x * sin(angle) + y_ * cos(angle);
}
CheckLaneChangeUrgency
检查紧急换道,当FLAGS_enable_lane_change_urgency_checking
为true时,启用函数。
void RuleBasedStopDecider::CheckLaneChangeUrgency(Frame *const frame) {// 直接进入循环,检查每个reference_line_infofor (auto &reference_line_info : *frame->mutable_reference_line_info()) {// Check if the target lane is blocked or not// 1. 检查目标道路是否阻塞,如果在change lane path上,就跳过if (reference_line_info.IsChangeLanePath()) {is_clear_to_change_lane_ =LaneChangeDecider::IsClearToChangeLane(&reference_line_info);is_change_lane_planning_succeed_ =reference_line_info.Cost() < kStraightForwardLineCost;continue;}// If it's not in lane-change scenario || (target lane is not blocked &&// change lane planning succeed), skip// 2.如果不是换道的场景,或者(目标lane没有阻塞)并且换道规划成功,跳过if (frame->reference_line_info().size() <= 1 ||(is_clear_to_change_lane_ && is_change_lane_planning_succeed_)) {continue;}// When the target lane is blocked in change-lane case, check the urgency// Get the end point of current routingconst auto &route_end_waypoint =reference_line_info.Lanes().RouteEndWaypoint();// If can't get lane from the route's end waypoint, then skip// 3.在route的末端无法获得lane,跳过if (!route_end_waypoint.lane) {continue;}auto point = route_end_waypoint.lane->GetSmoothPoint(route_end_waypoint.s);auto *reference_line = reference_line_info.mutable_reference_line();common::SLPoint sl_point;// Project the end point to sl_point on current reference lane// 将当前参考线的点映射到frenet坐标系下if (reference_line->XYToSL(point, &sl_point) &&reference_line->IsOnLane(sl_point)) {// Check the distance from ADC to the end point of current routingdouble distance_to_passage_end =sl_point.s() - reference_line_info.AdcSlBoundary().end_s();// If ADC is still far from the end of routing, no need to stop, skip// 4. 如果adc距离routing终点较远,不需要停止,跳过if (distance_to_passage_end >rule_based_stop_decider_config_.approach_distance_for_lane_change()) {continue;}// In urgent case, set a temporary stop fence and wait to change lane// TODO(Jiaxuan Xu): replace the stop fence to more intelligent actions// 5.如果遇到紧急情况,设置临时的stop fence,等待换道const std::string stop_wall_id = "lane_change_stop";std::vector<std::string> wait_for_obstacles;util::BuildStopDecision(stop_wall_id, sl_point.s(),rule_based_stop_decider_config_.urgent_distance_for_lane_change(),StopReasonCode::STOP_REASON_LANE_CHANGE_URGENCY, wait_for_obstacles,"RuleBasedStopDecider", frame, &reference_line_info);}}
}
AddPathEndStop
void RuleBasedStopDecider::AddPathEndStop(Frame *const frame, ReferenceLineInfo *const reference_line_info) {// 路径不为空且起点到终点的距离不小于20mif (!reference_line_info->path_data().path_label().empty() &&reference_line_info->path_data().frenet_frame_path().back().s() -reference_line_info->path_data().frenet_frame_path().front().s() <FLAGS_short_path_length_threshold) { // FLAGS_short_path_length_threshold: Threshold for too short path length(20m)// 创建虚拟墙的IDconst std::string stop_wall_id =PATH_END_VO_ID_PREFIX + reference_line_info->path_data().path_label();std::vector<std::string> wait_for_obstacles;// 创建stop fenceutil::BuildStopDecision(stop_wall_id,reference_line_info->path_data().frenet_frame_path().back().s() - 5.0,0.0, StopReasonCode::STOP_REASON_REFERENCE_END, wait_for_obstacles,"RuleBasedStopDecider", frame, reference_line_info);}
}
参考
[1] 基于规则的停止决策
相关文章:

【Apollo学习笔记】——规划模块TASK之RULE_BASED_STOP_DECIDER
文章目录 前言RULE_BASED_STOP_DECIDER相关配置RULE_BASED_STOP_DECIDER总体流程StopOnSidePassCheckClearDoneCheckSidePassStopIsPerceptionBlockedIsClearToChangeLaneCheckSidePassStopBuildStopDecisionELSE:涉及到的一些其他函数NormalizeAngleSelfRotate CheckLaneChang…...

【SpringBoot】最基础的项目架构(SpringBoot+Mybatis-plus+lombok+knife4j+hutool)
汝之观览,吾之幸也! 从本文开始讲下项目中用到的一些框架和技术,最基本的框架使用的是SpringBoot(2.5.10)Mybatis-plus(3.5.3.2)lombok(1.18.28)knife4j(3.0.3)hutool(5.8.21),可以做到代码自动生成,满足最基本的增删查改。 一、新…...

RNN 单元:分析 GRU 方程与 LSTM,以及何时选择 RNN 而不是变压器
一、说明 深度学习往往感觉像是在雪山上找到自己的道路。拥有坚实的原则会让你对做出决定更有信心。我们都去过那里 在上一篇文章中,我们彻底介绍并检查了 LSTM 单元的各个方面。有人可能会争辩说,RNN方法已经过时了,研究它们是没有意义的。的…...

Linux音频了解
ALPHA I.MX6U 开发板支持音频,板上搭载了音频编解码芯片 WM8960,支持播放以及录音功能! 本章将会讨论如下主题内容。 ⚫ Linux 下 ALSA 框架概述; ⚫ alsa-lib 库介绍; ⚫ alsa-lib 库移植; ⚫ alsa-l…...

精心整理了优秀的GitHub开源项目,包含前端、后端、AI人工智能、游戏、黑客工具、网络工具、AI医疗等等,空闲的时候方便看看提高自己的视野
精心整理了优秀的GitHub开源项目,包含前端、后端、AI人工智能、游戏、黑客工具、网络工具、AI医疗等等,空闲的时候方便看看提高自己的视野。 刚开源就变成新星的 igl,不仅获得了 2k star,也能提高你开发游戏的效率,摆…...

Leetcode54螺旋矩阵
思路:用set记录走过的地方,记下走的方向,根据方向碰壁变换 class Solution:def spiralOrder(self, matrix: list[list[int]]) -> list[int]:max_rows len(matrix)max_cols len(matrix[0])block_nums max_cols * max_rowscount 1i 0j…...
element-plus 表格-方法、事件、属性的使用
记录element-plus 表格的使用。方法、事件、属性的使用。因为是vue3的方式用到了const install getCurrentInstance();才能获取表格的相关信息 没解决怎么获取选中的行的行号,采用自己记的方式实习的。 利用row-class-name"setRowClass"实现样式的简单…...

NVME Linux的查询命令-继续更新
NVME Linux的查询命令 查看NVMe设备 # nvme list 查看nvme controller 支持的一些特性 # nvme id-ctrl /dev/nvme0 查看设备smart log信息 # nvme smart-log /dev/nvme0 查看设备error 信息 # nvme error-log /dev/nvme0 设备的所有命名空间 # nvme list-ns /dev/nvmeX 检…...
pyqt5-自定义文本域1
快捷键支持: CTRL鼠标滚轮实现字体大小调整 支持复制当前行 剪切当前行 # 多行文本框 class TextEdit(QTextEdit):def __init__(self, parentNone):super().__init__(parent)self.setStyleSheet("background-color: #262626;color: #d0d0d0;")self.setFon…...

Go实现LogCollect:海量日志收集系统【上篇——LogAgent实现】
Go实现LogCollect:海量日志收集系统【上篇——LogAgent实现】 下篇:Go实现LogCollect:海量日志收集系统【下篇——开发LogTransfer】 项目架构图: 0 项目背景与方案选择 背景 当公司发展的越来越大,业务越来越复杂…...
MySQL (1)
目录 操作须知 数据类型 1 DDL 1.1 操作库 1.2 操作表 1.3 操作字段(ALTER TABLE 表名) 2 DML 3 DQL(见下章) 操作须知 ※ MySQL在windows环境不区分大小写,但在Linux环境严格区分大小写 ※ 不同的数据库可能存在同名的表,可以给表前加"数据库前缀" //例:…...

MR混合现实汽车维修情景实训教学演示
MR混合现实技术应用于汽车维修课堂中,能够赋予学生更加真实,逼真地学习环境,让学生在情景体验中不断提高自己的专业能力。 MR混合现实汽车维修情景实训教学演示具体体现在: 1. 虚拟维修指导:利用MR技术,可…...
ChatGPT在航空航天工程和太空探索中的潜在应用如何?
ChatGPT在航空航天工程和太空探索领域具有广泛的潜在应用。这些应用可以涵盖从设计和模拟到任务控制和数据分析的多个方面。本文将探讨ChatGPT在航空航天和太空探索中的各种可能应用,包括设计优化、任务规划、智能导航、卫星通信、数据分析和太空探测器运行。 ### …...

算法基础第三章
算法基础第三章 1、dfs(深度搜索)1.1、 递归回溯1.2、递归剪枝(剪枝就是判断接下来的递归都不会满足条件,直接回溯,不再继续往下无意义的递归) 2、bfs(广度搜索)2.1、最优路径(只适合于边权都相等的题) 3、…...
ElementUI浅尝辄止20:Pagination 分页
分页组件常见于管理系统的列表查询页面,数据量巨大时需要分页的操作。 当数据量过多时,使用分页分解数据。 1.如何使用? /*设置layout,表示需要显示的内容,用逗号分隔,布局元素会依次显示。prev表示上一页…...

Docker从认识到实践再到底层原理(二-1)|容器技术发展史+虚拟化容器概念和简介
前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…...
什么是大模型?1750亿、700GB的GPT大模型大在哪?
文章目录 什么是大模型?1750亿、700GB的GPT大模型大在哪? 什么是大模型? 在人工智能领域,模型是指一种对数据进行处理和分析的数学结构。模型越复杂,能够处理的数据量和处理的准确性都会得到提高。 随着人工智能技术…...
剑指 Offer 10- II. 青蛙跳台阶问题
剑指 Offer 10- II. 青蛙跳台阶问题 和 剑指 Offer 10- I. 斐波那契数列 很像,改一下初始值就行了。 方法一 class Solution {int mod (int) 1e9 7;public int numWays(int n) {if(n < 1) return 1;int[] dp new int[n 1];dp[1] 1;dp[2] 2;for(int i 3…...
oracle10和11功能说明比较
Oracle 10g/11g的特点和优势 首先,Oracle 10g/11g具有以下几个特点: 1. 可靠性和稳定性:Oracle 10g采用了多种技术来确保数据的可靠性和稳定性,如ACID事务处理和数据备份与恢复机制。它还提供了高可用性的解决方案,如…...

golang-bufio 缓冲写
1. 缓冲写 在阅读这篇博客之前,请先阅读上一篇:golang-bufio 缓冲读 // buffered output// Writer implements buffering for an io.Writer object. // If an error occurs writing to a Writer, no more data will be // accepted and all subsequent…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...

【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...