ROS机器人未知环境自主探索功能包explore_lite最全源码详细解析(五)

news2025/6/22 14:08:05

   本系列文章主要针对ROS机器人常使用的未知环境自主探索功能包explore_lite展开全源码的详细解析,并进行概括总结。 本系列文章共包含六篇文章,前五篇文章主要介绍explore_lite功能包中 explore.cpp、costmap_tools.h、frontier_search.cpp、costmap_client.cpp等源码实现文件中全部函数的详细介绍,第六篇文章进行概括总结,包含自主探索功能包explore_lite的简介,实现未知环境自主探索功能的原理及流程总结,效果演示,使用功能包explore_lite时机器人一直在原地转圈的解决方法等内容。

在这里插入图片描述


   ☆☆☆本文系列文章索引及函数分布索引 【点击文章名可跳转】☆☆☆

文章一、ROS机器人未知环境自主探索功能包explore_lite最全源码详细解析(一)

   一、main    二、Explore构造函数    三、~Explore析构函数

   四、stop 函数    五、makePlan()函数 ☆☆☆☆☆

文章二、ROS机器人未知环境自主探索功能包explore_lite最全源码详细解析(二)

   六、visualizeFrontiers函数    七、goalOnBlacklist函数    八、reachedGoal函数

   九、start函数

文章三、ROS机器人未知环境自主探索功能包explore_lite最全源码详细解析(三)

   十、nhood4函数    十一、nhood8函数    十二、nearestCell函数

   十三、searchFrom函数

文章四、ROS机器人未知环境自主探索功能包explore_lite最全源码详细解析(四)

   十四、isNewFrontierCell函数    十五、buildNewFrontier函数    十六、frontierCost函数

   十七、FrontierSearch构造函数    十八、Costmap2DClient构造函数

文章五、ROS机器人未知环境自主探索功能包explore_lite最全源码详细解析(五)

   十九、updateFullMap函数    二十、updatePartialMap函数    二十一、getRobotPose函数

   二十二、init_translation_table函数

文章六、ROS机器人未知环境自主探索功能包explore_lite总结

   全系列文章的概括总结【强烈推荐】

   【注 1】:上述函数的颜色是我根据该函数对理解自主探索算法的工作原理及流程的重要程度划分的,红色的最重要,蓝色的次数,最后是绿色的,纯属个人观点,仅供参考。

   【注 2】:关于函数分布,函数一到九位于explore.cpp中,函数十到十二位于costmap_tools.h中,函数十三到十七位于frontier_search.cpp中,函数十八到二十二位于costmap_client.cpp中


在这里插入图片描述

十九、updateFullMap函数

   1、函数源码

void Costmap2DClient::updateFullMap(const nav_msgs::OccupancyGrid::ConstPtr& msg)
{
  global_frame_ = msg->header.frame_id;

  unsigned int size_in_cells_x = msg->info.width;
  unsigned int size_in_cells_y = msg->info.height;
  double resolution = msg->info.resolution;
  double origin_x = msg->info.origin.position.x;
  double origin_y = msg->info.origin.position.y;

  ROS_DEBUG("received full new map, resizing to: %d, %d", size_in_cells_x,
            size_in_cells_y);
  costmap_.resizeMap(size_in_cells_x, size_in_cells_y, resolution, origin_x,
                     origin_y);

  // lock as we are accessing raw underlying map
  auto* mutex = costmap_.getMutex();
  std::lock_guard<costmap_2d::Costmap2D::mutex_t> lock(*mutex);

  // fill map with data
  unsigned char* costmap_data = costmap_.getCharMap();
  size_t costmap_size = costmap_.getSizeInCellsX() * costmap_.getSizeInCellsY();
  ROS_DEBUG("full map update, %lu values", costmap_size);
  for (size_t i = 0; i < costmap_size && i < msg->data.size(); ++i) {
    unsigned char cell_cost = static_cast<unsigned char>(msg->data[i]);
    costmap_data[i] = cost_translation_table__[cell_cost];
  }
  ROS_DEBUG("map updated, written %lu values", costmap_size);
}

   2、主要作用:

   Costmap2DClient::updateFullMap函数的主要作用是处理完整的成本地图(costmap)更新。当收到一个新的nav_msgs::OccupancyGrid消息时,此函数将使用该消息更新内部的成本地图表示,这对于机器人的导航和路径规划至关重要。

   3、详细介绍:

更新成本地图的基本信息

global_frame_ = msg->header.frame_id;

unsigned int size_in_cells_x = msg->info.width;
unsigned int size_in_cells_y = msg->info.height;
double resolution = msg->info.resolution;
double origin_x = msg->info.origin.position.x;
double origin_y = msg->info.origin.position.y;

ROS_DEBUG("received full new map, resizing to: %d, %d", size_in_cells_x,
          size_in_cells_y);
costmap_.resizeMap(size_in_cells_x, size_in_cells_y, resolution, origin_x,
                   origin_y);
  • 首先,函数更新了全局坐标系名称(global_frame_)以匹配接收到的成本地图消息的帧ID。
  • 然后,它读取并设置了成本地图的尺寸、分辨率和原点位置。
  • 使用ROS_DEBUG打印接收到的成本地图的尺寸信息,并调用resizeMap函数调整内部成本地图的大小以匹配接收到的成本地图。

加锁并更新成本地图数据

auto* mutex = costmap_.getMutex();
std::lock_guard<costmap_2d::Costmap2D::mutex_t> lock(*mutex);

unsigned char* costmap_data = costmap_.getCharMap();
size_t costmap_size = costmap_.getSizeInCellsX() * costmap_.getSizeInCellsY();
ROS_DEBUG("full map update, %lu values", costmap_size);
for (size_t i = 0; i < costmap_size && i < msg->data.size(); ++i) {
  unsigned char cell_cost = static_cast<unsigned char>(msg->data[i]);
  costmap_data[i] = cost_translation_table__[cell_cost];
}
ROS_DEBUG("map updated, written %lu values", costmap_size);
  • 在更新内部成本地图之前,通过获取成本地图的互斥锁来确保线程安全。
  • 获取成本地图的原始数据指针和成本地图的大小。
  • 遍历接收到的成本地图数据,将每个单元格的成本值通过之前定义的成本值转换表cost_translation_table__转换后,更新到内部成本地图中。
  • 使用ROS_DEBUG打印更新的成本地图数据量信息。

   通过updateFullMap函数的处理,Costmap2DClient能够确保内部成本地图始终保持最新,反映了环境的当前状态,为机器人提供准确的导航和规划信息。


在这里插入图片描述

二十、updatePartialMap函数

   1、函数源码

void Costmap2DClient::updatePartialMap(
    const map_msgs::OccupancyGridUpdate::ConstPtr& msg)
{
  ROS_DEBUG("received partial map update");
  global_frame_ = msg->header.frame_id;

  if (msg->x < 0 || msg->y < 0) {
    ROS_ERROR("negative coordinates, invalid update. x: %d, y: %d", msg->x,
              msg->y);
    return;
  }

  size_t x0 = static_cast<size_t>(msg->x);
  size_t y0 = static_cast<size_t>(msg->y);
  size_t xn = msg->width + x0;
  size_t yn = msg->height + y0;

  // lock as we are accessing raw underlying map
  auto* mutex = costmap_.getMutex();
  std::lock_guard<costmap_2d::Costmap2D::mutex_t> lock(*mutex);

  size_t costmap_xn = costmap_.getSizeInCellsX();
  size_t costmap_yn = costmap_.getSizeInCellsY();

  if (xn > costmap_xn || x0 > costmap_xn || yn > costmap_yn ||
      y0 > costmap_yn) {
    ROS_WARN("received update doesn't fully fit into existing map, "
             "only part will be copied. received: [%lu, %lu], [%lu, %lu] "
             "map is: [0, %lu], [0, %lu]",
             x0, xn, y0, yn, costmap_xn, costmap_yn);
  }

  // update map with data
  unsigned char* costmap_data = costmap_.getCharMap();
  size_t i = 0;
  for (size_t y = y0; y < yn && y < costmap_yn; ++y) {
    for (size_t x = x0; x < xn && x < costmap_xn; ++x) {
      size_t idx = costmap_.getIndex(x, y);
      unsigned char cell_cost = static_cast<unsigned char>(msg->data[i]);
      costmap_data[idx] = cost_translation_table__[cell_cost];
      ++i;
    }
  }
}

   2、主要作用:

   Costmap2DClient::updatePartialMap函数负责处理成本地图的部分更新。当收到map_msgs::OccupancyGridUpdate消息时,此函数将更新内部成本地图的一部分,而不是整个成本地图,这通常用于实时更新成本地图中的变化区域,提高更新效率。

   3、详细介绍:

接收部分地图更新

ROS_DEBUG("received partial map update");
global_frame_ = msg->header.frame_id;

if (msg->x < 0 || msg->y < 0) {
  ROS_ERROR("negative coordinates, invalid update. x: %d, y: %d", msg->x,
            msg->y);
  return;
}
  • 首先,打印接收到部分更新的调试信息,并更新global_frame_为消息头中指定的帧ID。
  • 然后,检查更新消息中的坐标是否为负值,负坐标表示无效更新,如果是这种情况,函数将打印错误信息并返回。

准备更新数据

size_t x0 = static_cast<size_t>(msg->x);
size_t y0 = static_cast<size_t>(msg->y);
size_t xn = msg->width + x0;
size_t yn = msg->height + y0;
  • 接下来,计算更新区域的起始点(x0, y0)和终点(xn, yn)坐标,这些坐标标识了需要更新的成本地图区域。

加锁并检查更新范围

auto* mutex = costmap_.getMutex();
std::lock_guard<costmap_2d::Costmap2D::mutex_t> lock(*mutex);

size_t costmap_xn = costmap_.getSizeInCellsX();
size_t costmap_yn = costmap_.getSizeInCellsY();

if (xn > costmap_xn || x0 > costmap_xn || yn > costmap_yn ||
    y0 > costmap_yn) {
  ROS_WARN("received update doesn't fully fit into existing map, "
           "only part will be copied. received: [%lu, %lu], [%lu, %lu] "
           "map is: [0, %lu], [0, %lu]",
           x0, xn, y0, yn, costmap_xn, costmap_yn);
}
  • 使用互斥锁保证在更新成本地图数据时的线程安全。
  • 计算内部成本地图的尺寸,并检查接收到的更新是否完全适合现有的成本地图范围内。如果更新超出了现有地图的范围,则只会更新适合的部分,并打印警告信息。

更新成本地图数据

unsigned char* costmap_data = costmap_.getCharMap();
size_t i = 0;
for (size_t y = y0; y < yn && y < costmap_yn; ++y) {
  for (size_t x = x0; x < xn && x < costmap_xn; ++x) {
    size_t idx = costmap_.getIndex(x, y);
    unsigned char cell_cost = static_cast<unsigned char>(msg->data[i]);
    costmap_data[idx] = cost_translation_table__[cell_cost];
    ++i;
  }
}
  • 遍历指定的更新区域,在内部成本地图中更新相应单元格的成本值。成本值通过cost_translation_table__转换表转换,以匹配内部使用的成本表示。
  • 更新操作根据更新消息中的数据逐个单元格进行,只更新消息指定区域内的单元格。

通过这种方式,Costmap2DClient::updatePartialMap能够高效地更新成本地图中的特定区域,从而确保成本地图能够快速响应环境的变化,为机器人的导航和规划提供最新的信息。


在这里插入图片描述

二十一、getRobotPose函数

   1、函数源码

geometry_msgs::Pose Costmap2DClient::getRobotPose() const
{
  tf::Stamped<tf::Pose> global_pose;
  global_pose.setIdentity();
  tf::Stamped<tf::Pose> robot_pose;
  robot_pose.setIdentity();
  robot_pose.frame_id_ = robot_base_frame_;
  robot_pose.stamp_ = ros::Time();
  ros::Time current_time =
      ros::Time::now();  // save time for checking tf delay later

  // get the global pose of the robot
  try {
    tf_->transformPose(global_frame_, robot_pose, global_pose);
  } catch (tf::LookupException& ex) {
    ROS_ERROR_THROTTLE(1.0, "No Transform available Error looking up robot "
                            "pose: %s\n",
                       ex.what());
    return {};
  } catch (tf::ConnectivityException& ex) {
    ROS_ERROR_THROTTLE(1.0, "Connectivity Error looking up robot pose: %s\n",
                       ex.what());
    return {};
  } catch (tf::ExtrapolationException& ex) {
    ROS_ERROR_THROTTLE(1.0, "Extrapolation Error looking up robot pose: %s\n",
                       ex.what());
    return {};
  }
  // check global_pose timeout
  if (current_time.toSec() - global_pose.stamp_.toSec() >
      transform_tolerance_) {
    ROS_WARN_THROTTLE(1.0, "Costmap2DClient transform timeout. Current time: "
                           "%.4f, global_pose stamp: %.4f, tolerance: %.4f",
                      current_time.toSec(), global_pose.stamp_.toSec(),
                      transform_tolerance_);
    return {};
  }

  geometry_msgs::PoseStamped msg;
  tf::poseStampedTFToMsg(global_pose, msg);
  return msg.pose;
}

   2、主要作用:

   Costmap2DClient::getRobotPose函数的主要作用是获取机器人在成本地图所在的全局坐标系下的位置和姿态。这个过程通过查询ROS的tf变换系统来实现,确保了获取的机器人位置信息是与成本地图正确对齐的。

   3、详细介绍:

初始化和设置变换查询

tf::Stamped<tf::Pose> global_pose;
global_pose.setIdentity();
tf::Stamped<tf::Pose> robot_pose;
robot_pose.setIdentity();
robot_pose.frame_id_ = robot_base_frame_;
robot_pose.stamp_ = ros::Time();
ros::Time current_time = ros::Time::now();  // save time for checking tf delay later
  • 首先,初始化两个tf::Stamped<tf::Pose>对象:global_poserobot_poseglobal_pose用于存储转换后的全局位置,robot_pose表示机器人的当前位置。
  • robot_pose的帧ID被设置为机器人基座的坐标系(robot_base_frame_),时间戳设置为当前时间。

获取全局位置

try {
  tf_->transformPose(global_frame_, robot_pose, global_pose);
} catch (tf::LookupException& ex) {
  ROS_ERROR_THROTTLE(1.0, "No Transform available Error looking up robot pose: %s\n", ex.what());
  return {};
} catch (tf::ConnectivityException& ex) {
  ROS_ERROR_THROTTLE(1.0, "Connectivity Error looking up robot pose: %s\n", ex.what());
  return {};
} catch (tf::ExtrapolationException& ex) {
  ROS_ERROR_THROTTLE(1.0, "Extrapolation Error looking up robot pose: %s\n", ex.what());
  return {};
}
  • 使用tf::TransformListenertransformPose方法尝试将robot_pose从机器人基座坐标系转换到全局坐标系(global_frame_)。
  • 这个转换过程可能会抛出几种异常,包括查找变换时的异常、连接问题或数据外推错误。遇到任何异常时,函数将输出错误信息并返回空的位置信息。

检查变换延迟

if (current_time.toSec() - global_pose.stamp_.toSec() > transform_tolerance_) {
  ROS_WARN_THROTTLE(1.0, "Costmap2DClient transform timeout. Current time: %.4f, global_pose stamp: %.4f, tolerance: %.4f", current_time.toSec(), global_pose.stamp_.toSec(), transform_tolerance_);
  return {};
}
  • 在成功获取全局位置后,检查变换信息的时效性,确保获取的位置信息没有超过预定的容忍延迟(transform_tolerance_)。

返回机器人位置

geometry_msgs::PoseStamped msg;
tf::poseStampedTFToMsg(global_pose, msg);
return msg.pose;
  • 最后,将global_pose转换为geometry_msgs::PoseStamped类型,并返回其中的pose部分,即机器人在全局坐标系下的位置和姿态。

   通过这种方式,Costmap2DClient::getRobotPose为机器人提供了一种可靠的方法来获取其在成本地图全局坐标系下的精确位置,这对于路径规划和导航决策非常关键。


在这里插入图片描述

二十二、init_translation_table函数

   1、函数源码

std::array<unsigned char, 256> init_translation_table()
{
  std::array<unsigned char, 256> cost_translation_table;

  // lineary mapped from [0..100] to [0..255]
  for (size_t i = 0; i < 256; ++i) {
    cost_translation_table[i] =
        static_cast<unsigned char>(1 + (251 * (i - 1)) / 97);
  }

  // special values:
  cost_translation_table[0] = 0;      // NO obstacle
  cost_translation_table[99] = 253;   // INSCRIBED obstacle
  cost_translation_table[100] = 254;  // LETHAL obstacle
  cost_translation_table[static_cast<unsigned char>(-1)] = 255;  // UNKNOWN

  return cost_translation_table;
}

   2、主要作用:

   Costmap2DClient::updateFullMap函数的主要作用是处理完整的成本地图(costmap)更新。当收到一个新的nav_msgs::OccupancyGrid消息时,此函数将使用该消息更新内部的成本地图表示,这对于机器人的导航和路径规划至关重要。

   3、详细介绍:

init_translation_table函数的主要作用是初始化一个成本转换表,这个表用于将成本地图中的原始值转换为用于路径规划和障碍物避让的内部值。这种转换是必要的,因为成本地图中的原始值通常表示障碍物的占据概率(例如,0到100的范围),而在路径规划中需要将这些值转换为特定的成本值。

初始化成本转换表

std::array<unsigned char, 256> cost_translation_table;

// lineary mapped from [0..100] to [0..255]
for (size_t i = 0; i < 256; ++i) {
  cost_translation_table[i] =
      static_cast<unsigned char>(1 + (251 * (i - 1)) / 97);
}
  • 首先,创建一个std::array<unsigned char, 256>类型的数组cost_translation_table,用于存储转换后的成本值。
  • 通过循环遍历0到255的所有可能的输入值,使用线性映射公式1 + (251 * (i - 1)) / 97计算对应的成本值。这个公式将原始值的范围(0到100)映射到一个更宽的范围(1到252),以便在内部使用。

设置特殊成本值

cost_translation_table[0] = 0;      // NO obstacle
cost_translation_table[99] = 253;   // INSCRIBED obstacle
cost_translation_table[100] = 254;  // LETHAL obstacle
cost_translation_table[static_cast<unsigned char>(-1)] = 255;  // UNKNOWN
  • 接着,手动设置几个特殊的成本值:
    • 将数组的第一个元素(代表没有障碍物的情况)的值设置为0。
    • 将代表接触障碍物(inscribed obstacle)的值设置为253。
    • 将代表致命障碍物(lethal obstacle)的值设置为254。
    • 将代表未知区域的值设置为255。这里使用static_cast<unsigned char>(-1)来访问数组的最后一个元素,因为-1转换为无符号字符类型时会变为255。

返回成本转换表

return cost_translation_table;
  • 最后,函数返回填充完成的成本转换表。

   通过这个成本转换表,Costmap2DClient可以将成本地图中的原始数据转换为实际用于路径规划和障碍物避让的成本值。这个转换过程对于实现更高级的导航和探索策略至关重要。


在这里插入图片描述


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

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

相关文章

MySQL:关于数据库的一些练习题

文章目录 前面的内容已经把数据库的一些必要知识已经储备好了&#xff0c;因此下面就对于这些语句进行一些练习&#xff1a; 批量插入数据 insert into actor values (1, PENELOPE, GUINESS, 2006-02-15 12:34:33), (2, NICK, WAHLBERG, 2006-02-15 12:34:33);SQL202 找出所有…

C/S医学检验LIS实验室信息管理系统源码 医院LIS源码

LIS系统即实验室信息管理系统。LIS系统能实现临床检验信息化&#xff0c;检验科信息管理自动化。其主要功能是将检验科的实验仪器传出的检验数据经数据分析后&#xff0c;自动生成打印报告&#xff0c;通过网络存储在数据库中&#xff0c;使医生能够通过医生工作站方便、及时地…

一起学习python——基础篇(14)

今天讲一下python的json解析方式。 上一篇文章讲述了将传参数据转换为json格式的数据传给后台&#xff0c;如果后端返回的json格式数据&#xff0c;我们该如何解析呢&#xff1f; 例子一&#xff1a;简单的json数据格式 如果后端返回的json数据如下&#xff0c; { "na…

【leetcode面试经典150题】34.有效的数独(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

Docker Compose 一键安装

文章目录 一、场景说明二、脚本职责三、参数说明四、操作示例五、注意事项 一、场景说明 本自动化脚本旨在为提高研发、测试、运维快速部署应用环境而编写。 脚本遵循拿来即用的原则快速完成 CentOS 系统各应用环境部署工作。 统一研发、测试、生产环境的部署模式、部署结构、…

【C++学习】C++11新特性(第二节)—— 右值引用与移动语义超详解

文章目录 文章简介二.右值引用1.什么是左值&#xff0c;什么是右值&#xff1f;什么是左值引用&#xff0c;什么是右值引用&#xff1f;2.左值引用与右值引用比较 三.右值引用使用场景和意义1.左值引用的使用场景&#xff1a;2.左值引用的短板&#xff1a;3.右值引用与移动构造…

2024大模型落地应用案例集(免费下载)

【1】扫码关注本公众号 【2】私信发送 2024大模型落地应用案例集 【3】获取本方案PDF下载链接&#xff0c;直接下载即可。

【Linux】环境下OpenSSH升级到 OpenSSH_9.6P1(图文教程)

漏洞描述 OpenSSH&#xff08;OpenBSD Secure Shell&#xff09;是加拿大OpenBSD计划组的一套用于安全访问远程计算机的连接工具。该工具是SSH协议的开源实现&#xff0c;支持对所有的传输进行加密&#xff0c;可有效阻止窃听、连接劫持以及其他网络级的攻击。OpenSSH 9.6之前…

深入浅出Golang image库:编写高效的图像处理代码

深入浅出Golang image库&#xff1a;编写高效的图像处理代码 引言image库概览图像处理基础概念image库的主要组成和功能image接口图像格式的支持color模型 结论 图像的基本操作创建图像新图像的创建从文件加载图像 图像的保存与导出图像的颜色和像素处理绘制基本形状和文字 高级…

无网络连接 请检查你的网络设置 然后重试 [2604] 彻底解决方案

错误提示&#xff1a;无网络连接 请检查你的网络设置 然后重试 [2604] 彻底解决方案如下&#xff1a; 方案一&#xff1a; 打开Internet Explorer浏览器&#xff0c;选择"工具 > Internet 选项"。 在Internet属性窗口下&#xff0c;点击高级下滑到安全模块分类…

[漏洞复现]D-Link未授权RCE漏洞复现(CVE-2024-3273)

声明&#xff1a;亲爱的读者&#xff0c;我们诚挚地提醒您&#xff0c;Aniya网络安全的技术文章仅供个人研究学习参考。任何因传播或利用本实验室提供的信息而造成的直接或间接后果及损失&#xff0c;均由使用者自行承担责任。Aniya网络安全及作者对此概不负责。如有侵权&#…

Linux查看系统配置信息的命令【lscpu】【free】【df】【uname】【lsblk】【top】

目录 1.查看CPU信息【lscpu】 2.查看内存信息【free】 3.查看文件系统信息【df】 4.查看系统信息【uname】 知识扩展&#xff1a;Red Hat Enterprise Linux 和 Debian GNU/Linux 两者的发展介绍 知识扩展&#xff1a;Centos 和 ubuntu的区别 知识扩展&#xff1a;更多 …

Quanto: PyTorch 量化工具包

量化技术通过用低精度数据类型 (如 8 位整型 (int8)) 来表示深度学习模型的权重和激活&#xff0c;以减少传统深度学习模型使用 32 位浮点 (float32) 表示权重和激活所带来的计算和内存开销。 减少位宽意味着模型的内存占用更低&#xff0c;这对在消费设备上部署大语言模型至关…

Python学习从0开始——项目一day01爬虫

Python学习从0开始——项目一day01爬虫 一、导入代码二、使用的核心库三、功能测试3.1初始代码3.2新建文件3.3代码调试 四、页面元素解析4.1网页4.2修改代码4.3子页面4.4修改代码 一、导入代码 在Inscode新建一个python类型的项目&#xff0c;然后打开终端&#xff0c;粘贴以下…

高中数学:三角函数-基础知识

一、任意角 顺时针旋转是负值角 逆时针旋转式正值角 一个角对应一个终边 一个终边对应无数个角 xk*360 例题 二、弧度制 弧长与半径的比值&#xff0c;就是角度 常见角度与弧度的对应关系 例题 三、弧长与扇形面积公式 注意&#xff1a;弧度制下的扇形面积公式&#x…

SpringBoot --pagehelper分页

目录 1.建立数据库 2.页面显示 3.基本逻辑 4.配置依赖 5.使用pagehelper 6.页面列表 页面 效果 1.建立数据库 create database if not exists my_book; use my_book; create table if not exists myBook (id int primary key auto_increment,name varchar(50) not …

Python(4):函数(命名+参数+内置函数+匿名函数)

文章目录 一、关于*的一些打散功能二、函数的特点和命名规范三、函数的返回值return四、函数的参数1.无参数的函数2.有参数的函数 五、函数的命名空间六、全局变量和局部变量七、函数的作用域以及执行顺序(LEGB)八、递归函数九、常见内置函数十、匿名函数-lambda 一、关于*的一…

c++的学习之路:11、string(3)

昨天写string的时候没有说全&#xff0c;这里就开始接着讲。 目录 一、resize 二、insert 三、erase 一、resize 昨天说这个的时候没有考虑到缩小范围时咋处理&#xff0c;然后发现报错了&#xff0c;接着我调试发现缩小就不能正常执行了&#xff0c;因为用的是strcap所以…

芯片设计围炉札记

文章目录 语言Verilog 和 VHDL 区别 芯片验证 语言 System Verilog的概念以及与verilog的对比 IC 设计软件分析 Verilog 和 VHDL 区别 Verilog HDL 和 VHDL 的区别如下&#xff1a; 语法结构&#xff1a;Verilog的语法结构类似于C语言&#xff0c;而VHDL的语法结构则更接近…

流程图步骤条

1.结构 <ul class"stepUl"> <li class"stepLi" v-for"(item, index) in stepList" :key"index"> <div class"top"> <p :class"{active: currentState > item.key}">{{ item.value }}…