小秋SLAM入门实战

小秋SLAM入门实战

时间同步原理

时间同步是通过寻找与第一个激光雷达数据时间戳最接近的第二个激光雷达数据来实现的。这是基于假设:两个雷达虽然独立工作,但它们的数据可以通过时间戳对齐来达到时间同步。

  • 时间戳对比:通过计算两个雷达数据之间的时间差,可以找出时间上最接近的一对数据。这对于确保数据在时间上的一致性非常重要,尤其是在需要将这些数据结合起来进行进一步处理的情况下(例如,在机器人导航和地图构建中)。

  • 时间阈值判断:使用一个阈值(options_.merge_sync_time_)来决定是否接受找到的同步数据。这个阈值定义了可接受的最大时间差。如果实际时间差大于这个阈值,那么这对数据就被认为是不同步的。

  • 数据缓冲区管理:为了维护有效的数据集,函数在必要时会从第二激光雷达数据缓冲区中删除过时或已经处理过的数据。

这种基于时间戳的同步方法在处理来自多个独立传感器的数据时非常有效,特别是在这些传感器不能被精确地同步启动或具有不同的采样率时。通过这种方式,可以确保多传感器系统中的数据在时间上保持一致,从而为后续的数据融合和分析提供了一个稳固的基础。

代码实现

#include <iostream>
#include <limits>
#include <cmath>
#include <vector>
#include <mutex>

void findSyncSecondLaserData(const sensor_prts::LaserData &laser, sensor_prts::LaserData& sync_laser) {
    std::unique_lock<std::mutex> lk(second_laser_mtx_);
    double min_dt = std::numeric_limits<double>::max();
    auto min_it = second_laser_buf_.end();
    for (auto it = second_laser_buf_.begin(); it != second_laser_buf_.end(); ++it) {
        double dt = fabs(it->header().timestamp() - laser.header().timestamp());
        if (dt < min_dt) {
            min_dt = dt;
            min_it = it;
        }
    }
    if (min_it == second_laser_buf_.end()) {
        std::cout << "not find sync laser !" << std::endl;
        return;
    }
    if (min_dt > options_.merge_sync_time_) {
        std::cout << "not find sync laser, t1-t2-mindt[" << laser.header().timestamp() << ", " << min_it->header().timestamp() << ", " << min_dt << "]" << std::endl;
        if (min_it->header().timestamp() < laser.header().timestamp()) {
            second_laser_buf_.erase(second_laser_buf_.begin(), std::next(min_it));
        }
        return;
    }
    sync_laser = *min_it;
    std::cout << "find sync laser[" << laser.header().timestamp() << "-" << sync_laser.header().timestamp() << "]" << std::endl;
    second_laser_buf_.erase(second_laser_buf_.begin(), min_it);
}

代码解读

这段代码的主要功能是在一个集合中找到与给定激光数据时间戳最接近的激光数据,并进行一系列操作。下面是逐功能的解释:

  1. 锁定互斥量

    std::unique_lock<std::mutex> lk(second_laser_mtx_);
    

    使用 std::unique_lock 锁定互斥量 second_laser_mtx_,确保对共享资源 second_laser_buf_ 的访问是线程安全的。

  2. 初始化最小时间差和迭代器

    double min_dt = std::numeric_limits<double>::max();
    auto min_it = second_laser_buf_.end();
    

    min_dt 初始化为最大双精度浮点数,用于存储找到的最小时间差。min_it 初始化为指向 second_laser_buf_ 结束的迭代器。

  3. 遍历查找最接近的激光数据

    for (auto it = second_laser_buf_.begin(); it != second_laser_buf_.end(); ++it) {
        double dt = fabs(it->header().timestamp() - laser.header().timestamp());
        if (dt < min_dt) {
            min_dt = dt;
            min_it = it;
        }
    }
    

    遍历 second_laser_buf_,计算每个元素的时间戳与给定激光数据 laser 的时间戳之间的绝对时间差。更新最小时间差 min_dt 和相应的迭代器 min_it

  4. 检查是否找到匹配项

    if (min_it == second_laser_buf_.end()) {
        std::cout << "not find sync laser !" << std::endl;
        return;
    }
    

    如果没有找到匹配的激光数据(即 min_it 仍然指向 second_laser_buf_.end()),则输出信息并退出函数。

  5. 检查时间差是否超过阈值

    if (min_dt > options_.merge_sync_time_) {
        std::cout << "not find sync laser, t1-t2-mindt[" << laser.header().timestamp() 
                  << ",
    
    

" << min_it->header().timestamp() << ", " << min_dt << “]” << std::endl;
if (min_it->header().timestamp() < laser.header().timestamp()) {
second_laser_buf_.erase(second_laser_buf_.begin(), std::next(min_it));
}
return;
}

这一部分检查最小时间差 `min_dt` 是否超过预设阈值 `options_.merge_sync_time_`。如果是,输出相关信息,并在第二激光数据时间戳早于第一个激光数据时,从 `second_laser_buf_` 中删除直到 `min_it` 指向的元素(包含该元素)。然后退出函数。

6. **同步激光数据**:
```cpp
sync_laser = *min_it;
std::cout << "find sync laser[" << laser.header().timestamp() 
          << "-" << sync_laser.header().timestamp() << "]" << std::endl;

将找到的最接近的激光数据(由 min_it 指向)赋值给 sync_laser,然后输出相关信息。这一步骤实现了激光数据的同步。

  1. 更新激光数据缓冲区
    second_laser_buf_.erase(second_laser_buf_.begin(), min_it);
    
    second_laser_buf_ 中删除已经处理过的数据,直到找到的同步数据(不包括找到的同步数据本身)。这样做是为了保持缓冲区的最新状态,以便未来的同步操作。

这段代码的主要目的是在两个激光雷达数据集中找到时间上最接近的数据对,以便进行进一步的数据处理和分析。这在多传感器数据融合中是一个重要步骤,特别是在精确的时间同步对于后续操作至关重要的场景中。

01-13 19:42