ROS理论与实践学习笔记——6 ROS机器人导航(仿真)
在 ROS 中,机器人导航(Navigation)是由多个功能包组合而成的系统,统称为导航功能包集(navigation stack)。它提供了一个全面的框架,使得移动机器人能够自主导航到指定目标点,同时避开环境中的障碍物。
导航功能包集:该导航系统基于多个核心功能包,包括地图构建、定位、路径规划和运动控制等模块。这些功能包通过整合,协同处理机器人感知的环境数据和导航任务需求,从而实现自主导航。
二维导航堆栈:ROS 的二维导航堆栈(2D Navigation Stack)是该功能集的核心组件之一。它接收以下主要信息:
- 里程计数据:提供机器人自身的位置和运动状态信息。
- 传感器数据流:包括来自激光雷达(LiDAR)、深度摄像头、Kinect 或其他传感器的数据,帮助机器人感知周围的环境并检测障碍物。
- 目标姿态:用户通过 RViz 或其他接口为机器人设置的目标位置和方向(2D平面上的目标点)。
基于这些输入,导航堆栈的路径规划模块会计算从当前位置到目标点的最优路径,并结合局部路径规划,在导航过程中避开障碍物。
1.1 导航模块简介
(1)全局地图(定位 + 路径规划)
在现实生活中,当我们进行导航时,通常会首先参考一张全局地图,依据这张地图确定自己和目标的位置,并据此规划出一条合理的路线。同样地,对于机器人导航,地图也是其核心组成部分之一。机器人通过地图确定其在环境中的位置,并根据目标位置规划路径。为此,首先需要对环境进行建图。在机器人导航领域,随着技术的不断发展,出现了许多先进的地图建模方法,其中SLAM 技术尤其引人瞩目。
SLAM(Simultaneous Localization and Mapping,即同步定位与地图构建),也被称为 CML(Concurrent Mapping and Localization, 并发建图与定位),它是一种能够让机器人在未知环境中从未知位置开始导航的技术。SLAM 的问题可以描述为:机器人在未知环境中,通过自身运动,根据传感器数据估计自己的位置,并同时构建环境的地图。在这一过程中,SLAM 通过不断迭代,逐步完善机器人的位置估计和环境地图,最终绘制出整个环境的完整地图。
SLAM 的核心工作:
- 定位(Localization):机器人需要根据传感器数据和已知的地图或部分地图确定自身的具体位置。随着机器人在环境中移动,定位模块持续更新位姿信息。
- 建图(Mapping):机器人基于传感器数据同时构建环境的地图,通常是增量式的。在机器人更新自己位置的同时,它会在当前已知位置上逐步更新环境的地图信息。
ROS 中的 SLAM 实现: 在 ROS 中,已有多种实现 SLAM 的功能包,常用的包括:
- gmapping:基于粒子滤波的 2D SLAM 实现,适合激光雷达等传感器的应用。
- hector_slam:无需里程计数据,通过激光雷达构建高精度 2D 地图。
- cartographer:Google 开源的 2D/3D SLAM 框架,支持多传感器融合,效果稳定。
- rgbdslam:利用 RGB-D 摄像头(如 Kinect)进行 3D 地图构建。
- ORB-SLAM:基于视觉的 SLAM 系统,适合使用摄像头或立体相机。
无论使用哪种 SLAM 实现,机器人必须具备对周围环境的感知能力,尤其是获取深度信息的能力。实现感知通常依赖于以下传感器:
- 激光雷达(LiDAR):可以高精度扫描周围环境,生成二维或三维的深度数据。
- RGB-D 摄像头:如 Kinect,能够同时获取彩色图像和深度信息。
- 普通摄像头:用于视觉 SLAM,通过图像特征匹配来定位和建图。
SLAM 的地图生成与保存: SLAM 技术用于动态生成环境地图,而生成的地图需要保存以供后续使用。在 ROS 中,map_server 是常用的功能包,用于保存和加载地图数据。它可以将 SLAM 生成的地图保存为图片格式(如 .pgm
文件),并通过 .yaml
文件提供地图的元数据(如分辨率、原点等)。保存后的地图可以用于后续的导航或路径规划任务。
注意事项: 虽然 SLAM 是机器人导航的重要组成部分,但它与导航并不完全等同。SLAM 的作用主要是为机器人提供地图构建和即时定位功能,而导航系统则包括更多内容,如全局路径规划、局部避障等。SLAM 提供了机器人进行导航所需的地图和定位信息,但导航系统还需要综合其他模块来实现机器人从起点到目标点的自主运动。
(2)自身定位
在导航的起始阶段以及导航过程中的每一时刻,机器人都需要准确确定自身在环境中的位置。定位是导航的核心环节之一。如果机器人处于室外,使用 GPS 是一种便捷且有效的选择。然而,在室内、隧道、地下空间或其他屏蔽 GPS 信号的区域,GPS 信号变得微弱甚至完全不可用,因此需要使用其他技术进行定位。在这些环境中,SLAM(同步定位与地图构建)可以用于实现机器人自身的定位和地图构建。
此外,ROS 中提供了一个专门用于定位的功能包:amcl。
amcl(Adaptive Monte Carlo Localization)——自适应蒙特卡洛定位,是一种基于概率的方法,专门用于 2D 移动机器人的定位。它通过已知的地图和传感器数据来跟踪和估计机器人在地图中的位姿。amcl 使用粒子滤波器对机器人进行姿态跟踪,自适应采样(KLD 采样)机制动态调整粒子的数量,以提高计算效率和精度。amcl 的优点是能够在存在噪声的传感器数据下稳健地实现机器人定位。
(3)路径规划(全局 + 本地路径规划)
路径规划是导航中的关键步骤之一,它涉及如何让机器人从 A 点顺利到达 B 点。在此过程中,机器人需要根据全局地图规划出从起点到目标点的全局路线。同时,在导航过程中,还需要实时根据传感器反馈的环境变化(如出现的动态障碍物)调整当前的路线,避免碰撞并确保机器人到达目标位置。
在 ROS 中,路径规划功能主要由 move_base 包实现。它包含两个重要的规划器:
-
全局路径规划(global planner): 全局路径规划器根据机器人所在的位置、目标位置以及全局地图,计算一条从起点到目标点的最优路径。这通常使用 Dijkstra 或 A* 算法,它们通过对全局地图的遍历和权重计算来找到通往目标的最短路径。全局规划器生成的是一个宏观的全局路线,用于引导机器人朝目标移动。
-
本地路径规划(local planner): 在实际导航过程中,机器人可能会遇到未预见的障碍物,或者由于环境的变化无法沿全局最优路线前行。这时,本地路径规划器发挥作用。它基于机器人当前的位姿和周围环境,实时调整行进路线,通常使用动态窗口法(DWA,Dynamic Window Approaches)等算法进行局部避障,并在确保安全的前提下尽量保持与全局规划路线一致。
全局路径规划侧重于宏观的路线设计,而本地路径规划则侧重于微观的实时调整,两者结合能确保机器人既能朝着目标前进,又能灵活应对动态环境中的变化。
(4)运动控制(速度 + 方向)
在导航系统中,最终的输出是运动指令,这些指令告诉机器人以什么样的速度和方向运动。ROS 导航功能包集假定控制系统可以通过一个名为 /cmd_vel
的话题发布速度指令。
- cmd_vel 是 ROS 中标准的话题,发布的消息类型为
geometry_msgs/Twist
,该消息包含两个部分:- 线速度(linear velocity):表示机器人沿各轴(通常是 x 轴)方向的移动速度。
- 角速度(angular velocity):表示机器人绕 z 轴的旋转速度。
这些速度指令是基于机器人自身的基座坐标系(base_link)生成的,机器人需要通过订阅 /cmd_vel
话题,将发布的速度命令转化为实际电机的控制指令,并执行相应的移动或旋转。这部分通常由机器人的底盘控制器来完成。
(5)环境感知(传感器)
机器人导航离不开对环境的感知。环境感知系统通过多种传感器获取周围环境的实时数据,包括深度信息、速度信息等。这些信息为机器人定位、路径规划和避障提供了基础数据支持。
常用的传感器包括:
- 激光雷达(LiDAR):用于精确扫描周围环境的深度信息,生成点云数据,帮助机器人感知障碍物和空间的形状。
- 摄像头:用于获取环境的视觉信息,通常结合图像处理算法,用于 SLAM 或目标识别。
- RGB-D 摄像头:如 Kinect,既能获取彩色图像,又能提供深度信息,广泛应用于 3D SLAM。
- 编码器:用于测量电机的转速和机器人轮子的转动情况,生成**里程计(odometry)**信息。这对于定位和运动控制至关重要。
在导航功能包集中,环境感知模块是整个系统的基础模块之一。它为 SLAM、AMCL、move_base 等模块提供必要的环境数据,支持定位、建图和路径规划功能。不同传感器的数据在导航过程中通过传感器融合技术整合,提升机器人对复杂环境的感知能力,从而实现更加精准的导航。
1.2 导航之坐标系
(1)简介
定位是导航中的核心环节之一,其目的是确定机器人在某个参考坐标系中的位置和姿态。所谓定位,指的是在特定的参考坐标系中标定机器人的位置。比如,可以通过在机器人启动时设置一个参考点(如出发点),并以此为原点建立坐标系,然后通过该坐标系标注机器人的位置和姿态。
虽然定位的原理看似简单,但该参考坐标系并不是客观存在的。我们无法通过外部的上帝视角直接确定机器人的位姿,而是需要机器人通过自身感知,推导出参考系的原点并计算坐标系间的相对关系。实现这一过程常用的两种方式是:
-
里程计定位:通过实时收集机器人的速度信息来计算位置。基于速度信息和时间推导出机器人相对于父级参考系的位姿(位置和方向),并发布机器人在该参考系下的位置关系。
-
传感器定位:通过传感器(如激光雷达或摄像头)收集环境信息,通过匹配外部环境与已知地图来计算机器人相对于父级参考系的位置,并发布其坐标关系。
(2)特点
-
里程计定位:
- 优点:里程计定位基于速度信息推导位置,因此位置信息是连续的,没有离散的跳跃,数据平滑且稳定。
- 缺点:由于每一次的位置估计都基于前一时刻的位置,里程计定位会产生累计误差(随着时间推移误差会逐渐增加),不适合长时间或长距离的定位任务。
-
传感器定位:
- 优点:传感器定位通过直接匹配环境特征进行定位,通常比里程计定位更加精准,可以有效避免累计误差。
- 缺点:传感器定位会受到环境条件的影响,可能出现跳变(位置突然跳动)的情况。此外,在标志物较少或环境特征不明显的场景下,传感器定位的精度会大幅下降,可能导致误差增大或无法进行有效定位。
结合使用:由于两种定位方式各有优缺点,常见的做法是将里程计定位与传感器定位结合使用。通过里程计定位实现连续的位置估计,而传感器定位则用于修正里程计误差,确保长时间和复杂环境中的精确定位。
(3)坐标系变换
在导航系统中,机器人使用多个坐标系来描述位置和运动。一般来说,机器人自身的坐标系为根坐标系,通常称为 base_link
或 base_footprint
,这是机器人运动控制和感知的参考坐标系。
-
里程计定位:基于速度推导位置,父级坐标系通常称为
odom
。odom
坐标系描述了机器人相对于起始点(通常为机器人启动时的位置)的相对位移和旋转。 -
传感器定位:基于传感器的环境信息匹配,父级坐标系通常为
map
。map
坐标系用于描述机器人在已知地图中的绝对位置。
当里程计定位和传感器定位结合使用时,通常会同时使用 map
和 odom
两个父级坐标系。为了遵循坐标系变换的“单继承”原则,即每个坐标系只能有一个直接父级,ROS 导航中采用了以下坐标系转换结构:
map -> odom -> base_link 或 map -> odom -> base_footprint
这种层级结构表明:
map -> odom
:传感器定位修正了里程计定位中的误差,提供了机器人在全局地图中的位姿信息。
odom -> base_link
:里程计定位提供机器人在局部的精确位姿,通过时间推导出机器人相对于初始位置的变化。
这种转换关系确保了导航过程中,机器人能够通过 odom
实现局部定位和连续运动控制,同时通过 map
修正全局误差,提升整体定位精度。
1.3 导航条件说明
(1)硬件条件(三个主要的硬件限制)
-
差速驱动的轮式机器人:ROS 导航功能包集是为差速驱动的轮式机器人设计的。它假设机器人的底盘能够精确执行理想的运动命令,并能够实现预期的运动结果。具体的命令格式包括:
- x 轴速度分量(向前或向后移动)
- y 轴速度分量(通常在差速驱动下为零,因为机器人不具备侧向移动能力)
- 角速度(theta)分量(绕 z 轴的旋转速度)
在导航过程中,这些运动命令通过 /cmd_vel
话题发布,机器人需要能够根据这些命令控制自身的运动,执行路径规划和避障任务。
-
激光雷达(LiDAR):导航系统要求机器人装备一个单线激光雷达,通常安装在底盘上。激光雷达负责扫描周围环境,生成二维的点云数据。这些数据用于环境感知,帮助机器人实时构建地图(如在 SLAM 中)以及在定位过程中确定其在地图中的位置。激光雷达数据也是机器人避障和路径调整的关键信息来源。
-
机器人底盘形状和尺寸:ROS 的导航功能包集最初是为方形机器人设计的,因此方形或圆形的机器人可以获得最佳的导航性能。这是因为这些形状的机器人在移动和旋转时能够更好地适应导航中的几何计算。虽然导航系统可以兼容任意形状和大小的机器人,但对于较大的机器人,尤其是那些形状复杂或体积较大的机器人,它们可能会在狭窄空间中难以移动,导致导航性能下降。因此,机器人在设计时需要考虑其形状和尺寸,确保其在目标环境中能够高效导航。
(2)软件条件
-
安装 ROS:要使用 ROS 导航功能包集,首先需要在机器人或仿真环境中安装 ROS 以及相关的软件包。导航系统依赖于多个核心软件包(如
move_base
、amcl
和map_server
),这些软件包必须在系统中正确配置和运行。 -
基于仿真环境的测试:当前导航系统可以在仿真环境中测试,如使用 Gazebo 等仿真平台。在仿真环境中,机器人能够正常接收和处理
/cmd_vel
(运动控制命令)消息,并可以发布以下关键信息:- 里程计(Odometry)消息:由机器人的运动系统(如轮子编码器)生成,提供机器人相对位移和速度信息。通过里程计数据,导航系统能够跟踪机器人位置并计算运动轨迹。
- 传感器消息:激光雷达、摄像头或其他传感器的数据被实时发布,用于构建环境地图、识别障碍物,并提供避障和路径规划支持。
在仿真环境下,导航功能中的运动控制和环境感知模块已经可以成功运行。这意味着机器人可以通过接收速度命令调整运动路径,并利用传感器数据感知周围环境,完成定位、地图构建和路径规划等任务。
相关文章:

ROS理论与实践学习笔记——6 ROS机器人导航(仿真)
在 ROS 中,机器人导航(Navigation)是由多个功能包组合而成的系统,统称为导航功能包集(navigation stack)。它提供了一个全面的框架,使得移动机器人能够自主导航到指定目标点,同时避开…...

uniapp开发微信小程序,button的open-type=“share“ 分享给个人跳转到首页问题
当使用button标签带上open-type"share"属性,点击之后可分享当前页面给微信好友,但是分享之后朋友点开跳转到了首页问题。 需要使用 onShareAppMessage 函数 export default {onShareAppMessage(res) {if (res.from button) {// 来自页面内分…...

【jQuery】 jQuery基础及选择器介绍(基本选择器 层次选择器 属性选择器 过滤选择器)
文章目录 jQuery基础1. 优势2. 版本3. 基本语法4. 选择器基本选择器层次选择器属性选择器过滤选择器基本过滤选择器可见性过滤选择器 注意事项 jQuery基础 jQuery 是一个功能强大且易于使用的 JavaScript 库,它极大地简化了前端开发的工作。无论是 DOM 操作、事件处…...

网站在对抗机器人攻击的斗争中失败了
95% 的高级机器人攻击都未被发现,这一发现表明当前的检测和缓解策略存在缺陷。 这表明,虽然一些组织可能拥有基本的防御能力,但他们没有足够的能力应对更复杂的攻击。 例如利用人工智能和机器学习来模仿人类行为的攻击。 这些统计数据强调…...

Centos7 搭建logstash
下载并安装公共签名密钥: sudo rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch 创建一个名为 /etc/yum.repos.d/logstash.repo 的文件,并添加以下内容: [logstash-7.x] nameElastic repository for 7.x packages baseu…...

面试题:Redis(五)
1. 面试题 面试问 记录对集合中的数据进行统计 在移动应用中,需要统计每天的新增用户数和第2天的留存用户数; 在电商网站的商品评论中,需要统计评论列表中的最新评论; 在签到打卡中,需要统计一个月内连续打卡的用户数&…...

LeetCode18.四数之和
题目链接:18. 四数之和 - 力扣(LeetCode) 这道题是在三数之和上改编出来的,在写这道题之前可以尝试以下三数之和(15. 三数之和 - 力扣(LeetCode)); 1.常规解法…...

jmeter出参保存到文件,保存失败解决
1、添加JSON提取 2、添加beanshell FileWriter writer new FileWriter("C:/Users/xxx/Desktop/signUrl.csv", true); writer.write(vars.get("company_name")"\t"vars.get("signUrl")"\n"); writer.close(); 写文件的两个…...

黑龙江网络安全等级保护办理机制
黑龙江的网络安全等级保护机制根据《网络安全法》和相关法规要求,信息系统按照安全等级从低到高分为五级,分别为一般、重要、非常重要、特别重要和特别敏感。不同等级的信息系统必须实施相应的安全措施,以确保系统免受内外部威胁,…...

小红的行列式构造
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 小红希望你构造一个3阶行列式,满足每个元素的绝对值不小于1,且行列式的值等于xxx。你能帮帮她吗? 输入描述: 一个整数xxx −100≤x≤100 输出描…...

pyflink过滤kafka数据
from pyflink.table import (TableEnvironment, EnvironmentSettings)# 输入、输出、过滤条件 columns_in [ ... ]columns_out [ ... ] filter_condition "name 蒋介石 and sex 男"# 创建执行环境t_env TableEnvironment.create(EnvironmentSettings.in_stream…...

Webpack 完整指南
🌈个人主页:前端青山 🔥系列专栏:Webpack篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来webpack篇专栏内容:webpack介绍 目录 介绍 一、webpack 1.1、webpack是什么 1.2 webpack五个核心配置 1.…...

如何在 Ubuntu20.04 安装FTP Server vsftpd
1.安装: sudo apt-get install vsftpd 2.启动 sudo service vsftpd start //启动 sudo service vsftpd stop //停止 sudo service vsftpd restart //重新启动 3.打开配置文件 sudo nano /etc/vsftpd.conf 4.配置:限制在指定目录&…...

基于FPGA的DDS信号发生器(图文并茂+深度原理解析)
篇幅有限,本文详细源文件已打包 至个人主页资源,需要自取...... 前言 DDS(直接数字合成)技术是先进的频率合成手段,在数字信号处理与硬件实现领域作用关键。它因低成本、低功耗、高分辨率以及快速转换时间等优点备受认可。 本文着重探究基于 FPGA 的简易 DDS 信号发生器设…...

QT:绘制事件和定时器
1.绘制时针 xx.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTimer> #include<QPainter> #include <QTime>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpubl…...

【算法——递归回溯】
这个东西还是很重要的,直接决定了你的动态规划章节的学习深度 78. 子集 方法1: vector<vector<int>>V; void dfs(vector<int> v,vector<int> nums,int index) {if(indexnums.size()) V.push_back(v);else{v.push_back(nums[i…...

手机在网状态接口的使用和注意事项
手机在网状态接口是用于查询手机号码在运营商数据库中的实时状态的工具,这种接口在互联网金融、贷款、租赁、保险等相关行业中尤为重要,因为它可以帮助这些行业进行更有效的风控审核。以下是对手机在网状态接口的详细介绍: 一、手机在网状态…...

WebGl 使用uniform变量动态修改点的颜色
在WebGL中,uniform变量用于在顶点着色器和片元着色器之间传递全局状态信息,这些信息在渲染过程中不会随着顶点的变化而变化。uniform变量可以用来设置变换矩阵、光照参数、材料属性等。由于它们在整个渲染过程中共享,因此可以被所有使用该着色…...

Leetcode 划分字母区间
题目要求: 将字符串 s 划分成尽量多的片段,保证每个片段中出现的字母不会出现在其他片段中。 具体解释如下: 尽量多的片段:题目要求的是在划分过程中,我们要尽量让划分的片段数量最大化,而不是最少化。每…...

可编辑div遇到的那些事
在日常开发中有时可能会遇到input 或 textarea 不能满足的开发场景,比如多行输入的情况下,textarea 的右下角icon 无法去除, 所以此时可以使用div 设置可编辑状态,完成功能开发,在开发的过程中仍会遇到一下问题。 1,如…...

什麼是高速HTTP代理?
高速HTTP代理是一種用於加速和優化互聯網連接的技術。它通過在用戶和目標網站之間充當仲介伺服器,幫助用戶快速訪問網路資源。HTTP代理不僅可以提高訪問速度,還能提供一定程度的隱私保護和安全性。 高速HTTP代理的工作原理 HTTP代理伺服器位於用戶設備…...

三子棋(C 语言)
目录 一、游戏设计的整体思路二、各个步骤的代码实现1. 菜单及循环选择的实现2. 棋盘的初始化和显示3. 轮流下棋及结果判断实现4. 结果判断实现 三、所有代码四、总结 一、游戏设计的整体思路 (1)提供一个菜单让玩家选择人机对战、玩家对战或者退出游戏…...

HWS赛题 入门 MIPS Pwn-Mplogin(MIPS_shellcode)
解题所涉知识点: 泄露或修改内存数据: 堆地址:栈地址:栈上数据的连带输出(Stack Leak) && Stack溢出覆盖内存libc地址:BSS段地址: 劫持程序执行流程:[[MIPS_ROP]] 获得shell或flag&am…...

纯血鸿蒙启动公测,爱加密鸿蒙加固平台发布,助力鸿蒙应用安全运营!
鸿蒙系统打破了移动操作系统两极格局,实现操作系统核心技术的自主可控、安全可靠,在神州大地上掀起一波科技革新的浪潮,HarmonyOS NEXT成为大型企业必须要布局的应用系统之一。 HarmonyOS NEXT于10月8日正式开启公测,距离面向全体…...

MySQL中 truncate、drop和delete的区别
MySQL中 truncate、drop和delete区别 truncate 执行速度快,删除所有数据,但是保留表结构不记录日志事务不安全,不能回滚可重置自增主键计数器 drop 执行速度较快,删除整张表数据和结构不记录日志事务不安全,不能回…...

什么开放式耳机值得买?开放式耳机推荐排行榜!
长时间佩戴传统入耳式耳机有时可能会影响耳道健康,鉴于此,转而选择不入耳设计的开放式耳机就成了不少人的新倾向,它们有助于减少细菌滋生和耳道闷热的烦恼。为了帮助大家找到合适的选项,下面我将列举一些市面上口碑不错的开放式耳…...

Apache Doris的分区与分桶详解
目录 第一章 Doris介绍和分区分桶作用 1.1 Doris背景介绍 1.2 分区与分桶的意义 第二章 原理解析 2.1 分区机制 2.1.1 定义 2.1.2 类型 2.1.3 工作原理 2.2 分桶机制 2.2.1 概念 2.2.2 实现方式 2.2.3 与分区的关系 第三章 手动分区与自动分区对比 3.1 手动分区 …...

docker详解介绍+基础操作 (二)info详解
1 docker相关信息和优化配置 1)查看docker版本详解 rootzz:~# docker version Client: Docker Engine - CommunityVersion: 27.3.1API version: 1.47Go version: go1.22.7Git commit: ce12230Built: Fri Sep 20 11:40:…...

C0023.在Clion中创建控件,对控件进行提升为自定义控件的步骤
新建Ui界面文件 修改新生成的ui文件头文件 关闭之前打开的ui文件,如上图Qt Designer中打开的,然后修改新生成的ui文件对应的头文件,改成自己需要的控件类即可。 提升控件为自定义类 将如下头文件中的类名和头文件名输入到提升窗口中&#…...

探索 C# 常用第三方库与框架
在 C# 开发中,第三方库和框架极大地提高了开发效率和代码质量。通过这些库,开发者可以快速处理 JSON 数据、简化对象映射、记录日志、以及高效地与数据库交互。本文将介绍四个常用的 C# 第三方库:Newtonsoft.Json、AutoMapper、NLog/Serilog …...