当前位置: 首页 > news >正文

【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.txtmodules/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

框架分析&#xff08;6&#xff09;-Ruby on Rails 专栏介绍Ruby on Rails核心概念以及组件讲解MVC架构模式约定优于配置强大的ORM支持自动化测试丰富的插件生态系统RESTful路由安全性总结 优缺点优点快速开发简单易学MVC架构强大的ORM支持大量的插件和Gem支持 缺点性能问题学习…...

LLMs NLP模型评估Model evaluation ROUGE and BLEU SCORE

在整个课程中&#xff0c;你看到过类似模型在这个任务上表现良好&#xff0c;或者这个微调模型在性能上相对于基础模型有显著提升等陈述。 这些陈述是什么意思&#xff1f;如何形式化你的微调模型在你起初的预训练模型上的性能改进&#xff1f;让我们探讨一些由大型语言模型开…...

BlazorServer中C#与JavaScript的相互调用

BlazorServer中C#与JavaScript的相互调用 前言&#xff1a; ​ 虽然BlazorServer中推荐使用C#在razor页面中的替代JavaScript来完成逻辑的编写&#xff0c;但当需要使用第三方的javascript文件/组件里的内容时&#xff0c;则难免要在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目录下&#xff0c;新建router/index.ts&#xff0c;具体配置如下 import {RouteRecordRaw,createRouter,createWebHashHistory} from vue-router const r…...

Qt应用开发(基础篇)——日历 QCalendarWidget

一、前言 QCalendarWidget类继承于QWidget&#xff0c;是Qt设计用来让用户更直观的选择日期的窗口部件。 时间微调输入框 QCalendarWidget根据年份和月份初始化&#xff0c;程序员也通过提供公共函数去改变他们&#xff0c;默认日期为当前的系统时间&#xff0c;用户通过鼠标和…...

Python学习笔记:正则表达式、逻辑运算符、lamda、二叉树遍历规则、类的判断

1.正则表达式如何写&#xff1f; 序号实例说明1.匹配任何字符(除换行符以外)2\d等效于[0-9]&#xff0c;匹配数字3\D等效于[^0-9]&#xff0c;匹配非数字4\s等效于[\t\r\n\f]&#xff0c;匹配空格字符5\S等效于[^\t\r\n\f]&#xff0c;匹配非空格字符6\w等效于[A-Za-z0-9]&…...

【滑动窗口】leetcode1004:最大连续1的个数

一.题目描述 最大连续1的个数 这道题要我们找最大连续1的个数&#xff0c;看到“连续”二字&#xff0c;我们要想到滑动窗口的方法。滑动窗口的研究对象是一个连续的区间&#xff0c;这个区间需要满足某个条件。那么本题要找的是怎样的区间呢&#xff1f;是一个通过翻转0后得到…...

力扣:73. 矩阵置零(Python3)

题目&#xff1a; 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚…...

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 账号&#xff1b;建立 github 仓库&#xff0c;仓库名为 username.github.io&#xff0c;同时设置仓库为 public&#xff1b;clone 仓库&#xff0c;写入一个 index.html 文件&#xff0c;推送到仓库&#xff08;许多网上的教程会有…...

模型预测笔记(三):通过交叉验证网格搜索机器学习的最优参数

文章目录 网络搜索介绍步骤参数代码实现 网络搜索 介绍 网格搜索&#xff08;Grid Search&#xff09;是一种超参数优化方法&#xff0c;用于选择最佳的模型超参数组合。在机器学习中&#xff0c;超参数是在训练模型之前设置的参数&#xff0c;无法通过模型学习得到。网格搜索…...

创建型模式-建造者模式

使用多个简单的对象一步一步构建成一个复杂的对象 主要解决&#xff1a;主要解决在软件系统中&#xff0c;有时候面临着"一个复杂对象"的创建工作&#xff0c;其通常由各个部分的子对象用一定的算法构成&#xff1b;由于需求的变化&#xff0c;这个复杂对象的各个部…...

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- 自律与自身作则,管理者管好自己时间的五步法

前言&#xff1a; 管理好自己的时间&#xff0c;不仅仅是理念&#xff0c;也是方法和流程。 步骤1&#xff1a;理清各种待办事项 当提到工作事项时&#xff0c;这通常指的是要完成或处理的工作任务或事务。这些事项可以包括以下内容&#xff1a; 任务分配&#xff1a;根据工作…...

电子商务员考试题库及答案(中级)--判断题

电子商务员题库 一、判断题 1&#xff0e;EDI就是按照商定的协议&#xff0c;将商业文件分类&#xff0c;并通过计算机网络&#xff0c;在贸易伙伴的计算机网络系统之间进行数据交换和自动处理。〔〕 2.相互通信的EDI的用户必须使用相同类型的计算机。〔 〕 3.EDI采用共同…...

(WAF)Web应用程序防火墙介绍

&#xff08;WAF&#xff09;Web应用程序防火墙介绍 1. WAF概述 ​ Web应用程序防火墙&#xff08;WAF&#xff09;是一种关键的网络安全解决方案&#xff0c;用于保护Web应用程序免受各种网络攻击和威胁。随着互联网的不断发展&#xff0c;Web应用程序变得越来越复杂&#x…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...