1.Cartographer源码详解|(2)Cartographer_ros
2.详解flink中Look up维表的函数函数使用
3.Redis 源码剖析 3 -- redisCommand
4.Linux内核源码解析---mount挂载原理
Cartographer源码详解|(2)Cartographer_ros
上一篇文章深入分析了传感器数据的流向,接下来让我们继续探讨传感器格式的源码转换与类型变换。这部分内容在sensor_bridge.cc文件中。教程在处理传感器的函数函数坐标变换时,我们需要运用三维空间刚体运动的源码知识,先进行简要回顾,教程web2019源码以助于理解代码。函数函数
三维空间刚体运动涉及向量内积与外积。源码向量内积的教程计算公式如下,表示两个向量的函数函数点乘。向量外积则是源码一个向量,其方向垂直于两个向量,教程大小为两向量张成四边形的函数函数有向面积,计算公式如下。源码
旋转和平移是教程欧氏变换的两个关键部分。旋转涉及单位正交基的变换,形成旋转矩阵(Rotation matrix),该矩阵的各分量由两组基之间的内积组成,反映了旋转前后同一向量坐标的addcookie源码变化关系。平移则通过向旋转后的坐标中加入平移向量t实现。通过旋转矩阵R和平移向量t,我们可以完整描述欧氏空间中的坐标变换关系。
为了简化变换过程,引入齐次坐标和变换矩阵。在三维向量末尾添加1形成四维向量,进行线性变换。变换矩阵T能够将两次变换叠加简化为一个操作,便于后续计算。
Cartographer的坐标转换程序位于transform文件夹下的rigid_transform中,用于求解变换矩阵的逆。
在sensor_bridge类中,构造函数将传入配置参数,对里程计数据进行处理。首先将ros时间转换为ICU时间,然后利用tf_bridge_.LookupToTracking函数找到tracking坐标系与里程计child_frame_id之间的坐标变换。在ToOdometryData函数中,将里程计的parseq 源码footprint的pose转换为tracking_frame的pose,并最终将结果转换为carto::sensor::OdometryData的数据类型。
HandleOdometryMessage函数将传感器数据类型与坐标系转换完成后,调用trajectory_builder_->AddSensorData进行数据处理。对于雷达数据,首先转换为点云格式,然后对点云进行坐标变换,并调用trajectory_builder_->AddSensorData进行数据处理。
IMU数据处理中,要求平移分量小于1e-5,然后调用trajectory_builder_->AddSensorData对数据进行处理。
在雷达数据处理部分,首先将点云数据分段,然后传给HandleRangefinder处理,将点云坐标变换到tracking_frame坐标系下,调用trajectory_builder_->AddSensorData函数进行数据处理。
总结本章内容,我们详细解析了SensorBridge类,对传感器数据进行了转换和传输。removeview源码通过Node类、MapBuilderBridge类和SensorBridge类,我们对Cartographer_ros部分的代码有了基本了解。接下来,我们将深入学习cartographer。
详解flink中Look up维表的使用
背景
在流式计算领域,维表是一种常用概念,主要用于SQL的JOIN操作,以实现对流数据的补充。比如,我们的数据源stream是订单日志,日志中仅记录了订单商品的ID,缺乏其他信息。但在数据分析时,我们需要商品名称、价格等详细信息,这时可以通过查询维表对数据进行补充。
维表通常存储在外部存储中,cloudera 源码如MySQL、HBase、Redis等。本文以MySQL为例,介绍Flink中维表的使用。
LookupableTableSource
Flink提供LookupableTableSource接口,用于实现维表功能。通过特定的key列查询外部存储,获取相关信息,以补充stream数据。
LookupableTableSource有三个方法
在Flink中,实现LookupableTableSource接口的主要有四个类:JdbcTableSource、HBaseTableSource、CsvTableSource和HiveTableSource。本文以JDBC为例,讲解如何进行维表查询。
实例讲解
以下是一个示例,首先定义stream source,使用Flink 1.提供的datagen生成数据。
我们模拟生成用户数据,范围在1-之间。
datagen具体的使用方法请参考:
聊聊Flink 1.中的随机数据生成器-DataGen connector
然后创建一个MySQL维表信息:
该MySQL表中样例数据如下:
最后执行SQL查询,流表关联维表:
结果示例如下:
对于维表中存在的数据,已关联出来,对于维表中不存在的数据,显示为null。
完整代码请参考:github.com/zhangjun0x...
源码解析JdbcTableSource
以JDBC为例,看看Flink底层是如何实现的。
JdbcTableSource#isAsyncEnabled方法返回false,即不支持异步查询,因此进入JdbcTableSource#getLookupFunction方法。
最终构造一个JdbcLookupFunction对象。
JdbcLookupFunction
接下来看看JdbcLookupFunction类,它是TableFunction的子类,具体使用可参考以下文章:
Flink实战教程-自定义函数之TableFunction
TableFunction的核心是eval方法,在该方法中,主要工作是使用多个keys拼接成SQL查询数据,首先查询缓存,缓存有数据则直接返回,缓存无数据则查询数据库,并将查询结果返回并放入缓存。下次查询时,直接查询缓存。
为什么要加缓存?默认情况下不开启缓存,每次查询都会向维表发送请求,如果数据量较大,会给存储维表的系统造成压力。因此,Flink提供了LRU缓存,查询维表时,先查询缓存,缓存无数据则查询外部系统。如果某个数据查询频率较高,一直被命中,则无法获取新数据。因此,缓存需要设置超时时间,超过这个时间则强制删除该数据,查询外部系统获取新数据。
如何开启缓存?请参考JdbcLookupFunction#open方法:
即cacheMaxSize和cacheExpireMs需要同时设置,构造缓存对象cache来缓存数据。这两个参数对应的DDL属性为lookup.cache.max-rows和lookup.cache.ttl。
对于具体的缓存大小和超时时间的设置,用户需要根据自身情况自行定义,在数据准确性和系统吞吐量之间进行权衡。
Redis 源码剖析 3 -- redisCommand
Redis 使用 redisCommand 结构体处理命令请求,其内包含一个指向对应处理函数的 proc 指针。redisCommandTable 是一个存储所有 Redis 命令的数组,位于 server.c 文件中。此数组通过 populateCommandTable() 函数填充,该函数将 redisCommandTable 的内容添加到 server.commands 字典,将 Redis 支持的所有命令及其实现整合。
populateCommandTable() 函数中包含 populateCommandTableParseFlags() 子函数,用于将 sflags 字符串转换为对应的 flags 值。lookupCommand*() 函数族负责从 server.commands 中查找相应的命令。
Linux内核源码解析---mount挂载原理
Linux磁盘挂载命令"mount -t xxx /dev/sdb1 abc/def/"的底层实现原理非常值得深入了解。从内核初始化的vfsmount开始说起。
内核初始化过程中,主要关注"main.c"中的vfs_caches_init函数,这个方法与mount紧密相连。接着,跟进"mnt_init"和"namespace.c",关键在于最后的三个函数,它们控制了挂载过程的实现。
在"mount.c"中,sysfs_fs_type结构中包含了获取超级块的函数指针,而"init_rootfs"则注册了rootfs类型的文件系统。挂载系统调用sys_mount中的dev_name, dir_name和type参数,分别对应设备名称、挂载目录和文件系统类型。
"do_mount"方法通过path_lookup收集挂载目录信息,创建nameidata结构,然后调用do_add_mount进行实际挂载。这个过程涉及do_kern_mount和graft_tree,尽管具体实现较为复杂,但核心在于创建vfsmount并将其与namespace关联。
在"graft_tree"中的判断逻辑中,vfsmount被创建并与其父mount和挂载目录的dentry建立关系。在"attach_mnt"方法中,新vfsmount与现有结构关联,设置挂载点和父vfsmount,最终形成挂载的概念,即为设备分配vfsmount,并将其与指定目录和vfsmount结合,成为vfs系统的一部分。