grid map学习笔记3之详解grid_map_pcl库实现point cloud点云转换成grid map栅格地图

news2024/9/24 15:21:10

文章目录

  • 0 引言
  • 1 grid_map_pcl示例
    • 1.1 主要文件
    • 1.2 示例数据
    • 1.3 启动文件
    • 1.4 配置文件
    • 1.5 主要实现流程
    • 1.6 启动示例
    • 1.7 示例结果
  • 2 D435i 点云生成栅格地图
    • 2.1 D435i 点云文件
    • 2.2 修改启动文件
    • 2.3 测试和结果
    • 2.4 修改配置文件
    • 2.5 重新测试和结果

0 引言

grid map学习笔记1已经编译安装并测试了相关的demo示例,grid map学习笔记2进一步熟悉了该库相关的定义,本文在此基础上,重点学习grid_map_pcl,熟悉该子库在输入点云的前提下,如何转换成grid map格式的栅格地图,保存栅格地图,可视化栅格地图,以及相关的配置文件。

grid_map_pcl是一个用于在PointCloud Library (PCL)中进行栅格地图处理的库。它提供了一些功能,能够将点云数据映射到栅格地图中,以便进行高效的处理和分析。

  1. 创建和管理栅格地图:
    使用grid_map_pcl,可以创建一个栅格地图,并在其中存储点云数据。栅格地图是一个二维数据结构,类似于栅格地图,但每个栅格可以存储多个属性值。可以使用grid_map库的函数来创建、管理和访问栅格地图。

  2. 将点云数据映射到栅格地图:
    grid_map_pcl提供了函数来将点云数据映射到栅格地图中。可以使用fromPCLPointCloud2函数将PCL的点云数据转换为grid_map格式,也可以将点云数据添加到栅格地图中的特定层。

  3. 从栅格地图中提取点云数据:
    可以使用toPCLPointCloud2函数将栅格地图中的数据转换回PCL的点云格式,以便进行进一步的处理或保存。

  4. 进行栅格地图的其他处理:
    grid_map_pcl还提供了其他一些功能,如栅格地图的滤波、插值、裁剪等。可以使用这些功能对栅格地图进行进一步的处理和分析。

👉 grid map github:https://github.com/ANYbotics/grid_map

本文系统环境:

  • Ubuntu18.04
  • ROS-melodic
  • grid map
  • D435i相机和驱动

1 grid_map_pcl示例

1.1 主要文件

首先grid map学习笔记1已经一起编译安装了grid_map_pcl,可参考上文完成编译。

其次grid_map_pcl文件夹下所有文件的数目录如下:

.
├── CHANGELOG.rst
├── CMakeLists.txt
├── config
│   ├── elevation_map.bag
│   ├── parameters.yaml
│   ├── plane_noisy.pcd
├── doc
│   ├── forest.png
│   ├── indoor.png
│   └── outdoor.png
├── include
│   └── grid_map_pcl
│       ├── GridMapPclConverter.hpp
│       ├── grid_map_pcl.hpp
│       ├── GridMapPclLoader.hpp
│       ├── helpers.hpp
│       ├── PclLoaderParameters.hpp
│       └── PointcloudProcessor.hpp
├── launch
│   └── grid_map_pcl_loader_node.launch
├── package.xml
├── README.md
├── src
│   ├── GridMapPclConverter.cpp
│   ├── GridMapPclLoader.cpp
│   ├── grid_map_pcl_loader_node.cpp
│   ├── helpers.cpp
│   ├── PclLoaderParameters.cpp
│   └── PointcloudProcessor.cpp
└── test
    ├── GridMapPclLoaderTest.cpp
    ├── HelpersTest.cpp
    ├── PointcloudCreator.cpp
    ├── PointcloudCreator.hpp
    ├── PointcloudProcessorTest.cpp
    ├── test_data
    │   ├── parameters.yaml
    │   └── plane_noisy.pcd
    ├── test_grid_map_pcl.cpp
    ├── test_helpers.cpp
    └── test_helpers.hpp

其中主要的文件及文件夹简介如下:

  • CMakeLists.txtgrid_map_pcl 库的CMakeLists.txt文件,catkin_make编译时需要依据该文件来寻找依赖库(pcl等),也确定编译后的执行文件等等。
  • config 文件夹:该文件夹是grid_map_pcl库的配置文件夹,比如parameters.yaml是主要的配置文件,后文会详细介绍该文件;其他两个是示例的点云输入文件和栅格地图输出bag包。
  • doc 文件夹:该文件夹是grid_map_pcl库的说明文档,里边有三种图片,直观展示了grid_map_pcl库把点云生成栅格地图。
  • include 文件夹:该文件夹是grid_map_pcl库的头文件,GridMapPclConverter.hpp声明了点云和栅格地图数据的转换函数等;GridMapPclLoader.hpp声明了点云和栅格地图的导入函数;PclLoaderParameters.hpp声明了点云相关的参数导入函数;helpers.hpp声明了各种类似中间件的函数,比如栅格地图topic函数,栅格地图保存函数等。
  • src 文件夹:该文件夹是grid_map_pcl库的主要函数实现文件,对应include 文件夹的头文件,是各个头文件中声明函数的的具体实现代码。
  • launch 文件夹:grid_map_pcl_loader_node.launch 是具体的点云生成栅格地图并保存示例的启动文件。
  • test 文件夹:该文件夹是grid_map_pcl库的测试代码,类似src文件夹中的主要函数实现代码。

1.2 示例数据

示例文件是grid_map_pcl/config/plane_noisy.pcd点云文件,因为已经安装过pcl,可直接用pcl_viewer来打开查看:

# plane_noisy.pcd 文件目录下新开终端
pcl_viewer plane_noisy.pcd

请添加图片描述

1.3 启动文件

grid_map_pcl_loader_node.launch 启动文件的内容,主要内容简介如下:

  • folder_path:配置文件、输入文件及输出文件的相对路径
  • pcd_filename:点云文件的名字
  • map_rosbag_topic:栅格地图的ros topic
  • output_grid_map:栅格地图保存的ros bag名字
  • map_frame:栅格地图的frame名字,rviz默认的即是map
  • map_layer_name:该层栅格地图的名字
  • grid_map_pcl_loader_node:该示例启动的主要代码文件名为grid_map_pcl_loader_node.cpp
<?xml version="1.0" encoding="UTF-8"?> 

<launch>
	<arg name="folder_path" default="$(find grid_map_pcl)/config"/>
	<arg name="pcd_filename" default="plane_noisy.pcd" />
	<arg name="map_rosbag_topic" default="grid_map" />
	<arg name="output_grid_map" default="elevation_map.bag" />
	<arg name="map_frame" default="map" />
	<arg name="map_layer_name" default="elevation" />
	<arg name="prefix" default=""/>
	<arg name="set_verbosity_to_debug" default="false"/>
	<node name="grid_map_pcl_loader_node" pkg="grid_map_pcl"
		type="grid_map_pcl_loader_node" output="screen" launch-prefix="$(arg prefix)">
		<rosparam file="$(find grid_map_pcl)/config/parameters.yaml" />
		<param name="folder_path" type="string" value="$(arg folder_path)" />
		<param name="pcd_filename" type="string" value="$(arg pcd_filename)" />
		<param name="map_rosbag_topic" type="string" value="$(arg map_rosbag_topic)" />
		<param name="output_grid_map" type="string" value="$(arg output_grid_map)" />
		<param name="map_frame" type="string" value="$(arg map_frame)" />
		<param name="map_layer_name" type="string" value="$(arg map_layer_name)" />
		<param name="set_verbosity_to_debug" type="bool" value="$(arg set_verbosity_to_debug)" />
	</node>
</launch>

1.4 配置文件

parameters.yaml配置文件的内容如下,详细的配置参数含义已经注释:

pcl_grid_map_extraction:
	# 所需的线程数
	num_processing_threads: 4
	# 点云转换矩阵,平移和旋转(rpy)
	cloud_transform:
		translation:
			x: 0.0
			y: 0.0
			z: 0.0
		rotation: #intrinsic rotation X-Y-Z (r-p-y)sequence
			r: 0.0
			p: 0.0
			y: 0.0
	# 聚类提取的参数设置:聚类阈值,聚类最小的点云数及最大点云数
	cluster_extraction:
		cluster_tolerance: 0.05
		min_num_points: 4
		max_num_points: 1000000
		use_max_height_as_cell_elevation: false
	# 移除异常值:是否移除及参数设置
	outlier_removal:
		is_remove_outliers: true
		mean_K: 10
		stddev_threshold: 1.0
	# 降采样设置:是否降采样,体素大小
	downsampling:
		is_downsample_cloud: true
		voxel_size:
			x: 0.02
			y: 0.02
			z: 0.02
	# 栅格地图的设置:栅格单元的最小点云数和分辨率
	grid_map:
		min_num_points_per_cell: 4
		resolution: 0.1

1.5 主要实现流程

grid_map_pcl_loader_node.cpp是该示例启动的main函数文件,详细的注释如下,主要流程是:ros 初始化->定义grid map发布的ros topic->导入数据和配置参数->转换点云为栅格地图->保存和发布栅格地图

#include <ros/ros.h>
#include <grid_map_core/GridMap.hpp>
#include <grid_map_ros/GridMapRosConverter.hpp>
#include "grid_map_pcl/GridMapPclLoader.hpp"
#include "grid_map_pcl/helpers.hpp"

namespace gm = ::grid_map::grid_map_pcl;

int main(int argc, char** argv) {

	// ros 初始化
	ros::init(argc, argv, "grid_map_pcl_loader_node");
	ros::NodeHandle nh("~");
	gm::setVerbosityLevelToDebugIfFlagSet(nh); // 是否设置为调试级别
	
	// 定义grid map发布的ros topic
	ros::Publisher gridMapPub;
	gridMapPub = nh.advertise<grid_map_msgs::GridMap>("grid_map_from_raw_pointcloud", 1, true);
	
	grid_map::GridMapPclLoader gridMapPclLoader;
	const std::string pathToCloud = gm::getPcdFilePath(nh); // 获取点云pcd导入的路径
	gridMapPclLoader.loadParameters(gm::getParameterPath()); // 获取配置参数的路径并导入参数
	gridMapPclLoader.loadCloudFromPcdFile(pathToCloud); // 导入点云文件
	
	// 初始化点云到栅格地图,添加点云转换的栅格地图层 等
	gm::processPointcloud(&gridMapPclLoader, nh);
	
	// 定义并生成栅格地图,添加frame id
	grid_map::GridMap gridMap = gridMapPclLoader.getGridMap();
	gridMap.setFrameId(gm::getMapFrame(nh));
	// 保存栅格地图到 ros bag文件中
	gm::saveGridMap(gridMap, nh, gm::getMapRosbagTopic(nh));
	
	// publish grid map,持续发布生成的栅格地图topic
	
	grid_map_msgs::GridMap msg;
	grid_map::GridMapRosConverter::toMessage(gridMap, msg);
	gridMapPub.publish(msg);
	
	// run
	ros::spin();
	return EXIT_SUCCESS;
}

1.6 启动示例

执行以下命令启动:

# source激活环境
source ~/grid_map_ws/devel/setup.bash
roslaunch grid_map_pcl grid_map_pcl_loader_node.launch

1.7 示例结果

启动后,终端会打印出如下信息:

process[grid_map_pcl_loader_node-1]: started with pid [13328]
[ INFO] [1690873305.071903062]: Preprocessing of the pointcloud started
[ INFO] [1690873305.168204888]: Preprocessing and filtering finished
[ INFO] [1690873305.168273120]: Grid map dimensions: 2.5 x 1.3
[ INFO] [1690873305.168291046]: Grid map resolution: 0.1
[ INFO] [1690873305.168300955]: Grid map num cells: 25 x 13
[ INFO] [1690873305.168307533]: Initialized map geometry
[ INFO] [1690873305.168315524]: Initialization took: 0.096 sec
[ INFO] [1690873305.169005291]: Started adding layer: elevation
[ INFO] [1690873305.182350266]: Finished adding layer: elevation
[ INFO] [1690873305.182377328]: Total time: 0.11 sec
[ INFO] [1690873305.187189276]: Saving grid map successful: true

这时会发现grid_map_pcl/config/elevation_map.bag路径下保存了栅格地图的ros bag;通过rosbag info elevation_map.bag 可查看保存的栅格数据信息:

path:        elevation_map.bag
version:     2.0
duration:    0.0s
start:       Jul 31 2023 16:46:17.52 (1690793177.52)
end:         Jul 31 2023 16:46:17.52 (1690793177.52)
size:        13.3 KB
messages:    1
compression: none [1/1 chunks]
types:       grid_map_msgs/GridMap [95681e052b1f73bf87b7eb984382b401]
topics:      grid_map   1 msg     : grid_map_msgs/GridMap

同时开启rviz,按照如下步骤添加生成的栅格地图topic,即可看到可视化的栅格地图:

请添加图片描述

2 D435i 点云生成栅格地图

通过第1章,已经熟悉了grid_map_pcl实现点云转换成栅格地图的步骤,那接下来就用自己的点云数据来生成栅格地图,接下里就用D435i相机来演示。

2.1 D435i 点云文件

默认已经安装了D435i相机驱动,启动前需要修改rs_camera.launch,打开点云:

	<!-- rs_camera.launch 修改下行的false 为 true -->
  <arg name="enable_pointcloud"         default="true"/>

然后通过roslaunch realsense2_camera rs_camera.launch命令启动D435i相机,通过rostopic list即可查看到/camera/depth/color/pointsD435i相机的点云topic

接下来就是如何保存一帧点云topic的问题,可以直接使用或参考如下python代码,调用python-pcl(需安装pip install python-pcl)等库,主要流程是:订阅点云topic->转换为pcl库格式数据->保存成pcd点云文件->取消订阅

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import rospy
from sensor_msgs.msg import PointCloud2
from sensor_msgs import point_cloud2
import pcl

class PointCloudSubscriber:
    def __init__(self):
        self.cloud = pcl.PointCloud_PointXYZRGB()
        self.sub = rospy.Subscriber('/camera/depth/color/points', PointCloud2, self.callback)

    def callback(self, data):
        # Convert PointCloud2 message to PCL data
        pc = point_cloud2.read_points(data)
        self.cloud.from_list(list(pc))

        # Save PCL data as PCD file
        pcl.save(self.cloud, 'point_cloud_xyzrgb.pcd')
        rospy.loginfo('PointCloud2 message saved as point_cloud.pcd')

        # Unsubscribe from topic after saving one frame
        self.sub.unregister()

if __name__ == '__main__':
    rospy.init_node('pcl_subscriber', anonymous=True)
    pcl_subscriber = PointCloudSubscriber()
    rospy.spin()

执行完脚本后,即可在当前文件夹下保存一帧D435i相机的点云文件point_cloud_xyzrgb.pcd,可以用pcl_viewer point_cloud_xyzrgb.pcd来可视化查看点云:

请添加图片描述

备注:或者直接下载point_cloud_xyzrgb.pcd

2.2 修改启动文件

首先复制point_cloud_xyzrgb.pcdgrid_map_pcl/config/目录下,然后如下修改grid_map_pcl_loader_node.launch启动文件中的pcd_filenameoutput_grid_map

<arg name="folder_path" default="$(find grid_map_pcl)/config"/>
<!-- <arg name="pcd_filename" default="plane_noisy.pcd" /> -->
<arg name="pcd_filename" default="point_cloud_xyzrgb.pcd" />
<arg name="map_rosbag_topic" default="grid_map" />
<!-- <arg name="output_grid_map" default="elevation_map.bag" /> -->
<arg name="output_grid_map" default="point_cloud_xyzrgb_map.bag" />

2.3 测试和结果

重新执行以下命令启动:

# source激活环境
source ~/grid_map_ws/devel/setup.bash
roslaunch grid_map_pcl grid_map_pcl_loader_node.launch

启动后,终端会打印出如下信息:

process[grid_map_pcl_loader_node-1]: started with pid [17862]
[ INFO] [1690875646.276651807]: Preprocessing of the pointcloud started
[ INFO] [1690875648.082437226]: Preprocessing and filtering finished
[ INFO] [1690875648.082582464]: Grid map dimensions: 10.3 x 3.9
[ INFO] [1690875648.082612676]: Grid map resolution: 0.1
[ INFO] [1690875648.082621679]: Grid map num cells: 103 x 39
[ INFO] [1690875648.082628487]: Initialized map geometry
[ INFO] [1690875648.082636410]: Initialization took: 1.806 sec
[ INFO] [1690875648.083387628]: Started adding layer: elevation
[ INFO] [1690875648.103188697]: Finished adding layer: elevation
[ INFO] [1690875648.103218881]: Total time: 1.826 sec
[ INFO] [1690875648.107564757]: Saving grid map successful: true

这时会发现grid_map_pcl/config/point_cloud_xyzrgb_map.bag路径下保存了栅格地图的ros bag;通过rosbag info point_cloud_xyzrgb_map.bag 可查看保存的栅格数据信息:

path:        point_cloud_xyzrgb_map.bag
version:     2.0
duration:    0.0s
start:       Jul 31 2023 18:03:42.42 (1690797822.42)
end:         Jul 31 2023 18:03:42.42 (1690797822.42)
size:        27.7 KB
messages:    1
compression: none [1/1 chunks]
types:       grid_map_msgs/GridMap [95681e052b1f73bf87b7eb984382b401]
topics:      grid_map   1 msg     : grid_map_msgs/GridMap

同时开启rviz,按照如下步骤添加生成的栅格地图topic,即可看到可视化的栅格地图:

请添加图片描述

2.4 修改配置文件

以上演示的仅仅是修改了启动文件,替换了输入的点云文件,但每个传感器的点云质量,密度等都不一样,所以也需要多次调试配置文件parameters.yaml来调节生成的栅格地图。

比如仅调节resolution参数,分别调节成 resolution: 0.5resolution: 0.05,其他参数不变,对比生成的栅格地图。

# 栅格地图的设置:栅格单元的最小点云数和分辨率
grid_map:
	min_num_points_per_cell: 4
	# resolution: 0.1
	resolution: 0.5
	# resolution: 0.05

2.5 重新测试和结果

每次调整参数后,重新执行roslaunch grid_map_pcl grid_map_pcl_loader_node.launch生成栅格地图,如下图 resolution: 0.5resolution: 0.1resolution: 0.05的结果:

resolution0.50.10.05
grid mapAlt请添加图片描述请添加图片描述

Reference:

  • https://github.com/anybotics/grid_map



须知少时凌云志,曾许人间第一流。



⭐️👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍🌔

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

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

相关文章

海外网红营销:如何利用故事打造独具魅力的品牌形象?

随着全球数字化时代的来临&#xff0c;品牌推广已经从传统的广告宣传方式逐渐转变为更加注重故事性和情感共鸣的营销手段。故事营销在品牌塑造和传播过程中发挥着重要作用&#xff0c;它能够吸引消费者的注意力&#xff0c;加深品牌与受众的情感连接&#xff0c;从而为品牌带来…

uniapp开发微信小程序--自定义顶部导航栏

一、实现效果&#xff1a; 二、代码实现&#xff1a; 1.在pages.json文件中&#xff0c;单页面定义导航栏&#xff0c;添加以下代码&#xff1a; "navigationStyle": "custom" //自定义导航栏如图所示&#xff1a; 2.在components文件夹下&#xff0c;…

用于毫米波天线的新型无卤素超低传输损耗多层电路板R-5410

3月3日消息&#xff0c;松下公司宣布&#xff0c;其工业解决方案公司已经实现了R-5410的商业化&#xff0c;这是一种无卤素、超低传输损耗的多层电路板&#xff08;MLCB&#xff09;材料&#xff0c;适用于毫米波天线。将于2021年3月开始量产。 毫米波雷达是汽车、通信等行业的…

uC-OS2 V2.93 STM32L476 移植:环境搭建篇

前言 uC-OS2 是比较经典的 RTOS&#xff0c;如今软件授权已经改为 Apache License Version 2.0&#xff0c;意味着可以免费商用了 当前 uC-OS2 的最新版本是&#xff1a; V2.93&#xff0c;打算研究一下 RTOS 的设计思想&#xff0c;所以想在已有的开发板&#xff1a;NUCLEO-L…

Mybatis,Spring,SpringMVC项目创建

先做一些设置 file——setting——maven 创建项目maven项目 主方法下和java平行 创建完成 接下里就是导依赖了 spring和mybatis创建文件是一样的&#xff0c;就是配置不一样 SpringMVC前面和Mybatis和Spring是一样的&#xff0c;后面需要web 然后是new——projectStructure …

【数字IC基础】从触发器到亚稳态

从触发器到亚稳态 单稳态和双稳态三态门单稳态电路双稳态电路 锁存器SR锁存器 触发器电平触发的触发器SR触发器D锁存器&#xff08;电平触发的D触发器&#xff09; 边沿触发的触发器边沿触发 D 触发器脉冲触发的触发器 建立时间和保持时间恢复时间和去除时间亚稳态亚稳态的产生…

C++ | 哈希表的实现与unordered_set/unordered_map的封装

目录 前言 一、哈希 1、哈希的概念 2、哈希函数 &#xff08;1&#xff09;直接定址法 &#xff08;2&#xff09;除留余数法 &#xff08;3&#xff09;平方取中法&#xff08;了解&#xff09; &#xff08;4&#xff09;随机数法&#xff08;了解&#xff09; 3、哈…

.net 6升级.net7 容器报错is not supported on this platform.

一、生成验证码报错 System.PlatformNotSupportedException: System.Drawing.Common is not supported on this platform.Tue, Aug 1 2023 9:57:37 pmat System.Drawing.Image..ctor()Tue, Aug 1 2023 9:57:37 pmat System.Drawing.Bitmap..ctor(Int32 width, Int32 height) 二…

keil使用printf函数重定串口输出,程序卡在Reset_Handler

最近在做国产芯片GD32F103项目&#xff0c;使用printf()函数重定向USART0串口输出&#xff0c;发现程序没有运行&#xff0c;单步调试发现&#xff0c;程序卡在startup_gd32f10x.s文件的Reset_Handler处&#xff0c;记录一下解决方法。 解决办法&#xff1a; 1、引用头文件#in…

Git rebase和merge区别详解

文章目录 变基的基础用法变基过程中的冲突解决冲突后无法push问题更新变基后的代码更有趣的变基用法变基的风险用变基解决变基变基 vs 合并 此文在阅读前需要有一定的git命令基础&#xff0c;若基础尚未掌握&#xff0c;建议先阅读这篇文章Git命令播报详版 在 Git 中整合来自不…

【ChatGPT辅助学Rust | 基础系列 | 函数,语句和表达式】函数的定义,使用和特性

文章标题 简介一&#xff0c;函数1&#xff0c;函数的定义2&#xff0c;函数的调用3&#xff0c;函数的参数4&#xff0c;函数的返回值 二&#xff0c;语句和表达式1&#xff0c;语句2&#xff0c;表达式 总结&#xff1a; 简介 在Rust编程中&#xff0c;函数&#xff0c;语句…

hadoop与HDFS交互

一、利用Shell命令与HDFS进行交互 在进行HDFS编程实践前&#xff0c;需要首先启动Hadoop。可以执行如下命令启动Hadoop&#xff1a; cd /usr/local/hadoop ./sbin/start-dfs.sh #启动hadoop Hadoop支持很多Shell命令&#xff0c;其中fs是HDFS最常用的命令&#xff0c;利用fs…

在矩池云使用Llama2-7B的具体方法

今天给大家分享如何在矩池云服务器使用 Llama2-7b模型。 硬件要求 矩池云已经配置好了 Llama 2 Web UI 环境&#xff0c;显存需要大于 8G&#xff0c;可以选择 A4000、P100、3090 以及更高配置的等显卡。 租用机器 在矩池云主机市场&#xff1a;https://matpool.com/host-m…

5.开发DAO组件 -- Spring Data JPA

开发DAO组件 作用&#xff1a;用来访问数据库 持久化技术&#xff1a;Spring Data, JPA, Mybaits&#xff0c;jOOQ 等 Spring Boot为常见持久化技术提供了支持。 现在使用 Spring Data JPA Spring Data JPA 使用Spring Data JPA来访问数据库&#xff0c;需要再项目添加两个…

探究Vue源码:mustache模板引擎(8) 了解nestTokens 手写梳理模板字符串井号循环嵌套结构tokens

上文 探究Vue源码:mustache模板引擎(7) 手写模板字符串转换tokens数组过程中 我们操作出了一个较为简单的 tokens数组 并简单处理了 井号反斜杠的特殊符号语法 那么 我们现在需要将零散的tokens嵌套起来 主要就体现在 我们 井号 到 反斜杠 中间的内容 显然是属于循环语句中的子…

Postman如何做接口测试1:如何导入 swagger 接口文档

在使用 postman 做接口测试过程中&#xff0c;测试工程师会往界面中填入非常多的参数&#xff0c;包括 url 地址&#xff0c;请求方法&#xff0c;消息头和消息体等一系列数据&#xff0c;在请求参数比较多的情况下非常花时间。 我们可以使用 postman 的文档导入功能&#xff…

Chapter 11: Tuples | Python for Everybody 讲义笔记_En

文章目录 Python for Everybody课程简介TuplesTuples are immutableComparing tuplesTuple assignmentDictionaries and tuplesMultiple assignment with dictionariesThe most common wordsUsing tuples as keys in dictionariesSequences: strings, lists, and tuples - Oh M…

因果推断(二)倾向匹配得分(PSM)

因果推断&#xff08;二&#xff09;倾向匹配得分&#xff08;PSM&#xff09; 前文介绍了如何通过合成控制法构造相似的对照组&#xff0c;除此之外&#xff0c;也可以根据倾向匹配得分&#xff08;PSM&#xff09;进行构造&#xff0c;即为每一个试验组样本在对照组中找对与…

dialog => :before-close的属性应用

在element-ui里面关闭弹窗的时候before-close会触发。 也就是点击X的时候回触发before-close这个属性, 代码实例: <el-dialogtitle"新增用户":visible.sync"dialogVisible"width"50%":before-close"handleClose"> handleClose…

【动态规划part15】| 392.判断子序列、115.不同的子序列

&#x1f388;LeetCode392.判断子序列 链接&#xff1a;392.判断子序列 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;…