代码目录
feature_tracker文件
src文件
feature_tracker_node.cpp(光流)
feature_tracker_node.cpp 文件是其中的一个节点,主要功能是提取输入图像中的特征点并进行跟踪。
在该节点中,首先订阅了来自相机的图像话题,然后对每帧图像进行特征提取和跟踪。具体而言,通过使用 OpenCV库提供的功能,将每帧图像转换为灰度图像,并使用 FAST 特征检测算法提取图像中的关键点。然后,对于每一个关键点,利用 KLT算法在前一帧图像中进行跟踪,并计算其光流信息(即点的移动像素数)。最终,根据得到的光流信息,对关键点进行筛选并发布当前帧图像中的有效关键点。
需要注意的是,在实际应用中,为了提高跟踪效果和鲁棒性,除了上述基本的特征提取和跟踪操作外,还需要考虑一些细节问题,比如运动估计(包括相机运动和特征点运动)、特征点筛选和描述子匹配等方面的处理。而feature_tracker_node.cpp 只是其中的一个简化版本,对于特定的应用场景和硬件环境可能需要进行一定程度的修改和优化。
坐标系
在一个视觉slam中,一般只有一种坐标系且一般为右手坐标系,在VIIO中,世界坐标系的原点一般为相机的第一帧当做世界坐标系原点,且z轴与重力方向对其。
光流vs描述子匹配
光流
描述子
注意:光流适合帧间匹配,且相对于计算描述子速度较快,但是光流在回环检测时由于帧间时间相隔太远,不适合用流光
视觉前端——特征点光流
代码部分
位置:
vins_mono/src/vins-mono-master/feature_tracker/src/feature_tracker_node.cpp
第235行主函数:
ros::init(argc, argv, "feature_tracker"); // ros节点初始化
ros::NodeHandle n("~"); // 声明一个句柄,~代表这个节点的命名空间
ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Info); // 设置ros log级别
readParameters(n); //; 读取config.yaml配置文件,这里仅仅读取和相机有关的参数
//这个函数的主要作用是从配置文件中读取参数,并将这些参数存储到对应的变量中,过程如下面-------------内容
---------------------------readParameters函数(头)----------------------------------
位置:
feature_tracker\src\parameters.cpp
第40行void readParameters(ros::NodeHandle &n)函数:
std::string config_file;
// 首先获得配置文件的路径
//; 这里的config_file就是ros参数服务器中的参数变量名称,最后得到的就是config.yaml文件的带路径的文件名
config_file = readParam<std::string>(n, "config_file");
其中的readParam函数说明(feature_tracker\src\parameters.cpp):
template <typename T>
T readParam(ros::NodeHandle &n, std::string name)
{
T ans;
if (n.getParam(name, ans)) //; n.getParam是ros的内置函数,用来读入ROS的参数服务器中的参数
{
ROS_INFO_STREAM("Loaded " << name << ": " << ans);
}
else
{
ROS_ERROR_STREAM("Failed to load " << name);
n.shutdown(); //; 没有读取到节点关闭
}
return ans;//返回ans的总路径值
}
-----------------------------------------------
template <typename T>说明:
类型模板参数 T 是 C++ 中的一个模板参数,它表示一个占位符,可以在模板类、函数或方法中用来代替一种特定的数据类型。在模板实例化时,将会用实际的数据类型替换 T,从而实例化出一个具体的类或函数。
在这段代码中,函数 readParam 使用了类型模板参数 T,因为我们不确定要读取的参数是什么数据类型,可以是整数、浮点数、字符串或其它任何数据类型。因此,我们需要使用类型模板参数 T 来表示这个未知的数据类型。当调用 readParam 函数时,需要为类型模板参数 T 提供一个具体类型
第40行void readParameters(ros::NodeHandle &n)函数(接上一部分):
// 使用opencv的yaml文件接口来读取文件
//创建了一个 cv::FileStorage 类的对象 fsSettings,并传入两个参数:config_file 和 cv::FileStorage::READ
//其中,config_file 是配置文件的路径,cv::FileStorage::READ 表示以只读方式打开该文件
cv::FileStorage fsSettings(config_file, cv::FileStorage::READ);
if(!fsSettings.isOpened())
{
//通过调用 isOpened() 方法可以检查文件是否成功打开。如果文件打开失败,则会输出一条错误信息
std::cerr << "ERROR: Wrong path to settings" << std::endl;
}
std::string VINS_FOLDER_PATH = readParam<std::string>(n, "vins_folder");
//注意这里仅仅读取了和相机有关的参数,IMU有关的参数都没有读取
//拿Euroc作为例子,读取的为VINS-Mono-CC_Comments-master\config\euroc文件夹下的yaml文件
fsSettings["image_topic"] >> IMAGE_TOPIC;
fsSettings["imu_topic"] >> IMU_TOPIC;
MAX_CNT = fsSettings["max_cnt"];//特征跟踪中的最大特征数
MIN_DIST = fsSettings["min_dist"];//两个特征点之间的最短距离,主要防止特征点过于集中
ROW = fsSettings["image_height"];
COL = fsSettings["image_width"];
FREQ = fsSettings["freq"]; //; 这里的freq是发给后端的频率,在Euroc配置文件中有参数
F_THRESHOLD = fsSettings["F_threshold"];//像素
SHOW_TRACK = fsSettings["show_track"];//是否对图像可视化
EQUALIZE = fsSettings["equalize"]; //; 是否做均衡化处理
FISHEYE = fsSettings["fisheye"];
//是否是鱼眼相机
if (FISHEYE == 1)
FISHEYE_MASK = VINS_FOLDER_PATH + "config/fisheye_mask.jpg";
CAM_NAMES.push_back(config_file);
WINDOW_SIZE = 20; //滑窗中图像帧的数量
STEREO_TRACK = false;//是否启用双目跟踪模式。当双目跟踪被开启时,系统会使用双目视觉进行位姿估计
FOCAL_LENGTH = 460;//这个变量表示相机标定的焦距,即相机内参矩阵中的fx or fy,VINS-Mono 支持从标定文件中提取内参信息,因此这个值不一定是准确的,仅在没有标定数据的情况下作为默认值使用。
PUB_THIS_FRAME = false; //; 默认这一帧图像不发布
if (FREQ == 0)
FREQ = 100;//这个变量表示系统运行的频率,即每秒处理多少帧图像
fsSettings.release();//通过 fsSettings.release() 释放了一些资源。这一行代码的作用是关闭配置文件,并释放内存资源
---------------------------readParameters函数(尾)----------------------------------
位置:
feature_tracker/src/feature_tracker.cpp
约301行
void FeatureTracker::readIntrinsicParameter(const string &calib_file)
{
ROS_INFO("reading paramerter of camera %s", calib_file.c_str());
//; 读到的相机内参赋给m_camera
m_camera = CameraFactory::instance()->generateCameraFromYamlFile(calib_file);
}