【Apollo学习笔记】——规划模块TASK之PATH_REUSE_DECIDER
文章目录
- 前言
- PATH_REUSE_DECIDER功能简介
- PATH_REUSE_DECIDER相关配置
- PATH_REUSE_DECIDER总体流程
- PATH_REUSE_DECIDER相关子函数
- IsCollisionFree
- TrimHistoryPath
- IsIgnoredBlockingObstacle和GetBlockingObstacleS
- Else
- 参考
前言
在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的第二个TASK——PATH_REUSE_DECIDER
PATH_REUSE_DECIDER功能简介

主要功能:检查路径是否可重用,提高帧间平顺性。
主要逻辑:主要判断是否可以重用上一帧规划的路径。若上一帧的路径未与障碍物发生碰撞,则可以重用,提高稳定性,节省计算量。若上一帧的规划出的路径发生碰撞,则重新规划路径。
PATH_REUSE_DECIDER相关配置
PATH_REUSE_DECIDER的相关配置集中在以下两个文件:modules/planning/conf/planning_config.pb.txt和modules/planning/conf/scenario/lane_follow_config.pb.txt
// modules/planning/conf/planning_config.pb.txt
default_task_config: {task_type: PATH_REUSE_DECIDERpath_reuse_decider_config {reuse_path: false}
}
// modules/planning/conf/scenario/lane_follow_config.pb.txttask_config: {task_type: PATH_REUSE_DECIDERpath_reuse_decider_config {reuse_path: false}}
可以看到,默认情况不启用PATH_REUSE,改为true后启用。
PATH_REUSE_DECIDER总体流程

接着来看一看PATH_REUSE_DECIDER的代码逻辑。代码路径:modules/planning/tasks/deciders/path_reuse_decider/path_reuse_decider.cc
主函数逻辑集中在Process函数中:
Status PathReuseDecider::Process(Frame* const frame,ReferenceLineInfo* const reference_line_info) {// Sanity checks.CHECK_NOTNULL(frame);CHECK_NOTNULL(reference_line_info);if (!Decider::config_.path_reuse_decider_config().reuse_path()) {ADEBUG << "skipping reusing path: conf";reference_line_info->set_path_reusable(false);return Status::OK();}// skip path reuse if not in LANE_FOLLOW_SCENARIOconst auto scenario_type = injector_->planning_context()->planning_status().scenario().scenario_type();if (scenario_type != ScenarioType::LANE_FOLLOW) {ADEBUG << "skipping reusing path: not in LANE_FOLLOW scenario";reference_line_info->set_path_reusable(false);return Status::OK();}// active path reuse during change_lane onlyauto* lane_change_status = injector_->planning_context()->mutable_planning_status()->mutable_change_lane();ADEBUG << "lane change status: " << lane_change_status->ShortDebugString();// skip path reuse if not in_change_laneif (lane_change_status->status() != ChangeLaneStatus::IN_CHANGE_LANE &&!FLAGS_enable_reuse_path_in_lane_follow) {ADEBUG << "skipping reusing path: not in lane_change";reference_line_info->set_path_reusable(false);return Status::OK();}// for hybrid model: skip reuse path for valid path referenceconst bool valid_model_output =reference_line_info->path_data().is_valid_path_reference();if (valid_model_output) {ADEBUG << "skipping reusing path: path reference is valid";reference_line_info->set_path_reusable(false);return Status::OK();}/*count total_path_ when in_change_lane && reuse_path*/++total_path_counter_;/*reuse path when in non_change_lane reference line oroptimization succeeded in change_lane reference line*/bool is_change_lane_path = reference_line_info->IsChangeLanePath();if (is_change_lane_path && !lane_change_status->is_current_opt_succeed()) {reference_line_info->set_path_reusable(false);ADEBUG << "reusable_path_counter[" << reusable_path_counter_<< "] total_path_counter[" << total_path_counter_ << "]";ADEBUG << "Stop reusing path when optimization failed on change lane path";return Status::OK();}// stop reusing current path:// 1. replan path// 2. collision// 3. failed to trim previous path// 4. speed optimization failed on previous pathbool speed_optimization_successful = false;const auto& history_frame = injector_->frame_history()->Latest();if (history_frame) {const auto history_trajectory_type =history_frame->reference_line_info().front().trajectory_type();speed_optimization_successful =(history_trajectory_type != ADCTrajectory::SPEED_FALLBACK);}// const auto history_trajectory_type = injector_->FrameHistory()s// ->Latest()// ->reference_line_info()// .front()// .trajectory_type();if (path_reusable_) {if (!frame->current_frame_planned_trajectory().is_replan() &&speed_optimization_successful && IsCollisionFree(reference_line_info) &&TrimHistoryPath(frame, reference_line_info)) {ADEBUG << "reuse path";++reusable_path_counter_; // count reusable path} else {// stop reuse pathADEBUG << "stop reuse path";path_reusable_ = false;}} else {// F -> Tauto* mutable_path_decider_status = injector_->planning_context()->mutable_planning_status()->mutable_path_decider();static constexpr int kWaitCycle = -2; // wait 2 cycleconst int front_static_obstacle_cycle_counter =mutable_path_decider_status->front_static_obstacle_cycle_counter();const bool ignore_blocking_obstacle =IsIgnoredBlockingObstacle(reference_line_info);ADEBUG << "counter[" << front_static_obstacle_cycle_counter<< "] IsIgnoredBlockingObstacle[" << ignore_blocking_obstacle << "]";// stop reusing current path:// 1. blocking obstacle disappeared or moving far away// 2. trimming successful// 3. no statical obstacle collision.if ((front_static_obstacle_cycle_counter <= kWaitCycle ||ignore_blocking_obstacle) &&speed_optimization_successful && IsCollisionFree(reference_line_info) &&TrimHistoryPath(frame, reference_line_info)) {// enable reuse pathADEBUG << "reuse path: front_blocking_obstacle ignorable";path_reusable_ = true;++reusable_path_counter_;}}reference_line_info->set_path_reusable(path_reusable_);ADEBUG << "reusable_path_counter[" << reusable_path_counter_<< "] total_path_counter[" << total_path_counter_ << "]";return Status::OK();
}
PATH_REUSE_DECIDER相关子函数
IsCollisionFree

bool PathReuseDecider::IsCollisionFree(ReferenceLineInfo* const reference_line_info) {const ReferenceLine& reference_line = reference_line_info->reference_line();static constexpr double kMinObstacleArea = 1e-4;const double kSBuffer = 0.5;static constexpr int kNumExtraTailBoundPoint = 21;static constexpr double kPathBoundsDeciderResolution = 0.5;// current vehicle sl positioncommon::SLPoint adc_position_sl;GetADCSLPoint(reference_line, &adc_position_sl);// current obstaclesstd::vector<Polygon2d> obstacle_polygons;for (auto obstacle :reference_line_info->path_decision()->obstacles().Items()) {// filtered all non-static objects and virtual obstacleif (!obstacle->IsStatic() || obstacle->IsVirtual()) {if (!obstacle->IsStatic()) {ADEBUG << "SPOT a dynamic obstacle";}if (obstacle->IsVirtual()) {ADEBUG << "SPOT a virtual obstacle";}continue;}const auto& obstacle_sl = obstacle->PerceptionSLBoundary();// Ignore obstacles behind ADCif ((obstacle_sl.end_s() < adc_position_sl.s() - kSBuffer) ||// Ignore too small obstacles.(obstacle_sl.end_s() - obstacle_sl.start_s()) *(obstacle_sl.end_l() - obstacle_sl.start_l()) <kMinObstacleArea) {continue;}obstacle_polygons.push_back(Polygon2d({Vec2d(obstacle_sl.start_s(), obstacle_sl.start_l()),Vec2d(obstacle_sl.start_s(), obstacle_sl.end_l()),Vec2d(obstacle_sl.end_s(), obstacle_sl.end_l()),Vec2d(obstacle_sl.end_s(), obstacle_sl.start_l())}));}if (obstacle_polygons.empty()) {return true;}const auto& history_frame = injector_->frame_history()->Latest();if (!history_frame) {return false;}const DiscretizedPath& history_path =history_frame->current_frame_planned_path();// path end point// 将上一段轨迹的终点投影到SL坐标系下common::SLPoint path_end_position_sl;common::math::Vec2d path_end_position = {history_path.back().x(),history_path.back().y()};reference_line.XYToSL(path_end_position, &path_end_position_sl);for (size_t i = 0; i < history_path.size(); ++i) {common::SLPoint path_position_sl;common::math::Vec2d path_position = {history_path[i].x(),history_path[i].y()};reference_line.XYToSL(path_position, &path_position_sl);if (path_end_position_sl.s() - path_position_sl.s() <=kNumExtraTailBoundPoint * kPathBoundsDeciderResolution) {break;}if (path_position_sl.s() < adc_position_sl.s() - kSBuffer) {continue;}const auto& vehicle_box =common::VehicleConfigHelper::Instance()->GetBoundingBox(history_path[i]);std::vector<Vec2d> ABCDpoints = vehicle_box.GetAllCorners();for (const auto& corner_point : ABCDpoints) {// For each corner point, project it onto reference_linecommon::SLPoint curr_point_sl;if (!reference_line.XYToSL(corner_point, &curr_point_sl)) {AERROR << "Failed to get the projection from point onto ""reference_line";return false;}auto curr_point = Vec2d(curr_point_sl.s(), curr_point_sl.l());// Check if it's in any polygon of other static obstacles.for (const auto& obstacle_polygon : obstacle_polygons) {if (obstacle_polygon.IsPointIn(curr_point)) {// for debugADEBUG << "s distance to end point:" << path_end_position_sl.s();ADEBUG << "s distance to end point:" << path_position_sl.s();ADEBUG << "[" << i << "]"<< ", history_path[i].x(): " << std::setprecision(9)<< history_path[i].x() << ", history_path[i].y()"<< std::setprecision(9) << history_path[i].y();ADEBUG << "collision:" << curr_point.x() << ", " << curr_point.y();Vec2d xy_point;reference_line.SLToXY(curr_point_sl, &xy_point);ADEBUG << "collision:" << xy_point.x() << ", " << xy_point.y();return false;}}}}return true;
}
TrimHistoryPath

bool PathReuseDecider::TrimHistoryPath(Frame* frame, ReferenceLineInfo* const reference_line_info) {const ReferenceLine& reference_line = reference_line_info->reference_line();const auto& history_frame = injector_->frame_history()->Latest();if (!history_frame) {ADEBUG << "no history frame";return false;}// 找到上一帧轨迹的起始点const common::TrajectoryPoint history_planning_start_point =history_frame->PlanningStartPoint();common::PathPoint history_init_path_point =history_planning_start_point.path_point();ADEBUG << "history_init_path_point x:[" << std::setprecision(9)<< history_init_path_point.x() << "], y["<< history_init_path_point.y() << "], s: ["<< history_init_path_point.s() << "]";// 当前周期规划的起点const common::TrajectoryPoint planning_start_point =frame->PlanningStartPoint();common::PathPoint init_path_point = planning_start_point.path_point();ADEBUG << "init_path_point x:[" << std::setprecision(9) << init_path_point.x()<< "], y[" << init_path_point.y() << "], s: [" << init_path_point.s()<< "]";const DiscretizedPath& history_path =history_frame->current_frame_planned_path();DiscretizedPath trimmed_path;// 获取自车的SL坐标common::SLPoint adc_position_sl; // current vehicle sl positionGetADCSLPoint(reference_line, &adc_position_sl);ADEBUG << "adc_position_sl.s(): " << adc_position_sl.s();size_t path_start_index = 0;for (size_t i = 0; i < history_path.size(); ++i) {// find previous init point// 找到上周期轨迹规划的起点索引if (history_path[i].s() > 0) {path_start_index = i;break;}}ADEBUG << "!!!path_start_index[" << path_start_index << "]";// get current s=0common::SLPoint init_path_position_sl;// 当前轨迹的起点reference_line.XYToSL(init_path_point, &init_path_position_sl);bool inserted_init_point = false;//匹配当前规划起点位置,裁剪该点之后的轨迹for (size_t i = path_start_index; i < history_path.size(); ++i) {common::SLPoint path_position_sl;common::math::Vec2d path_position = {history_path[i].x(),history_path[i].y()};reference_line.XYToSL(path_position, &path_position_sl);double updated_s = path_position_sl.s() - init_path_position_sl.s();// insert init pointif (updated_s > 0 && !inserted_init_point) {trimmed_path.emplace_back(init_path_point);trimmed_path.back().set_s(0);inserted_init_point = true;}trimmed_path.emplace_back(history_path[i]);// if (i < 50) {// ADEBUG << "path_point:[" << i << "]" << updated_s;// path_position_sl.s();// ADEBUG << std::setprecision(9) << "path_point:[" << i << "]"// << "x: [" << history_path[i].x() << "], y:[" <<// history_path[i].y()// << "]. s[" << history_path[i].s() << "]";// }trimmed_path.back().set_s(updated_s);}ADEBUG << "trimmed_path[0]: " << trimmed_path.front().s();ADEBUG << "[END] trimmed_path.size(): " << trimmed_path.size();// 检查裁剪出来的轨迹是不是过短if (!NotShortPath(trimmed_path)) {ADEBUG << "short path: " << trimmed_path.size();return false;}// set pathauto path_data = reference_line_info->mutable_path_data();ADEBUG << "previous path_data size: " << history_path.size();path_data->SetReferenceLine(&reference_line);ADEBUG << "previous path_data size: " << path_data->discretized_path().size();path_data->SetDiscretizedPath(DiscretizedPath(std::move(trimmed_path)));ADEBUG << "not short path: " << trimmed_path.size();ADEBUG << "current path size: "<< reference_line_info->path_data().discretized_path().size();return true;
}
IsIgnoredBlockingObstacle和GetBlockingObstacleS
前方堵塞的障碍物是否离开足够远的距离
bool PathReuseDecider::IsIgnoredBlockingObstacle(ReferenceLineInfo* const reference_line_info) {const ReferenceLine& reference_line = reference_line_info->reference_line();static constexpr double kSDistBuffer = 30.0; // meterstatic constexpr int kTimeBuffer = 3; // second// vehicle speeddouble adc_speed = injector_->vehicle_state()->linear_velocity();double final_s_buffer = std::max(kSDistBuffer, kTimeBuffer * adc_speed);// current vehicle s positioncommon::SLPoint adc_position_sl;GetADCSLPoint(reference_line, &adc_position_sl);// blocking obstacle start sdouble blocking_obstacle_start_s;if (GetBlockingObstacleS(reference_line_info, &blocking_obstacle_start_s) &&// distance to blocking obstacle(blocking_obstacle_start_s - adc_position_sl.s() > final_s_buffer)) {ADEBUG << "blocking obstacle distance: "<< blocking_obstacle_start_s - adc_position_sl.s();return true;} else {return false;}
}
bool PathReuseDecider::GetBlockingObstacleS(ReferenceLineInfo* const reference_line_info, double* blocking_obstacle_s) {auto* mutable_path_decider_status = injector_->planning_context()->mutable_planning_status()->mutable_path_decider();// get blocking obstacle ID (front_static_obstacle_id)const std::string& blocking_obstacle_ID =mutable_path_decider_status->front_static_obstacle_id();const IndexedList<std::string, Obstacle>& indexed_obstacles =reference_line_info->path_decision()->obstacles();const auto* blocking_obstacle = indexed_obstacles.Find(blocking_obstacle_ID);if (blocking_obstacle == nullptr) {return false;}const auto& obstacle_sl = blocking_obstacle->PerceptionSLBoundary();*blocking_obstacle_s = obstacle_sl.start_s();ADEBUG << "blocking obstacle distance: " << obstacle_sl.start_s();return true;
}
Else
在启用reuse之后,之后的task会有这样一段代码,用以跳过以下流程,沿用之前的path
// skip path_lane_borrow_decider if reused pathif (FLAGS_enable_skip_path_tasks && reference_line_info->path_reusable()) {// for debugAINFO << "skip due to reusing path";return Status::OK();}
参考
[1] Apollo Planning决策规划代码详细解析 (7): PathReuseDecider
[2] Apollo6.0 PathReuseDecider流程与代码解析
相关文章:
【Apollo学习笔记】——规划模块TASK之PATH_REUSE_DECIDER
文章目录 前言PATH_REUSE_DECIDER功能简介PATH_REUSE_DECIDER相关配置PATH_REUSE_DECIDER总体流程PATH_REUSE_DECIDER相关子函数IsCollisionFreeTrimHistoryPathIsIgnoredBlockingObstacle和GetBlockingObstacleS Else参考 前言 在Apollo星火计划学习笔记——Apollo路径规划算…...
框架分析(6)-Ruby on Rails
框架分析(6)-Ruby on Rails 专栏介绍Ruby on Rails核心概念以及组件讲解MVC架构模式约定优于配置强大的ORM支持自动化测试丰富的插件生态系统RESTful路由安全性总结 优缺点优点快速开发简单易学MVC架构强大的ORM支持大量的插件和Gem支持 缺点性能问题学习…...
LLMs NLP模型评估Model evaluation ROUGE and BLEU SCORE
在整个课程中,你看到过类似模型在这个任务上表现良好,或者这个微调模型在性能上相对于基础模型有显著提升等陈述。 这些陈述是什么意思?如何形式化你的微调模型在你起初的预训练模型上的性能改进?让我们探讨一些由大型语言模型开…...
BlazorServer中C#与JavaScript的相互调用
BlazorServer中C#与JavaScript的相互调用 前言: 虽然BlazorServer中推荐使用C#在razor页面中的替代JavaScript来完成逻辑的编写,但当需要使用第三方的javascript文件/组件里的内容时,则难免要在C#中调用其方法或对象。反之当你的(用到第…...
深入理解 MD5 消息摘要算法和在密码存储中的应用及安全隐患
MD5 算法相信很多开发人员都听说过, 一个最常见的使用到它的地方就是密码的存储. 当然, 很多人会说, 这个算法已经不太安全了, 确实如果你想更安全的保存密码, 则应该考虑其它更安全的算法, 不过这不属于此次讨论的主题. 什么是 MD5 MD5 是一种算法, MD5 中的 MD 代表 Message…...
python网络爬虫指南二:多线程网络爬虫、动态内容爬取(待续)
文章目录 一、多线程网络爬虫1.1 线程的基础内容、GIL1.2 创建线程的两种方式1.3 threading.Thread类1.4 线程常用方法和锁机制1.5 生产者-消费者模式1.5.1 生产者-消费者模式简介1.5.2 Condition 类协调线程 1.6 线程中的安全队列1.6 多线程爬取王者荣耀壁纸1.6.1 网页分析1.6…...
华为AirEgine9700S AC配置示例
Vlan97为管理Vlan <AirEgine9700S>dis cu Software Version V200R021C00SPC100 #sysname AirEgine9700S #http timeout 60http secure-server ssl-policy default_policyhttp secure-server server-source -i allhttp server enable #set np rss hash-mode 5-tuple # md…...
VUE3基础
一、vue-router v4.x 介绍 | Vue Router 1、安装 yarn add vue-routernext next代表最新的版本 2、路由配置 在src目录下,新建router/index.ts,具体配置如下 import {RouteRecordRaw,createRouter,createWebHashHistory} from vue-router const r…...
Qt应用开发(基础篇)——日历 QCalendarWidget
一、前言 QCalendarWidget类继承于QWidget,是Qt设计用来让用户更直观的选择日期的窗口部件。 时间微调输入框 QCalendarWidget根据年份和月份初始化,程序员也通过提供公共函数去改变他们,默认日期为当前的系统时间,用户通过鼠标和…...
Python学习笔记:正则表达式、逻辑运算符、lamda、二叉树遍历规则、类的判断
1.正则表达式如何写? 序号实例说明1.匹配任何字符(除换行符以外)2\d等效于[0-9],匹配数字3\D等效于[^0-9],匹配非数字4\s等效于[\t\r\n\f],匹配空格字符5\S等效于[^\t\r\n\f],匹配非空格字符6\w等效于[A-Za-z0-9]&…...
【滑动窗口】leetcode1004:最大连续1的个数
一.题目描述 最大连续1的个数 这道题要我们找最大连续1的个数,看到“连续”二字,我们要想到滑动窗口的方法。滑动窗口的研究对象是一个连续的区间,这个区间需要满足某个条件。那么本题要找的是怎样的区间呢?是一个通过翻转0后得到…...
力扣:73. 矩阵置零(Python3)
题目: 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 来源:力扣(LeetCode) 链接:力扣(LeetCode)官网 - 全球极客挚…...
VB|基础语法 变量定义 函数定义 循环语句 IF判断语句等
文章目录 变量定义函数定义控制台输入输出switch case语句IF语句FOR循环语句不等于逻辑运算符 变量定义 int Dim 变量名 As Int32 0 string Dim 变量名 As String "" bool Dim 变量名 As Boolean False 枚举 Dim 变量名 As 枚举名 数组 Dim array(256) As String…...
Github 博客搭建
Github 博客搭建 准备工作 准备一个 github 账号;建立 github 仓库,仓库名为 username.github.io,同时设置仓库为 public;clone 仓库,写入一个 index.html 文件,推送到仓库(许多网上的教程会有…...
模型预测笔记(三):通过交叉验证网格搜索机器学习的最优参数
文章目录 网络搜索介绍步骤参数代码实现 网络搜索 介绍 网格搜索(Grid Search)是一种超参数优化方法,用于选择最佳的模型超参数组合。在机器学习中,超参数是在训练模型之前设置的参数,无法通过模型学习得到。网格搜索…...
创建型模式-建造者模式
使用多个简单的对象一步一步构建成一个复杂的对象 主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部…...
Rust常用加密算法
哈希运算(以Sha256为例) main.rs: use crypto::digest::Digest;use crypto::sha2::Sha256;fn main() { let input "dashen"; let mut sha Sha256::new(); sha.input_str(input); println!("{}", sha.result_str());} Cargo.toml: [package]n…...
[管理与领导-55]:IT基层管理者 - 扩展技能 - 1 - 时间管理 -2- 自律与自身作则,管理者管好自己时间的五步法
前言: 管理好自己的时间,不仅仅是理念,也是方法和流程。 步骤1:理清各种待办事项 当提到工作事项时,这通常指的是要完成或处理的工作任务或事务。这些事项可以包括以下内容: 任务分配:根据工作…...
电子商务员考试题库及答案(中级)--判断题
电子商务员题库 一、判断题 1.EDI就是按照商定的协议,将商业文件分类,并通过计算机网络,在贸易伙伴的计算机网络系统之间进行数据交换和自动处理。〔〕 2.相互通信的EDI的用户必须使用相同类型的计算机。〔 〕 3.EDI采用共同…...
(WAF)Web应用程序防火墙介绍
(WAF)Web应用程序防火墙介绍 1. WAF概述 Web应用程序防火墙(WAF)是一种关键的网络安全解决方案,用于保护Web应用程序免受各种网络攻击和威胁。随着互联网的不断发展,Web应用程序变得越来越复杂&#x…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
