GSLAM | 一个通用的SLAM架构和基准

作者 | 欢喜  编辑 | 汽车人

原文链接:https://zhuanlan.zhihu.com/p/661803163

点击下方卡片,关注“自动驾驶之心”公众号

ADAS巨卷干货,即可获取

点击进入→自动驾驶之心【SLAM】技术交流群

本文只做学术分享,如有侵权,联系删文

突然发现了一篇19年的论文

GSLAM:A General SLAM Framework and Benchmark

开源代码:https://github.com/zdzhaoyong/GSLAM

直接上全文,感受这项工作的质量吧~

1摘要

SLAM技术最近取得了许多成功,并吸引了高科技公司的关注。然而,如何同一现有或新兴算法的界面,一级有效地进行关于速度、稳健性和可移植性的基准测试仍然是问题。本文,提出了一个名为GSLAM的新型SLAM平台,它不仅提供评估功能,还为研究人员提供了快速开发自己的SLAM系统的有用工具。GSLAM的核心贡献是一个通用的。跨平台的、完全开源的SLAM接口,旨在处理输入数据集、SLAM实现、可视化和应用程序的统一框架中的交互。通过这个平台,用户可以以插件形式实现自己的功能,以提高SLAM的性能,并进一步将SLAM的应用推向实际应用。

2介绍

从上世纪80年代以来,同时定位与地图构建(SLAM)一直是计算机视觉和机器人领域的热门研究主题。SLAM为许多需要实时导航的应用提供了基本功能,如机器人技术、无人机(UAVs)、自动驾驶、以及虚拟现实和增强现实。近来年,SLAM技术得到了迅速发展,提出了各种SLAM系统,包括单目SLAM系统(基于特征点,直接和半直接方法)、多传感器SLAM系统(RGBD、双目和惯性辅助的方法)以及基于学习的SLAM系统(有监督和无监督方法)。

然而,随着SLAM技术的迅速发展,几乎所有的研究人员都集中精力于自己的SLAM系统的理论和实施,这使得难以交流思想,并且不容易实现迁移到其他系统。这妨碍了SLAM技术快速应用于各种行业领域。此外,目前存在许多SLAM系统的不同实现版本,如何有效地进行速度、稳健性和可移植性的基准测试仍然是一个问题。最近,Nardi等人和Bodin等人提出了统一的SLAM基准测试系统,以进行定量、可比较和可验证的实验研究,也探究各种SLAM系统之间的权衡。通过这些系统,可以使用数据集和度量评估模块轻松进行评估实验。

由于现有的系统仅提供评估基准,该论文认为有可能建立一个平台,以服务SLAM算法的整个生命周期,包括开发、评估和应用阶段。此外,近年来深度学习基础的SLAM已取得显著进展,因此有必要创建一个平台,不仅支持C++,还支持Python,以更好地支持几何和深度学习基础的SLAM系统的集成。因此,在本文中,介绍了一个新型的SLAM平台,不仅提供评估功能,还为研究人员提供了有用的工具,以快速开发他们自己的SLAM系统。通过这个平台,常用功能以插件形式提供,因此用户可以直接使用它们或创建自己的功能以实现更好的性能。希望这个平台能进一步推动SLAM系统的实际应用。总而言之,本文的主要贡献如下:

  1. 本文提出了一个通用的、跨平台的、完全开源的SLAM平台,旨在用于研究和商业用途,超越了以往的基准测试系统。SLAM接口由多个轻量级、无依赖的头文件组成,这使得在统一框架中以插件形式与不同数据集、SLAM算法和应用进行交互变得容易。此外,还提供了JavaScript和Python,以支持基于Web和深度学习的SLAM应用。

  2. 提出的GSLAM平台中,引入了三个经过优化的模块作为实用工具类,包括Estimator、Optimizer和Vocabulary。Estimator旨在提供一组封闭形式的求解器,涵盖所有情况,具有强大的样本一致性(RANSAC);Optimizer旨在提供流行的非线性SLM问题的统一接口;Vocabulary旨在提供高效且可移植的词袋实现,用于多线程和SIMD优化的地点识别。

  3. 受益于上述接口,该工作在一个统一的框架中实现并评估了现有数据集、SLAM实现和可视化应用的插件,未来出现的基准测试或应用也可以轻松地进行进一步集成。

下面首先介绍GSLAM框架的接口,并解释GSLAM的工作原理。其次,介绍三个实用组件,即Estimator, Optimizer和Vocabulary。然后,使用几个典型的公共数据集,使用GSLAM框架来评估不同流行的SLAM实现。最后,总结这些工作,并展望未来的研究方向。

3相关工作

Simultaneous Localization And Mapping

SLAM技术用于在未知环境中构建地图,并将传感器在地图中进行定位,主要侧重于实时操作。早期的SLAM主要基于扩展卡尔曼滤波(EKF)。将6自由度的运动参数和3D地标以概率方式表示为单一状态向量。经典EKF的复杂性随着地标数量的增加呈二次增长,限制了其可拓展性。近年来,SLAM技术得到了快速发展,提出了许多单目视觉SLAM系统,包括基于特征点、直接法和半直接方法。然而,单目SLAM系统缺乏尺度信息,无法处理纯旋转情况,因此一些其他多传感器SLAM系统,包括RGBD,双目和惯性辅助方法出现,以提高鲁棒性和精度。

尽管提出了大量的SLAM系统,但在统一这些算法的接口方面几乎没有什么工作,也没有对它们的性能进行全面的比较。此外,这些SLAM算法的实现通常以独立的可执行文件的形式发布,而不是以库的形式,而且往往不符合任何标准结构。

最近,基于深度学习的有监督和无监督的视觉里程计(VO)与传统的基于几何的方法相比,提出了新颖的思路。但是,进一步优化多个关键帧的一致性仍然不容易。GSLAM提供的工具可以帮助获得更好的全局一致性。通过该框架,更容易可视化或评估结果,并进一步应用于各种行业领域。

Computer Vision and Robotics Platform

在机器人技术和计算机领域,机器人系统(ROS)提供了节点之间非常便捷的通信方式,受到大多数机器人研究人员的青睐。许多SLAM实现提供了ROS包装器,以订阅传感器数据并发布可视化结果。但它并未统一SLAM实现的输入和输出,难以进一步评估不同SLAM系统。

受ROS消息架构的启发,GSLAM实现了一个类似的进程间通信实用类,称为Messenger。这为替代SLAM实现内部的ROS提供了另一种选择,并保持了兼容性,也就是说,该框架内支持所有ROS定义的消息,并自然地实现了ROS包装器。由于采用了进程内设计,消息传递时没有序列化和数据传输,消息可以无延迟和额外成本地发送。与此同时,消息的有效载荷不仅限于ROS定义的消息,还可以是任何可复制的数据结构。此外,不仅提供评估功能,还为研究人员提供了有用的工具,以快速开发和集成他们自己的SLAM算法。

SLAM Benchmarks

目前存在几种SLAM基准测试系统,包括KITTI基准测试、TUM RGB-D基准测试和ICL-NUIM RGB-D基准数据集,这些系统仅提供评估功能。此外,SLAMBench2将这些基准测试扩展为算法和数据集,要求用户将已发布的实现与SLAMBench2兼容,以进行评估,这难以扩展到更多应用领域。与这些系统不同,本文提出的GSLAM平台提供了一个解决方案,可为SLAM实现的整个生命周期提供服务,从开发、评估到应用。为研究人员提供了有用的工具,以快速开发他们自己的SLAM系统,并进一步基于统一接口开发可视化、评估和应用程序。

4通用SLAM架构

Framework Overview

GSLAM的框架如图所示。总的来说,接口旨在处理三个部分的交互。

  1. 处理SLAM实现的输入。运行SLAM时,需要传感器数据和一些参数。对于GSLAM,使用Svar类进行参数配置和命令处理。所有SLAM实现所需的传感器数据都由Dataset实现提供,并使用Messenger进行传输。GSLAM实现了几个流行的视觉SLAM数据集,用于可以自由实现自己的数据集插件。

  2. SLAM实现。GSLAM将每个实现视为插件库。开发人员可以非常容易地基于GSLAM接口和实用类设计一个SLAM实现。开发人员还可以使用接口包装实现,而无需引入额外的依赖。用户可以专注于核心算法的开发,而无需关心SLAM实现外部需要处理的输入和输出。

  3. 可视化部分或使用SLAM结果的应用。在SLAM实现处理输入帧后,用户可能希望展示或利用结果。为了通用性,SLAM结果应以标准格式发布。默认情况下,GSLAM使用Qt进行可视化,但用户可以自由实现自定义的可视化工具,并添加应用插件,如评估应用程序。

b513b52be417ec493f9f2514944b0955.png

该框架被设计为与各种不同类型的SLAM实现兼容,包括但不限于单目、双目、RGBD和多摄像头视觉惯性里程计与多传感器融合。现代深度学习平台和开发人员更喜欢使用Python进行编码,因此GSLAM提供了Python绑定,开发人员能够使用Python实现SLAM,并使用GSLAM调用它,或者使用Python调用基于C++的SLAM实现。此外,还支持JavaScript用于基于Web的用途。

Basic Interface Classes

SLAM接口通常使用的一些数据结构包括参数设置/读取、图像格式、姿态变换、相机模型和地图数据结构。以下是一些基本接口类的简要介绍。

Paramter Setting

GSLAM使用一个小巧的参数解析和参数设置类Svar,它仅包含一个头文件,依赖于C++11,并具有以下特点:

a.参数解析和配置加载以及帮助信息。类似于流行的参数解析工具,如Google gflags,变量配置可以从命令行参数、文件和系统环境中加载。用户还可以定义不同类型的参数,并提供介绍信息,这些信息将显示在帮助文档中。

b.一个小型脚本语言,支持变量、函数和条件语句,使配置文件更加强大。

c.线程安全的变量绑定和共享。建议将使用频率非常高的变量绑定到指针或引用上,这不仅提供了高效性,还提供了便利性。

d,简单的函数定义和从C++或纯脚本进行调用。命令和函数之间的绑定有助于开发人员解耦文件依赖关系。

e.支持树形结构表示,这意味着可以轻松地使用XML、JSON和YAML格式加载或保存配置。

Intra-Process Messaging

由于ROS提供了一个非常便捷的节点间通信方式,受到大多数机器人研究人员的青睐。受到ROS2消息架构的启发,GSLAM实现了一个类似的进程间通信实用类,称为Messenger。这为替代SLAM实现内部的ROS提供了另一种选择,并保持了兼容性。由于采用了进程间设计,Messenger能够发布和订阅任何类,而无需额外成本。以下是更多功能的介绍:

a.该接口采用了ROS的风格,对用来说容易上手。而且支持所有ROS定义的消息,这意味着只需要很少的工作就能替代原来的ROS消息传递系统。

b.由于没有序列化和数据传输,消息可以无延迟和额外成本地发送。与此同时,消息的有效载荷不仅限于ROS定义的消息,还支持任何可复制的数据结构。

c.源代码只包括基于C++11的头文件,没有额外的依赖,使其具有可移植性。

d.API是线程安全的,并在列队大小大于零时支持多线程条件通知。在发布者和订阅者相互连接之前,会对主题名称和RTTI数据结构进行检查,以确保正确地调用。

3D Transforamtion

b6b087833d16e205863111c291f1b644.png 174514630f724e469703c0a0b4955eaa.png

对于旋转部分,有几种表示方式可供选择,包括矩阵、欧拉角、单位四元数和李代数so(3)。对于给定的变换,可以使用其中任何一种来表示,并可以相互转换。但是,当考虑多个变换和流形优化时,需要密切关注所选择的表示方式。矩阵表示法使用9个参数进行过度参数化,而旋转只有3个自由度(DOF)。欧拉角表示使用3个变量,易于理解,但面临着万向锁的问题,而且不方便进行多重变换。单位四元数是执行多次旋转的最高效方式,而李代数则是执行流行优化的常见表示方法。

8c00b01b16948fa5fcc961f6a88a91a8.png

类似地,定义了刚体和相似性变换的李代数se(3)和sim(3)。GSLAM使用四元数来表示旋转部分,并提供了一种表示形式转换为另一种表示形式的函数。表格1展示了变换实现,并于另外三种流形的实现(Sophus, TooN和Ceres)进行了比较。由于Ceres实现使用角轴表示,因此不需要旋转的指数和对数。如表格所示,GSLAM的实现性能更佳,因为它使用四元数并具有更好的优化,而TooN使用矩阵实现,在点变换方面性能更好。

47fde6e8b3effd6d86dfea541a37920c.png

Image format

图像数据的存储和传输是视觉SLAM中最重要的功能之一。为了提高效率和便利性,GSLAM使用了一个数据结构GImage,它与cv::Mat兼容。它具有智能指针计数器,以确保内存安全释放,并且可以在不进行内存复制的情况下轻松传输。数据指针对齐,以便更容易进行单指令多数据(SIMD)加速。用户可以在GImage和cv::Mat之间无缝、安全地进行转换,而无需进行内存复制。

Camera Models

03ea40b692c69f477654f994eb721e91.png

由于SLAM可能包含由于制造不完美而引起的径向和切向畸变,或者是由鱼眼或全景相机捕捉的图像,因此提出了不同的相机模型来描述投影。GSLAM提供了包括OpenCV(ORB-SLAM使用)、ATAN(PTAM使用)和OCamCalib(MultiCol-SLAM使用)在内的实现。用户也可以轻松继承这些类并实现其他相机模型,如Kannala-Brandt和等距全景模型。

Map Data Structure

对于SLAM实现,其目标是实时定位并生成地图。GSLAM建议使用一个统一的地图数据结构,有多个地图帧和地图点组成。这个数据结构适用于大多数已有的视觉SLAM系统,包括基于特征或直接方法。

地图帧用于表示不同时间的位置状态,包括由传感器捕捉的各种信息或估算结果,包括IMU或GPS原始数据、深度信息和相机模型。SLAM实现估算它们之间的关系,它们之间的连接形成了一个姿势图。

地图点用于表示由帧观察到的环境,通常由基于特征的方法使用。但是,一个地图点不仅可以表示一个关键点,还可以表示一个GCP(地面控制点)、边缘线或3D对象。它们与地图帧的对应关系形成了一个观察图,通常被称为捆绑图。

5SLAM实现工具

为了更容易实现一个SLAM系统,GSLAM提供了一个实用类。本节将简要介绍三个经过优化的模块,分别是Estimator, Optimizer和Vocabulary。

Estimator

纯几何计算仍然是一个需要强大和准确的实时解决方案的基本问题。传统的视觉SLAM算法或现代的视觉惯性解决方案都依赖与几何视觉算法来进行初始化、重定位和回环闭合。OpenCV提供了多个几何算法,Kneip提供了一个用于几何视觉的工具箱OpenGV,该工具箱仅限于相机姿态计算。GSLAM的Estimator旨在提供一系列包括所有情况的封闭形式解算器,并使用了鲁棒的随机采样一致性方法(RANSAC)。

表2列出了Estimator支持的算法。根据给定的观测数据,它们被分成三类。2D-2D匹配用于估计极线或单应约束,并且可以从中分解相对姿态。2D-3D对应于估计单目或多摄像头系统的中心或非中心绝对位姿,这是著名的PnP问题。还支持3D几何函数,如平面拟合,以及估算两个点云的SIM变换。大多数算法都依赖与开源线性代数库Eigen,它是一个仅包含头文件的库,并且适用于大多数平台。

fbac22272fdb2588e92fe708a9c84412.png

Optimizer

非线性优化是现代几何SLAM系统的核心部分。由于Hessian矩阵的高纬度和稀疏性,图结构被用来建模SLAM的复杂估计问题。提出了几种框架,包括Ceres、G2O和GTSAM,用于解决一般的图优化问题。这些框架在不同的SLAM系统中广泛使用。ORB-SLAM、SVO使用G2O进行BA和位姿图优化。OKVIS、VINS使用Ceres进行带IMU因素的图优化,滑动窗口用于控制计算复杂性。Forster等人提出了一种基于SVO的视觉初始化方法,并使用GTSAM实现后端。

GSLAM的Optimizer旨在为大多数非线性SLAM问题提供一个统一的接口,如PnP求解器,BA,姿态图优化。基于Ceres库实现了这些问题的通用插件。对于特定问题,如BA,还可以提供一些更高效的实现,如PBA和ICE-BA作为插件。使用优化器工具,开发人员可以使用统一的接口访问不同的实现,特别是用于基于深度学习的SLAM系统。

Vocabulary

地点识别是SLAM系统中最重要的部分之一,用于重新定位和回环检测。词袋(BoW)方法在SLAM系统中广泛使用,因为它高效且性能出色。FabMap提出了一种基于外观的地点识别的概率方法,该方法用于RSLAM、LSD-SLAM等系统。由于它使用了像SIFT和SURF这样的浮点描述子,DBoW2为训练和检测构建了一个词汇树,支持二进制和浮点描述子。Refael提出了DBoW2的两个改进版本,DBoW3和FBoW,它们简化了接口并加快了训练和加载速度。之后,ORB-SLAM采用了ORB描述子,并使用DBoW2进行回环检测、重定位和快速匹配。随后,一系列SLAM系统,如ORB-SLAM2、VINS-Mono和LDSO,使用DBoW3进行回环检测。它已经成为实现SLAM系统地点识别的最流行工具。

受上述工作的启发,GSLAM对DBoW3词汇进行了仅包含头文件的实现,具有以下特点:

  1. 去除了对OpenCV的依赖,所有函数都在一个仅依赖C++11的头文件中实现。

  2. 结合DBoW2/3和FBoW的优点,具有极快的速度和易于使用。提供了类似于DBoW3的接口,并使用SSE和AVX指令加速了二进制和浮点描述子。

  3. 改进了内存使用和加速了加载、保存或训练词汇以及从图像特征到BoW向量转换的速度。

表3展示了四个词袋库的比较。在实验中,每个父节点有10个子节点,ORB特征检测使用ORB-SLAM,SIFT检测使用SiftGPU。实现结果中使用了ORB词汇,分别有4级和6级,以及一个SIFT词汇。FBoW和GSLAM都使用多线程进行词汇训练。GSLAM的实现在几乎所有项目中的表现都优于其他实现,包括加载和保存词汇、训练新词汇、将描述符列表转换为用于地点识别的BoW向量和用于快速特征匹配的特征向量。此外GSLAM实现使用更少的内存,并分配了更少的动态内存块,因为DBoW2需要大量内存的主要原因是碎片问题。

f98b3af793778bc0fae0cd78115493ce.png

6SLAM评估基准

现有的基准需要用户下载测试数据集并上传结果以进行精确性评估,这不足以统一运行环境并评估公平的性能比较。得益于GSLAM的统一接口,SLAM系统的评估变得更加优雅。在GSLAM的帮助下,开发人员只需上传SLAM插件,便可以在一个使用固定资源的docker化环境中进行速度、计算成本和准确性的各种评估。在本节中,将首先介绍一些数据集和已实现的SLAM插件。然后,对速度、准确性、内存和CPU使用率进行三个代表SLAM实现的评估。此评估旨在展示具有不同SLAM插件的统一SLAM基准实现的可能性。

Datasets

运行SLAM系统通常需要传感器数据流和相应的配置。为了让开发人员专注于核心SLAM插件的开发,GSLAM提供了一个标准的数据集接口,开发人员不需要关心SLAM的输入。通过不同的数据集插件,提供了在线传感器输入和离线数据,正确地插件会根据给定的数据集路径后缀动态加载。数据集的实现应该提供所有请求的传感器流以及相关配置,因此不需要为不同的数据集进行额外设置。所有不同的传感器流通过Messenger发布,使用标准的主题名称和数据格式。

GSLAM已经实现了几个流行的视觉SLAM数据集插件,如表4所示。用户也可以非常容易地基于仅包含头文件的GSLAM核心来实现一个数据集插件,并将其发布为插件并与应用程序一起进行编译。

c328f4cc4cd69748357ba88a06fc5617.png

SLAM Implementations

图2展示了一些使用内置Qt可视化器运行的开源SLAM和SfM插件的屏幕截图。该框架支持不同体系结构的SLAM系统,包括直接法、半直接法、基于特征的方法,甚至SfM方法。DSO实现需要发布结果,例如点云、相机姿势、轨迹和姿态图,以便像基于ROS的实现一样进行可视化。用户可以使用统一的框架访问不同的SLAM插件,根据C++、Python和Node-JS接口开发基于SLAM的应用程序非常方便。由于许多研究人员在开发中使用ROS,GSLAM还提供了ROS可视化插件,以无缝传输ROS定义的消息,并使开发人员可以利用Rviz进行显示或继续开发其他基于ROS的应用程序。

28b8ceb83d4512e2a979a2a53d11b16b.png

Evaluation

由于大多数现有的基准只提供数据集,或者没有groundtruth供用户自行进行评估,GSLAM提供了一个内置插件和一些脚本工具,用于计算性能和精度评估。

论文中使用TUM RGBD数据集中的序列nostructure-texture-near-withloop来演示评估的执行情况。接下来的实验采用三个开源的单目SLAM插件DSO, SVO和ORB-SLAM。在所有实验中,使用一台搭载i7-6700 CPU、GTX 1060 GPU和16GB RAM的计算机,运行64位Ubuntu 16.04。

计算性能评估包括内存使用、分配内存块数量、CPU使用率以及统计每帧所用的时间,如图3所示。结果表明,SVO使用的内存和CPU资源最少,并获得了最快的速度。而且由于SVO只是一个视觉里程计,在实现内部只维护了一个本地地图,所以成本保持稳定。DSO分配的内存块数较少,但消耗了100MB以上的内存,且增长较慢。DSO的一个问题是当帧数低于500时,处理时间会急剧增加,此外,关键帧的处理时间甚至更长。ORB-SLAM使用了最多的CPU资源,计算时间稳定,但内存使用快速增加,并且它分配和释放了大量的内存块,因为其BA使用了G2O库,没有使用增量优化方法。

84b2930c1b4229484edbbb0bd4a30ed3.png

图4展示了里程计轨迹的评估结果。如图所示,SVO速度较快,但漂移较大,而ORBSLAM在绝对姿态误差(APE)方面达到了最高的精度。由于综合评估是一个可插拔的插件应用程序,可以重新实施更多的评估指标,例如点云的精度。

fa54c13e21c4a31323f27b04a6035197.png

7总结

本文介绍了一个名为GSLAM的新型通用SLAM平台,该平台提出了从开发、评估到应用的支持。通过这个平台,常用的工具包以插件形式提供,用户还可以轻松地开发自己的模块。为了使平台易于使用,使接口只依赖于C++11。此外,还提供了Python和JavaScript接口,以更好地集成传统SLAM和基于深度学习的SLAM,或在Web上进行分布式操作。

在接下来的研究中,会提供更多的SLAM实现、文档和演示代码,以便学习和使用。此外,还将提供传统SLAM和基于深度学习的SLAM的集成,以进一步探索SLAM系统的未知可能性。

这项工作的主页如下:

GSLAM: Main Page

感觉是可学习SLAM各部分原理的框架~

① 全网独家视频课程

BEV感知、毫米波雷达视觉融合多传感器标定多传感器融合多模态3D目标检测点云3D目标检测目标跟踪Occupancy、cuda与TensorRT模型部署协同感知语义分割、自动驾驶仿真、传感器部署、决策规划、轨迹预测等多个方向学习视频(扫码即可学习

794377d555f75907f557a06508779c12.png 视频官网:www.zdjszx.com

② 国内首个自动驾驶学习社区

近2000人的交流社区,涉及30+自动驾驶技术栈学习路线,想要了解更多自动驾驶感知(2D检测、分割、2D/3D车道线、BEV感知、3D目标检测、Occupancy、多传感器融合、多传感器标定、目标跟踪、光流估计)、自动驾驶定位建图(SLAM、高精地图、局部在线地图)、自动驾驶规划控制/轨迹预测等领域技术方案、AI模型部署落地实战、行业动态、岗位发布,欢迎扫描下方二维码,加入自动驾驶之心知识星球,这是一个真正有干货的地方,与领域大佬交流入门、学习、工作、跳槽上的各类难题,日常分享论文+代码+视频,期待交流!

c2658144ba6a7e851742a0862757a040.png

③【自动驾驶之心】技术交流群

自动驾驶之心是首个自动驾驶开发者社区,聚焦目标检测、语义分割、全景分割、实例分割、关键点检测、车道线、目标跟踪、3D目标检测、BEV感知、多模态感知、Occupancy、多传感器融合、transformer、大模型、点云处理、端到端自动驾驶、SLAM、光流估计、深度估计、轨迹预测、高精地图、NeRF、规划控制、模型部署落地、自动驾驶仿真测试、产品经理、硬件配置、AI求职交流等方向。扫码添加汽车人助理微信邀请入群,备注:学校/公司+方向+昵称(快速入群方式)

9e3818d6892ef74320aa7c7db7d25954.jpeg

④【自动驾驶之心】平台矩阵,欢迎联系我们!

1cb0af1441dc2fc6ef00549743e18361.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值