标题: 如何解读fast-lio2中的IKFoM
中的宏定义
作者: 边城量子 ( shihezichen@live.cn )
KeyMessage 1: 本文讲解如何解析 fast-lio2 中的 IKFOM 的宏定义.
KeyMessage 2: 本文中一开始有较多宏解析过程的介绍, 若想直接看解析后的结果, 可以根据右边侧边栏上的 目录导引直接跳转到对应的章节, 如"Step1..." 、"Step2..."、"Step3..." 看最后解析完毕的C++代码.
Keymessage 3: 编写宏时, 会涉及大量boost的宏模板编程技术, 如BOOST_PP_SEQ_xxx 等; 但是在解读宏代码时, 则不需要了解太多 boost 的技术。 本文无需涉及 boost 库即可解读宏代码.
现象 : build_manifold.hpp 中存在大量的宏定义
-
文件中定义了大量的宏,举例如下:
#ifndef PARSED_BY_DOXYGEN //////// internals ////// #define MTK_APPLY_MACRO_ON_TUPLE(r, macro, tuple) macro tuple #define MTK_TRANSFORM_COMMA(macro, entries) BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_TRANSFORM_S(1, MTK_APPLY_MACRO_ON_TUPLE, macro, entries)) ...
- 其中的代码
#ifndef PARSED_BY_DOXYGEN
表示接下来的代码,将不是由DOXYGEN
工具来解析,而是由C++预处理来处理 - 所谓的C++预处理来处理,即使用宏定义展开的方式来生成代码
- 大量使用到了Boost库的预处理(PP: preprocessor)模板元库的宏定义, 例如 BOOST_PP_SEQ_ENUM 宏用来将一个序列转换成数组, BOOST_PP_SEQ_TRANSFORM_S 宏则用来产生一个序列.
- 这些宏层层嵌套引用, 最终组成了若干个更大的宏定义, 例如:
MTK_BUILD_MANIFOLD
暂时先不需要细究
build_manifold.hpp
中的代码中宏定义细节, 也不需要去深究其中Boost的预处理宏模板元编程细节.只需要知道此文件中定义的是一堆宏定义即可,我们后续将使用一些方法,把宏展开(包括boost宏),那时就可以看得更清楚;
- 其中的代码
问题 : 谁在使用build_mainfold.hpp
中的宏定义?
现已知build_mainfold.hpp
是个充满了宏定义的头文件,那又是谁使用到了它?
- 通过走读代码, 发现使用到
build_manifold.hpp
的是use-ikfom.hpp
文件 - 在
use-ikfom.hpp
中有如下代码:typedef MTK::vect<3, double> vect3; typedef MTK::SO3<double> SO3; typedef MTK::S2<double, 98090, 10000, 1> S2; typedef MTK::vect<1, double> vect1; typedef MTK::vect<2, double> vect2; MTK_BUILD_MANIFOLD(state_ikfom, ((vect3, pos)) ((SO3, rot)) ((SO3, offset_R_L_I)) ((vect3, offset_T_L_I)) ((vect3, vel)) ((vect3, bg)) ((vect3, ba)) ((S2, grav)) ); MTK_BUILD_MANIFOLD(input_ikfom, ((vect3, acc)) ((vect3, gyro)) ); ...
- 可以看出,
use-ikfom.hpp
代码中, 在不断的使用MTK_BUILD_MANIFOLD
宏来生成代码 - 当某个文件包含了
use-ikfom.hpp
时,这些宏就会被展开对应的c++代码 - 通过查看代码可以发现,使用了
use-ikfom.hpp
的是IMU_Processing.hpp
文件
- 可以看出,
问题: 如何展开use-ikfom.hpp
中的宏?
如何展开use-ikfom.hpp
中的宏, 看到其对应的C++代码的样子?
使用手工逐个从底层宏到上层宏, 做宏展开, 这当然是一种手段, 但这种方法费时费力, 且容易出错, 此处不予考虑。
下面将使用C++预处理能力的方式展开宏, 相比之下较为自动和准确。分为如下几个环节:
-
第一个环节: 准备宏代码分析的Project和相关的小工具代码
-
Step 1: 使用IDE建立一个最简单的C++工程, 把 include 目录下的文件都放进去
备注: 下图中红色框起来的四个文件是新增的文件, 其余的均为fast-lio2 已有的文件. 新增的文件此时还不存在, 可先添加其余的文件.
-
Step 2: 为避免IDE编译时报错,需再建立一个
main.cpp
文件, 里面存放main()
函数。 由于我们只需要做编译期推导,因此函数内部可以没有实现, 如下:
#include "use-ikfom.hpp" int main() { return 0; }
- Step 3: 再准备一些宏展开的小工具,本质上是一些辅助宏解析和展示的C++代码, 放入到
main.cpp
文件中, 此时main.cpp
变为:
#include "use-ikfom.hpp" // 定义用于显示宏内容的宏代码 #define M(x) #x #define DIS(x) #x"=>\n\t"M(x) // Start: 如下区域用于对IKFoM的宏进行展开 // End int main() { return 0; }
备注: 以上用到了宏的基本知识, 例如#等。 若需对C++宏的基本概念有进一步理解, 可参见帖子: C/C++宏基本概念
-
-
第二个环节,准备C++代码格式化工具:
主要目的是用于对C++代码进行格式化,使之可读。
可以使用IDE的代码格式化功能,或者在线的代码格式化功能,例如: tools.jb51.net/code/jb51_c…
开始解析
准备工作完成后, 就可以开始解析 IKFoM
中的宏了。
在build_mainfold.hpp
中, 有如下三段宏, 下面会分别进行展开:
MTK_BUILD_MANIFOLD(input_ikfom,
((vect3, acc))
((vect3, gyro))
);
MTK_BUILD_MANIFOLD(state_ikfom,
((vect3, pos))
((SO3, rot))
((SO3, offset_R_L_I))
((vect3, offset_T_L_I))
((vect3, vel))
((vect3, bg))
((vect3, ba))
((S2, grav))
);
MTK_BUILD_MANIFOLD(process_noise_ikfom,
((vect3, ng))
((vect3, na))
((vect3, nbg))
((vect3, nba))
);
Step1:解析 input_ikfom
对应的宏
use-ikfom.hpp
中的存在如下宏定义的原始代码片段:
MTK_BUILD_MANIFOLD(input_ikfom,
((vect3, acc))
((vect3, gyro))
);
它宏展开是怎样的形式呢?
可在 main.cpp
中Start
和 End
区域中增加宏展开语句, 新增的代码如下形式:
// Start: 如下区域用于对IKFoM的宏进行展开
#pragma message(DIS( \
MTK_BUILD_MANIFOLD(input_ikfom, \
((vect3, acc)) \
((vect3, gyro)) \
) \
))
// End
- 可以看到,代码本质是把宏定义放到 #pragma message(DIS( )) 中进行展开
- 针对以上代码进行编译(注意是编译并不链接,如果是gcc可以用gcc –E),以看到编译阶段的输出如下:
MTK_BUILD_MANIFOLD(input_ikfom, ((vect3, acc)) ((vect3, gyro)) )=>
struct input_ikfom { typedef input_ikfom self; std::vector<std::pair<int, int> > S2_state; std::vector<std::pair<int, int> > SO3_state; std::vector<std::pair<std::pair<int, int>, int> > vect_state; MTK_ENTRIES_OUTPUT_I ( 2, (vect3, acc) , ((vect3, gyro)) (~), 0, 0, S2_state, SO3_state ) MTK_ENTRIES_OUTPUT_I ( 1, (vect3, gyro) , (~), 0 + BOOST_PP_TUPLE_ELEM_2_0 (vect3, acc)::DOF, 0 + BOOST_PP_TUPLE_ELEM_2_0 (vect3, acc)::DIM, S2_state, SO3_state) input_ikfom ( BOOST_PP_SEQ_ENUM_2 (const vect3& acc = vect3()) (const vect3& gyro = vect3()) ) : BOOST_PP_SEQ_ENUM_2 (acc(acc)) (gyro(gyro)) {} int getDOF() const { return DOF; } void boxplus(const MTK::vectview<const scalar, DOF> & __vec, scalar __scale = 1 ) { MTK_BOXPLUS (vect3, acc) MTK_BOXPLUS (vect3, gyro) } void oplus(const MTK::vectview<const scalar, DIM> & __vec, scalar __scale = 1 ) { MTK_OPLUS (vect3, acc) MTK_OPLUS (vect3, gyro) } void boxminus(MTK::vectview<scalar,DOF> __res, const input_ikfom& __oth) const { MTK_BOXMINUS (vect3, acc) MTK_BOXMINUS (vect3, gyro) } friend std::ostream& operator<<(std::ostream& __os, const input_ikfom& __var){ return __os MTK_OSTREAM (vect3, acc) MTK_OSTREAM (vect3, gyro) ; } void build_S2_state(){ MTK_S2_state (vect3, acc) MTK_S2_state (vect3, gyro) } void build_vect_state(){ MTK_vect_state (vect3, acc) MTK_vect_state (vect3, gyro) } void build_SO3_state(){ MTK_SO3_state (vect3, acc) MTK_SO3_state (vect3, gyro) } void S2_hat(Eigen::Matrix<scalar, 3, 3> &res, int idx) { MTK_S2_hat (vect3, acc) MTK_S2_hat (vect3, gyro) } void S2_Nx_yy(Eigen::Matrix<scalar, 2, 3> &res, int idx) { MTK_S2_Nx_yy (vect3, acc) MTK_S2_Nx_yy (vect3, gyro) } void S2_Mx(Eigen::Matrix<scalar, 3, 2> &res, Eigen::Matrix<scalar, 2, 1> dx, int idx) { MTK_S2_Mx (vect3, acc) MTK_S2_Mx (vect3, gyro) } friend std::istream& operator>>(std::istream& __is, input_ikfom& __var){ return __is MTK_ISTREAM (vect3, acc) MTK_ISTREAM (vect3, gyro) ; } };
- 上文的第二行C++代码是比较长的,把它拷贝出来,并使用代码格式化工具进行格式化,可知其对应如下代码:
struct input_ikfom
{
typedef input_ikfom self;
std::vector<std::pair<int, int> > S2_state;
std::vector<std::pair<int, int> > SO3_state;
std::vector<std::pair<std::pair<int, int>, int> > vect_state;
MTK_ENTRIES_OUTPUT_I ( 2, (vect3, acc) , ((vect3, gyro)) (~), 0, 0, S2_state, SO3_state )
MTK_ENTRIES_OUTPUT_I ( 1, (vect3, gyro) , (~), 0 + BOOST_PP_TUPLE_ELEM_2_0 (vect3, acc)::DOF, 0 + BOOST_PP_TUPLE_ELEM_2_0 (vect3, acc)::DIM, S2_state, SO3_state)
input_ikfom ( BOOST_PP_SEQ_ENUM_2 (const vect3& acc = vect3()) (const vect3& gyro = vect3()) ) : BOOST_PP_SEQ_ENUM_2 (acc(acc)) (gyro(gyro))
{
}
int getDOF() const
{
return DOF;
}
void boxplus(const MTK::vectview<const scalar, DOF> & __vec, scalar __scale = 1 )
{
MTK_BOXPLUS (vect3, acc) MTK_BOXPLUS (vect3, gyro)
}
void oplus(const MTK::vectview<const scalar, DIM> & __vec, scalar __scale = 1 )
{
MTK_OPLUS (vect3, acc) MTK_OPLUS (vect3, gyro)
}
void boxminus(MTK::vectview<scalar,DOF> __res, const input_ikfom& __oth) const
{
MTK_BOXMINUS (vect3, acc) MTK_BOXMINUS (vect3, gyro)
}
friend std::ostream& operator<<(std::ostream& __os, const input_ikfom& __var)
{
return __os MTK_OSTREAM (vect3, acc) MTK_OSTREAM (vect3, gyro) ;
}
void build_S2_state()
{
MTK_S2_state (vect3, acc) MTK_S2_state (vect3, gyro)
}
void build_vect_state()
{
MTK_vect_state (vect3, acc) MTK_vect_state (vect3, gyro)
}
void build_SO3_state()
{
MTK_SO3_state (vect3, acc) MTK_SO3_state (vect3, gyro)
}
void S2_hat(Eigen::Matrix<scalar, 3, 3> &res, int idx)
{
MTK_S2_hat (vect3, acc) MTK_S2_hat (vect3, gyro)
}
void S2_Nx_yy(Eigen::Matrix<scalar, 2, 3> &res, int idx)
{
MTK_S2_Nx_yy (vect3, acc) MTK_S2_Nx_yy (vect3, gyro)
}
void S2_Mx(Eigen::Matrix<scalar, 3, 2> &res, Eigen::Matrix<scalar, 2, 1> dx, int idx)
{
MTK_S2_Mx (vect3, acc) MTK_S2_Mx (vect3, gyro)
}
friend std::istream& operator>>(std::istream& __is, input_ikfom& __var)
{
return __is MTK_ISTREAM (vect3, acc) MTK_ISTREAM (vect3, gyro) ;
}
};
-
这段代码本质上是定义了一个
struct
, 名为input_ikfom
-
在结构体中定义了一些成员变量, 如
S2_state
、SO3_state
等, 还定义了一些方法,如boxplus
、oplus
、build_SO3_state
、S2_hat
等 -
遗留问题: 可以看到,生成的代码中, 依然还有一些深层次宏并没有被展开,例如
MTK_ENTRIES_OUTPUT_I
、BOOST_PP_SEQ_ENUM_2
、BOOST_PP_TUPLE_ELEM_2_0
、MTK_BOXPLUS
等. 原因是编译器在编译期进行宏展开时,如果遇到参数中宏定义有#或##符号进行连接时, 就会停止这一层的宏展开. -
如何解决? 没关系, 针对这种情况, 依然可以继续使用上面的方法来针对它们特别处理,例如:
- 举例 1:
宏的原代码:
MTK_ENTRIES_OUTPUT_I ( 2, (vect3, acc) , ((vect3, gyro)) (~), 0, 0, S2_state, SO3_state )
使用上述相同的宏展开方法, 可以得到以上宏最终的C++代码如下(注: 宏展开可能会多次递归).
MTK::SubManifold<vect3, 0, 0> acc;
可知这是一个加速度的类成员变量定义, 类型为 MTK::SubManifold<vect3, 0, 0>
- 举例 2 :I
原代码:
MTK_ENTRIES_OUTPUT_I ( 1, (vect3, gyro) , (~), 0 + BOOST_PP_TUPLE_ELEM_2_0 (vect3, acc)::DOF, 0 + BOOST_PP_TUPLE_ELEM_2_0 (vect3, acc)::DIM, S2_state, SO3_state)
上述宏定义最终对应的C++代码为:
MTK::SubManifold<vect3, 0 + vect3::DOF, 0 + vect3::DIM> gyro; enum { DOF = vect3::DOF + 0 + vect3::DOF }; enum { DIM = vect3::DIM + 0 + vect3::DIM }; typedef vect3::scalar scalar;
可知, 这段代码定义了
gyro
成员变量和DOF, DIM
枚举值, 以及定义了scalar
数据类型.- 举例 3: 原代码:
input_ikfom ( BOOST_PP_SEQ_ENUM_2 (const vect3& acc = vect3()) (const vect3& gyro = vect3()) ) : BOOST_PP_SEQ_ENUM_2 (acc(acc)) (gyro(gyro)) { }
上述宏定义最终对应的C++代码为:
input_ikfom(const vect3& acc = vect3(), const vect3& gyro = vect3()) : acc(acc), gyro(gyro) { }
可知, 这段代码定义了一个构造函数
-
举例 : 其他的宏
与上述举例类似, 均为重复性工作, 此处不再赘述
Step1 的解析结果
-
最终可以得到对应的C++代码片段如下:
宏的原代码:
MTK_BUILD_MANIFOLD(input_ikfom, ((vect3, acc)) ((vect3, gyro)) );
宏展开后 对应的C++代码如下:
注: 可以看到, 这段宏, 定义了一个
struct
, 名称为input_ikfom
, 成员变量有两个acc, gyro
, 并且自动生成了 等运算对应的成员函数struct input_ikfom { typedef input_ikfom self; std::vector<std::pair<int, int> > S2_state; std::vector<std::pair<int, int> > SO3_state; std::vector<std::pair<std::pair<int, int>, int> > vect_state; //MTK_ENTRIES_OUTPUT_I ( 2, (vect3, acc) , ((vect3, gyro)) (~), 0, 0, S2_state, SO3_state ) MTK::SubManifold<vect3, 0, 0> acc; //MTK_ENTRIES_OUTPUT_I ( 1, (vect3, gyro) , (~), 0 + BOOST_PP_TUPLE_ELEM_2_0 (vect3, acc)::DOF, 0 + BOOST_PP_TUPLE_ELEM_2_0 (vect3, acc)::DIM, S2_state, SO3_state) MTK::SubManifold<vect3, 0 + vect3::DOF, 0 + vect3::DIM> gyro; enum { DOF = vect3::DOF + 0 + vect3::DOF }; enum { DIM = vect3::DIM + 0 + vect3::DIM }; typedef vect3::scalar scalar; // input_ikfom ( BOOST_PP_SEQ_ENUM_2 (const vect3& acc = vect3()) (const vect3& gyro = vect3()) ) : BOOST_PP_SEQ_ENUM_2 (acc(acc)) (gyro(gyro)) input_ikfom(const vect3& acc = vect3(), const vect3& gyro = vect3()) : acc(acc), gyro(gyro) { } int getDOF() const { return DOF; } void boxplus(const MTK::vectview<const scalar, DOF>& __vec, scalar __scale = 1) { //MTK_BOXPLUS(vect3, acc) MTK_BOXPLUS(vect3, gyro) acc.boxplus(MTK::subvector(__vec, &self::acc), __scale); gyro.boxplus(MTK::subvector(__vec, &self::gyro), __scale); } void oplus(const MTK::vectview<const scalar, DIM>& __vec, scalar __scale = 1) { //MTK_OPLUS(vect3, acc) MTK_OPLUS(vect3, gyro) acc.oplus(MTK::subvector_(__vec, &self::acc), __scale); gyro.oplus(MTK::subvector_(__vec, &self::gyro), __scale); } void boxminus(MTK::vectview<scalar, DOF> __res, const input_ikfom& __oth) const { //MTK_BOXMINUS(vect3, acc) MTK_BOXMINUS(vect3, gyro) acc.boxminus(MTK::subvector(__res, &self::acc), __oth.acc); gyro.boxminus(MTK::subvector(__res, &self::gyro), __oth.gyro); } friend std::ostream& operator<<(std::ostream& __os, const input_ikfom& __var) { //return __os MTK_OSTREAM(vect3, acc) MTK_OSTREAM(vect3, gyro); return __os << __var.acc << " " << __var.gyro << " "; } void build_S2_state() { //MTK_S2_state(vect3, acc) MTK_S2_state(vect3, gyro) if (acc.TYP == 1) { S2_state.push_back(std::make_pair(acc.IDX, acc.DIM)); } if (gyro.TYP == 1) { S2_state.push_back(std::make_pair(gyro.IDX, gyro.DIM)); } } void build_vect_state() { //MTK_vect_state(vect3, acc) MTK_vect_state(vect3, gyro) if (acc.TYP == 0) { (vect_state).push_back(std::make_pair(std::make_pair(acc.IDX, acc.DIM), vect3::DOF)); } if (gyro.TYP == 0) { (vect_state).push_back(std::make_pair(std::make_pair(gyro.IDX, gyro.DIM), vect3::DOF)); } } void build_SO3_state() { //MTK_SO3_state(vect3, acc) MTK_SO3_state(vect3, gyro) if (acc.TYP == 2) { (SO3_state).push_back(std::make_pair(acc.IDX, acc.DIM)); } if (gyro.TYP == 2) { (SO3_state).push_back(std::make_pair(gyro.IDX, gyro.DIM)); } } void S2_hat(Eigen::Matrix<scalar, 3, 3>& res, int idx) { //MTK_S2_hat(vect3, acc) MTK_S2_hat(vect3, gyro) if (acc.IDX == idx) { acc.S2_hat(res); } if (gyro.IDX == idx) { gyro.S2_hat(res); } } void S2_Nx_yy(Eigen::Matrix<scalar, 2, 3>& res, int idx) { //MTK_S2_Nx_yy(vect3, acc) MTK_S2_Nx_yy(vect3, gyro) if (acc.IDX == idx) { acc.S2_Nx_yy(res); } if (gyro.IDX == idx) { gyro.S2_Nx_yy(res); } } void S2_Mx(Eigen::Matrix<scalar, 3, 2>& res, Eigen::Matrix<scalar, 2, 1> dx, int idx) { //MTK_S2_Mx(vect3, acc) MTK_S2_Mx(vect3, gyro) if (acc.IDX == idx) { acc.S2_Mx(res, dx); } if (gyro.IDX == idx) { gyro.S2_Mx(res, dx); } } friend std::istream& operator>>(std::istream& __is, input_ikfom& __var) { //return __is MTK_ISTREAM(vect3, acc) MTK_ISTREAM(vect3, gyro); return __is >> __var.acc >> __var.gyro; } };
Step2:解析 state_ikfom
对应的宏
以 use-ikfom.hpp
中的如下宏定义代码代码片段为例:
MTK_BUILD_MANIFOLD(state_ikfom,
((vect3, pos))
((SO3, rot))
((SO3, offset_R_L_I))
((vect3, offset_T_L_I))
((vect3, vel))
((vect3, bg))
((vect3, ba))
((S2, grav))
);
依照上述办法解析.不再赘述.
Step2 的解析结果
对应的代码片段为:
struct state_ikfom
{
typedef state_ikfom self;
std::vector<std::pair<int, int> > S2_state;
std::vector<std::pair<int, int> > SO3_state;
std::vector<std::pair<std::pair<int, int>, int> > vect_state;
//MTK_ENTRIES_OUTPUT_I ( 8, (vect3, pos) , ((SO3, rot)) ((SO3, offset_R_L_I)) ((vect3, offset_T_L_I)) ((vect3, vel)) ((vect3, bg)) ((vect3, ba)) ((S2, grav)) (~), 0, 0, S2_state, SO3_state )
MTK::SubManifold<vect3, 0, 0> pos;
//MTK_ENTRIES_OUTPUT_I ( 7, (SO3, rot) , ((SO3, offset_R_L_I)) ((vect3, offset_T_L_I)) ((vect3, vel)) ((vect3, bg)) ((vect3, ba)) ((S2, grav)) (~), 0 + BOOST_PP_TUPLE_ELEM_2_0 (vect3, pos)::DOF, 0 + BOOST_PP_TUPLE_ELEM_2_0 (vect3, pos)::DIM, S2_state, SO3_state) MTK_ENTRIES_OUTPUT_I ( 6, (SO3, offset_R_L_I) , ((vect3, offset_T_L_I)) ((vect3, vel)) ((vect3, bg)) ((vect3, ba)) ((S2, grav)) (~), 0 + vect3::DOF + BOOST_PP_TUPLE_ELEM_2_0 (SO3, rot)::DOF, 0 + vect3::DIM + BOOST_PP_TUPLE_ELEM_2_0 (SO3, rot)::DIM, S2_state, SO3_state)
MTK::SubManifold<SO3, 0 + vect3::DOF, 0 + vect3::DIM> rot;
MTK::SubManifold<SO3, 0 + vect3::DOF + SO3::DOF, 0 + vect3::DIM + SO3::DIM> offset_R_L_I;
//MTK_ENTRIES_OUTPUT_I ( 5, (vect3, offset_T_L_I) , ((vect3, vel)) ((vect3, bg)) ((vect3, ba)) ((S2, grav)) (~), 0 + vect3::DOF + SO3::DOF + BOOST_PP_TUPLE_ELEM_2_0 (SO3, offset_R_L_I)::DOF, 0 + vect3::DIM + SO3::DIM + BOOST_PP_TUPLE_ELEM_2_0 (SO3, offset_R_L_I)::DIM, S2_state, SO3_state) MTK_ENTRIES_OUTPUT_I ( 4, (vect3, vel) , ((vect3, bg)) ((vect3, ba)) ((S2, grav)) (~), 0 + vect3::DOF + SO3::DOF + SO3::DOF + BOOST_PP_TUPLE_ELEM_2_0 (vect3, offset_T_L_I)::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + BOOST_PP_TUPLE_ELEM_2_0 (vect3, offset_T_L_I)::DIM, S2_state, SO3_state)
MTK::SubManifold<vect3, 0 + vect3::DOF + SO3::DOF + SO3::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM> offset_T_L_I;
MTK::SubManifold<vect3, 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM> vel;
//MTK_ENTRIES_OUTPUT_I ( 3, (vect3, bg) , ((vect3, ba)) ((S2, grav)) (~), 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + BOOST_PP_TUPLE_ELEM_2_0 (vect3, vel)::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + BOOST_PP_TUPLE_ELEM_2_0 (vect3, vel)::DIM, S2_state, SO3_state) MTK_ENTRIES_OUTPUT_I ( 2, (vect3, ba) , ((S2, grav)) (~), 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + vect3::DOF + BOOST_PP_TUPLE_ELEM_2_0 (vect3, bg)::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + vect3::DIM + BOOST_PP_TUPLE_ELEM_2_0 (vect3, bg)::DIM, S2_state, SO3_state)
MTK::SubManifold<vect3, 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + vect3::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + vect3::DIM> bg;
MTK::SubManifold<vect3, 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + vect3::DOF + vect3::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + vect3::DIM + vect3::DIM> ba;
//MTK_ENTRIES_OUTPUT_I ( 1, (S2, grav) , (~), 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + vect3::DOF + vect3::DOF + BOOST_PP_TUPLE_ELEM_2_0 (vect3, ba)::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + vect3::DIM + vect3::DIM + BOOST_PP_TUPLE_ELEM_2_0 (vect3, ba)::DIM, S2_state, SO3_state)
MTK::SubManifold<S2, 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + vect3::DOF + vect3::DOF + vect3::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + vect3::DIM + vect3::DIM + vect3::DIM> grav;
enum {DOF = S2::DOF + 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + vect3::DOF + vect3::DOF + vect3::DOF};
enum {DIM = S2::DIM+0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + vect3::DIM + vect3::DIM + vect3::DIM};
typedef S2::scalar scalar;
//state_ikfom ( BOOST_PP_SEQ_ENUM_8 (const vect3& pos = vect3()) (const SO3& rot = SO3()) (const SO3& offset_R_L_I = SO3()) (const vect3& offset_T_L_I = vect3()) (const vect3& vel = vect3()) (const vect3& bg = vect3()) (const vect3& ba = vect3()) (const S2& grav = S2()) ) : BOOST_PP_SEQ_ENUM_8 (pos(pos)) (rot(rot)) (offset_R_L_I(offset_R_L_I)) (offset_T_L_I(offset_T_L_I)) (vel(vel)) (bg(bg)) (ba(ba)) (grav(grav))
state_ikfom(const vect3& pos = vect3(), const SO3& rot = SO3(), const SO3& offset_R_L_I = SO3(), const vect3& offset_T_L_I = vect3(), const vect3& vel = vect3(), const vect3& bg = vect3(), const vect3& ba = vect3(), const S2& grav = S2()) : pos(pos), rot(rot), offset_R_L_I(offset_R_L_I), offset_T_L_I(offset_T_L_I), vel(vel), bg(bg), ba(ba), grav(grav)
{
}
int getDOF() const
{
return DOF;
}
void boxplus(const MTK::vectview<const scalar, DOF> & __vec, scalar __scale = 1 )
{
//MTK_BOXPLUS (vect3, pos) MTK_BOXPLUS (SO3, rot) MTK_BOXPLUS (SO3, offset_R_L_I) MTK_BOXPLUS (vect3, offset_T_L_I) MTK_BOXPLUS (vect3, vel) MTK_BOXPLUS (vect3, bg) MTK_BOXPLUS (vect3, ba) MTK_BOXPLUS (S2, grav)
pos.boxplus(MTK::subvector(__vec, &self::pos), __scale);
rot.boxplus(MTK::subvector(__vec, &self::rot), __scale);
offset_R_L_I.boxplus(MTK::subvector(__vec, &self::offset_R_L_I), __scale);
offset_T_L_I.boxplus(MTK::subvector(__vec, &self::offset_T_L_I), __scale);
vel.boxplus(MTK::subvector(__vec, &self::vel), __scale);
bg.boxplus(MTK::subvector(__vec, &self::bg), __scale);
ba.boxplus(MTK::subvector(__vec, &self::ba), __scale);
grav.boxplus(MTK::subvector(__vec, &self::grav), __scale);
}
void oplus(const MTK::vectview<const scalar, DIM> & __vec, scalar __scale = 1 )
{
//MTK_OPLUS (vect3, pos) MTK_OPLUS (SO3, rot) MTK_OPLUS (SO3, offset_R_L_I) MTK_OPLUS (vect3, offset_T_L_I) MTK_OPLUS (vect3, vel) MTK_OPLUS (vect3, bg) MTK_OPLUS (vect3, ba) MTK_OPLUS (S2, grav)
pos.oplus(MTK::subvector_(__vec, &self::pos), __scale);
rot.oplus(MTK::subvector_(__vec, &self::rot), __scale);
offset_R_L_I.oplus(MTK::subvector_(__vec, &self::offset_R_L_I), __scale);
offset_T_L_I.oplus(MTK::subvector_(__vec, &self::offset_T_L_I), __scale);
vel.oplus(MTK::subvector_(__vec, &self::vel), __scale);
bg.oplus(MTK::subvector_(__vec, &self::bg), __scale);
ba.oplus(MTK::subvector_(__vec, &self::ba), __scale);
grav.oplus(MTK::subvector_(__vec, &self::grav), __scale);
}
void boxminus(MTK::vectview<scalar,DOF> __res, const state_ikfom& __oth) const
{
//MTK_BOXMINUS (vect3, pos) MTK_BOXMINUS (SO3, rot) MTK_BOXMINUS (SO3, offset_R_L_I) MTK_BOXMINUS (vect3, offset_T_L_I) MTK_BOXMINUS (vect3, vel) MTK_BOXMINUS (vect3, bg) MTK_BOXMINUS (vect3, ba) MTK_BOXMINUS (S2, grav)
pos.boxminus(MTK::subvector(__res, &self::pos), __oth.pos);
rot.boxminus(MTK::subvector(__res, &self::rot), __oth.rot);
offset_R_L_I.boxminus(MTK::subvector(__res, &self::offset_R_L_I), __oth.offset_R_L_I);
offset_T_L_I.boxminus(MTK::subvector(__res, &self::offset_T_L_I), __oth.offset_T_L_I);
vel.boxminus(MTK::subvector(__res, &self::vel), __oth.vel);
bg.boxminus(MTK::subvector(__res, &self::bg), __oth.bg);
ba.boxminus(MTK::subvector(__res, &self::ba), __oth.ba);
grav.boxminus(MTK::subvector(__res, &self::grav), __oth.grav);
}
friend std::ostream& operator<<(std::ostream& __os, const state_ikfom& __var)
{
//return __os MTK_OSTREAM (vect3, pos) MTK_OSTREAM (SO3, rot) MTK_OSTREAM (SO3, offset_R_L_I) MTK_OSTREAM (vect3, offset_T_L_I) MTK_OSTREAM (vect3, vel) MTK_OSTREAM (vect3, bg) MTK_OSTREAM (vect3, ba) MTK_OSTREAM (S2, grav) ;
return __os << __var.pos << " " << __var.rot << " " << __var.offset_R_L_I << " " << __var.offset_T_L_I << " " << __var.vel << " " << __var.bg << " " << __var.ba << " " << __var.grav << " ";
}
void build_S2_state()
{
//MTK_S2_state (vect3, pos) MTK_S2_state (SO3, rot) MTK_S2_state (SO3, offset_R_L_I) MTK_S2_state (vect3, offset_T_L_I) MTK_S2_state (vect3, vel) MTK_S2_state (vect3, bg) MTK_S2_state (vect3, ba) MTK_S2_state (S2, grav)
if(pos.TYP == 1)
{
S2_state.push_back(std::make_pair(pos.IDX, pos.DIM));
}
if(rot.TYP == 1)
{
S2_state.push_back(std::make_pair(rot.IDX, rot.DIM));
}
if(offset_R_L_I.TYP == 1)
{
S2_state.push_back(std::make_pair(offset_R_L_I.IDX, offset_R_L_I.DIM));
}
if(offset_T_L_I.TYP == 1)
{
S2_state.push_back(std::make_pair(offset_T_L_I.IDX, offset_T_L_I.DIM));
}
if(vel.TYP == 1)
{
S2_state.push_back(std::make_pair(vel.IDX, vel.DIM));
}
if(bg.TYP == 1)
{
S2_state.push_back(std::make_pair(bg.IDX, bg.DIM));
}
if(ba.TYP == 1)
{
S2_state.push_back(std::make_pair(ba.IDX, ba.DIM));
}
if(grav.TYP == 1)
{
S2_state.push_back(std::make_pair(grav.IDX, grav.DIM));
}
}
void build_vect_state()
{
//MTK_vect_state (vect3, pos) MTK_vect_state (SO3, rot) MTK_vect_state (SO3, offset_R_L_I) MTK_vect_state (vect3, offset_T_L_I) MTK_vect_state (vect3, vel) MTK_vect_state (vect3, bg) MTK_vect_state (vect3, ba) MTK_vect_state (S2, grav)
if(pos.TYP == 0)
{
(vect_state).push_back(std::make_pair(std::make_pair(pos.IDX, pos.DIM), vect3::DOF));
}
if(rot.TYP == 0)
{
(vect_state).push_back(std::make_pair(std::make_pair(rot.IDX, rot.DIM), SO3::DOF));
}
if(offset_R_L_I.TYP == 0)
{
(vect_state).push_back(std::make_pair(std::make_pair(offset_R_L_I.IDX, offset_R_L_I.DIM), SO3::DOF));
}
if(offset_T_L_I.TYP == 0)
{
(vect_state).push_back(std::make_pair(std::make_pair(offset_T_L_I.IDX, offset_T_L_I.DIM), vect3::DOF));
}
if(vel.TYP == 0)
{
(vect_state).push_back(std::make_pair(std::make_pair(vel.IDX, vel.DIM), vect3::DOF));
}
if(bg.TYP == 0)
{
(vect_state).push_back(std::make_pair(std::make_pair(bg.IDX, bg.DIM), vect3::DOF));
}
if(ba.TYP == 0)
{
(vect_state).push_back(std::make_pair(std::make_pair(ba.IDX, ba.DIM), vect3::DOF));
}
if(grav.TYP == 0)
{
(vect_state).push_back(std::make_pair(std::make_pair(grav.IDX, grav.DIM), S2::DOF));
}
}
void build_SO3_state()
{
//MTK_SO3_state (vect3, pos) MTK_SO3_state (SO3, rot) MTK_SO3_state (SO3, offset_R_L_I) MTK_SO3_state (vect3, offset_T_L_I) MTK_SO3_state (vect3, vel) MTK_SO3_state (vect3, bg) MTK_SO3_state (vect3, ba) MTK_SO3_state (S2, grav)
if(pos.TYP == 2)
{
(SO3_state).push_back(std::make_pair(pos.IDX, pos.DIM));
}
if(rot.TYP == 2)
{
(SO3_state).push_back(std::make_pair(rot.IDX, rot.DIM));
}
if(offset_R_L_I.TYP == 2)
{
(SO3_state).push_back(std::make_pair(offset_R_L_I.IDX, offset_R_L_I.DIM));
}
if(offset_T_L_I.TYP == 2)
{
(SO3_state).push_back(std::make_pair(offset_T_L_I.IDX, offset_T_L_I.DIM));
}
if(vel.TYP == 2)
{
(SO3_state).push_back(std::make_pair(vel.IDX, vel.DIM));
}
if(bg.TYP == 2)
{
(SO3_state).push_back(std::make_pair(bg.IDX, bg.DIM));
}
if(ba.TYP == 2)
{
(SO3_state).push_back(std::make_pair(ba.IDX, ba.DIM));
}
if(grav.TYP == 2)
{
(SO3_state).push_back(std::make_pair(grav.IDX, grav.DIM));
}
}
void S2_hat(Eigen::Matrix<scalar, 3, 3> &res, int idx)
{
//MTK_S2_hat (vect3, pos) MTK_S2_hat (SO3, rot) MTK_S2_hat (SO3, offset_R_L_I) MTK_S2_hat (vect3, offset_T_L_I) MTK_S2_hat (vect3, vel) MTK_S2_hat (vect3, bg) MTK_S2_hat (vect3, ba) MTK_S2_hat (S2, grav)
if(pos.IDX == idx)
{
pos.S2_hat(res);
}
if(rot.IDX == idx)
{
rot.S2_hat(res);
}
if(offset_R_L_I.IDX == idx)
{
offset_R_L_I.S2_hat(res);
}
if(offset_T_L_I.IDX == idx)
{
offset_T_L_I.S2_hat(res);
}
if(vel.IDX == idx)
{
vel.S2_hat(res);
}
if(bg.IDX == idx)
{
bg.S2_hat(res);
}
if(ba.IDX == idx)
{
ba.S2_hat(res);
}
if(grav.IDX == idx)
{
grav.S2_hat(res);
}
}
void S2_Nx_yy(Eigen::Matrix<scalar, 2, 3> &res, int idx)
{
//MTK_S2_Nx_yy (vect3, pos) MTK_S2_Nx_yy (SO3, rot) MTK_S2_Nx_yy (SO3, offset_R_L_I) MTK_S2_Nx_yy (vect3, offset_T_L_I) MTK_S2_Nx_yy (vect3, vel) MTK_S2_Nx_yy (vect3, bg) MTK_S2_Nx_yy (vect3, ba) MTK_S2_Nx_yy (S2, grav)
if(pos.IDX == idx)
{
pos.S2_Nx_yy(res);
}
if(rot.IDX == idx)
{
rot.S2_Nx_yy(res);
}
if(offset_R_L_I.IDX == idx)
{
offset_R_L_I.S2_Nx_yy(res);
}
if(offset_T_L_I.IDX == idx)
{
offset_T_L_I.S2_Nx_yy(res);
}
if(vel.IDX == idx)
{
vel.S2_Nx_yy(res);
}
if(bg.IDX == idx)
{
bg.S2_Nx_yy(res);
}
if(ba.IDX == idx)
{
ba.S2_Nx_yy(res);
}
if(grav.IDX == idx)
{
grav.S2_Nx_yy(res);
}
}
void S2_Mx(Eigen::Matrix<scalar, 3, 2> &res, Eigen::Matrix<scalar, 2, 1> dx, int idx)
{
//MTK_S2_Mx (vect3, pos) MTK_S2_Mx (SO3, rot) MTK_S2_Mx (SO3, offset_R_L_I) MTK_S2_Mx (vect3, offset_T_L_I) MTK_S2_Mx (vect3, vel) MTK_S2_Mx (vect3, bg) MTK_S2_Mx (vect3, ba) MTK_S2_Mx (S2, grav)
if(pos.IDX == idx)
{
pos.S2_Mx(res, dx);
}
if(rot.IDX == idx)
{
rot.S2_Mx(res, dx);
}
if(offset_R_L_I.IDX == idx)
{
offset_R_L_I.S2_Mx(res, dx);
}
if(offset_T_L_I.IDX == idx)
{
offset_T_L_I.S2_Mx(res, dx);
}
if(vel.IDX == idx)
{
vel.S2_Mx(res, dx);
}
if(bg.IDX == idx)
{
bg.S2_Mx(res, dx);
}
if(ba.IDX == idx)
{
ba.S2_Mx(res, dx);
}
if(grav.IDX == idx)
{
grav.S2_Mx(res, dx);
}
}
friend std::istream& operator>>(std::istream& __is, state_ikfom& __var)
{
//return __is MTK_ISTREAM (vect3, pos) MTK_ISTREAM (SO3, rot) MTK_ISTREAM (SO3, offset_R_L_I) MTK_ISTREAM (vect3, offset_T_L_I) MTK_ISTREAM (vect3, vel) MTK_ISTREAM (vect3, bg) MTK_ISTREAM (vect3, ba) MTK_ISTREAM (S2, grav) ;
return __is >> __var.pos >> __var.rot >> __var.offset_R_L_I >> __var.offset_T_L_I >> __var.vel >> __var.bg >> __var.ba >> __var.grav;
}
};
Step3:解析 process_noise_ikfom
对应的宏
以 use-ikfom.hpp
中的如下代码片段为例:
MTK_BUILD_MANIFOLD(process_noise_ikfom,
((vect3, ng))
((vect3, na))
((vect3, nbg))
((vect3, nba))
);
依照上述办法解析.不再赘述.
Step3 的解析结果
对应的代码片段为:
struct process_noise_ikfom
{
typedef process_noise_ikfom self;
std::vector<std::pair<int, int> > S2_state;
std::vector<std::pair<int, int> > SO3_state;
std::vector<std::pair<std::pair<int, int>, int> > vect_state;
//MTK_ENTRIES_OUTPUT_I ( 4, (vect3, ng) , ((vect3, na)) ((vect3, nbg)) ((vect3, nba)) (~), 0, 0, S2_state, SO3_state )
MTK::SubManifold<vect3, 0, 0> ng;
//MTK_ENTRIES_OUTPUT_I ( 3, (vect3, na) , ((vect3, nbg)) ((vect3, nba)) (~), 0 + BOOST_PP_TUPLE_ELEM_2_0 (vect3, ng)::DOF, 0 + BOOST_PP_TUPLE_ELEM_2_0 (vect3, ng)::DIM, S2_state, SO3_state)
MTK::SubManifold<vect3, 0 + vect3::DOF, 0 + vect3::DIM> na;
//MTK_ENTRIES_OUTPUT_I ( 2, (vect3, nbg) , ((vect3, nba)) (~), 0 + vect3::DOF + BOOST_PP_TUPLE_ELEM_2_0 (vect3, na)::DOF, 0 + vect3::DIM + BOOST_PP_TUPLE_ELEM_2_0 (vect3, na)::DIM, S2_state, SO3_state)
MTK::SubManifold<vect3, 0 + vect3::DOF + vect3::DOF, 0 + vect3::DIM + vect3::DIM> nbg;
//MTK_ENTRIES_OUTPUT_I ( 1, (vect3, nba) , (~), 0 + vect3::DOF + vect3::DOF + BOOST_PP_TUPLE_ELEM_2_0 (vect3, nbg)::DOF, 0 + vect3::DIM + vect3::DIM + BOOST_PP_TUPLE_ELEM_2_0 (vect3, nbg)::DIM, S2_state, SO3_state)
MTK::SubManifold<vect3, 0 + vect3::DOF + vect3::DOF + vect3::DOF, 0 + vect3::DIM + vect3::DIM + vect3::DIM> nba;
enum {DOF = vect3::DOF + 0 + vect3::DOF + vect3::DOF + vect3::DOF};
enum {DIM = vect3::DIM+0 + vect3::DIM + vect3::DIM + vect3::DIM};
typedef vect3::scalar scalar;
//process_noise_ikfom ( BOOST_PP_SEQ_ENUM_4 (const vect3& ng = vect3()) (const vect3& na = vect3()) (const vect3& nbg = vect3()) (const vect3& nba = vect3()) ) : BOOST_PP_SEQ_ENUM_4 (ng(ng)) (na(na)) (nbg(nbg)) (nba(nba))
process_noise_ikfom(const vect3& ng = vect3(), const vect3& na = vect3(), const vect3& nbg = vect3(), const vect3& nba = vect3()) : ng(ng), na(na), nbg(nbg), nba(nba)
{
}
int getDOF() const
{
return DOF;
}
void boxplus(const MTK::vectview<const scalar, DOF> & __vec, scalar __scale = 1 )
{
//MTK_BOXPLUS (vect3, ng) MTK_BOXPLUS (vect3, na) MTK_BOXPLUS (vect3, nbg) MTK_BOXPLUS (vect3, nba)
ng.boxplus(MTK::subvector(__vec, &self::ng), __scale);
na.boxplus(MTK::subvector(__vec, &self::na), __scale);
nbg.boxplus(MTK::subvector(__vec, &self::nbg), __scale);
nba.boxplus(MTK::subvector(__vec, &self::nba), __scale);
}
void oplus(const MTK::vectview<const scalar, DIM> & __vec, scalar __scale = 1 )
{
//MTK_OPLUS (vect3, ng) MTK_OPLUS (vect3, na) MTK_OPLUS (vect3, nbg) MTK_OPLUS (vect3, nba)
ng.oplus(MTK::subvector_(__vec, &self::ng), __scale);
na.oplus(MTK::subvector_(__vec, &self::na), __scale);
nbg.oplus(MTK::subvector_(__vec, &self::nbg), __scale);
nba.oplus(MTK::subvector_(__vec, &self::nba), __scale);
}
void boxminus(MTK::vectview<scalar,DOF> __res, const process_noise_ikfom& __oth) const
{
//MTK_BOXMINUS (vect3, ng) MTK_BOXMINUS (vect3, na) MTK_BOXMINUS (vect3, nbg) MTK_BOXMINUS (vect3, nba)
ng.boxminus(MTK::subvector(__res, &self::ng), __oth.ng);
na.boxminus(MTK::subvector(__res, &self::na), __oth.na);
nbg.boxminus(MTK::subvector(__res, &self::nbg), __oth.nbg);
nba.boxminus(MTK::subvector(__res, &self::nba), __oth.nba);
}
friend std::ostream& operator<<(std::ostream& __os, const process_noise_ikfom& __var)
{
//return __os MTK_OSTREAM (vect3, ng) MTK_OSTREAM (vect3, na) MTK_OSTREAM (vect3, nbg) MTK_OSTREAM (vect3, nba) ;
return __os << __var.ng << " " << __var.na << " " << __var.nbg << " " << __var.nba << " ";
}
void build_S2_state()
{
//MTK_S2_state (vect3, ng) MTK_S2_state (vect3, na) MTK_S2_state (vect3, nbg) MTK_S2_state (vect3, nba)
if(ng.TYP == 1)
{
S2_state.push_back(std::make_pair(ng.IDX, ng.DIM));
}
if(na.TYP == 1)
{
S2_state.push_back(std::make_pair(na.IDX, na.DIM));
}
if(nbg.TYP == 1)
{
S2_state.push_back(std::make_pair(nbg.IDX, nbg.DIM));
}
if(nba.TYP == 1)
{
S2_state.push_back(std::make_pair(nba.IDX, nba.DIM));
}
}
void build_vect_state()
{
//MTK_vect_state (vect3, ng) MTK_vect_state (vect3, na) MTK_vect_state (vect3, nbg) MTK_vect_state (vect3, nba)
if(ng.TYP == 0)
{
(vect_state).push_back(std::make_pair(std::make_pair(ng.IDX, ng.DIM), vect3::DOF));
}
if(na.TYP == 0)
{
(vect_state).push_back(std::make_pair(std::make_pair(na.IDX, na.DIM), vect3::DOF));
}
if(nbg.TYP == 0)
{
(vect_state).push_back(std::make_pair(std::make_pair(nbg.IDX, nbg.DIM), vect3::DOF));
}
if(nba.TYP == 0)
{
(vect_state).push_back(std::make_pair(std::make_pair(nba.IDX, nba.DIM), vect3::DOF));
}
}
void build_SO3_state()
{
//MTK_SO3_state (vect3, ng) MTK_SO3_state (vect3, na) MTK_SO3_state (vect3, nbg) MTK_SO3_state (vect3, nba)
if(ng.TYP == 2)
{
(SO3_state).push_back(std::make_pair(ng.IDX, ng.DIM));
}
if(na.TYP == 2)
{
(SO3_state).push_back(std::make_pair(na.IDX, na.DIM));
}
if(nbg.TYP == 2)
{
(SO3_state).push_back(std::make_pair(nbg.IDX, nbg.DIM));
}
if(nba.TYP == 2)
{
(SO3_state).push_back(std::make_pair(nba.IDX, nba.DIM));
}
}
void S2_hat(Eigen::Matrix<scalar, 3, 3> &res, int idx)
{
//MTK_S2_hat (vect3, ng) MTK_S2_hat (vect3, na) MTK_S2_hat (vect3, nbg) MTK_S2_hat (vect3, nba)
if(ng.IDX == idx)
{
ng.S2_hat(res);
}
if(na.IDX == idx)
{
na.S2_hat(res);
}
if(nbg.IDX == idx)
{
nbg.S2_hat(res);
}
if(nba.IDX == idx)
{
nba.S2_hat(res);
}
}
void S2_Nx_yy(Eigen::Matrix<scalar, 2, 3> &res, int idx)
{
//MTK_S2_Nx_yy (vect3, ng) MTK_S2_Nx_yy (vect3, na) MTK_S2_Nx_yy (vect3, nbg) MTK_S2_Nx_yy (vect3, nba)
if(ng.IDX == idx)
{
ng.S2_Nx_yy(res);
}
if(na.IDX == idx)
{
na.S2_Nx_yy(res);
}
if(nbg.IDX == idx)
{
nbg.S2_Nx_yy(res);
}
if(nba.IDX == idx)
{
nba.S2_Nx_yy(res);
}
}
void S2_Mx(Eigen::Matrix<scalar, 3, 2> &res, Eigen::Matrix<scalar, 2, 1> dx, int idx)
{
//MTK_S2_Mx (vect3, ng) MTK_S2_Mx (vect3, na) MTK_S2_Mx (vect3, nbg) MTK_S2_Mx (vect3, nba)
if(ng.IDX == idx)
{
ng.S2_Mx(res, dx);
}
if(na.IDX == idx)
{
na.S2_Mx(res, dx);
}
if(nbg.IDX == idx)
{
nbg.S2_Mx(res, dx);
}
if(nba.IDX == idx)
{
nba.S2_Mx(res, dx);
}
}
friend std::istream& operator>>(std::istream& __is, process_noise_ikfom& __var)
{
//return __is MTK_ISTREAM (vect3, ng) MTK_ISTREAM (vect3, na) MTK_ISTREAM (vect3, nbg) MTK_ISTREAM (vect3, nba) ;
return __is >> __var.ng >> __var.na >> __var.nbg >> __var.nba;
}
};
附录:
最终附上解析 三个 宏定义的递归解析代码
input_ikfom 的宏解析代码: input_ikfom_build.hpp
state_ikfom 的宏解析代码: state_ikfom_build.hpp
process_noise_ikfom 的宏解析代码: process_noise_ikfom_build.hpp
工程入口代码: main.cpp
1) input_ikfom_build.hpp
#pragma once
#pragma message(DIS( \
MTK_BUILD_MANIFOLD(input_ikfom, \
((vect3, acc)) \
((vect3, gyro)) \
) \
))
#pragma message(DIS( \
MTK_ENTRIES_OUTPUT_I ( 2, (vect3, acc) , ((vect3, gyro)) (~), 0, 0, S2_state, SO3_state ) \
))
#pragma message(DIS( \
MTK_PUT_TYPE(vect3, acc, 0, 0, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_ENTRIES_OUTPUT_I(1, (vect3, gyro), (~), 0 + BOOST_PP_TUPLE_ELEM_2_0(vect3, acc)::DOF, 0 + BOOST_PP_TUPLE_ELEM_2_0(vect3, acc)::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_PUT_TYPE_AND_ENUM ( vect3, gyro, 0 + vect3::DOF, 0 + vect3::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
input_ikfom(BOOST_PP_SEQ_ENUM_2(const vect3& acc = vect3()) (const vect3& gyro = vect3())) : BOOST_PP_SEQ_ENUM_2(acc(acc)) (gyro(gyro)) { } \
))
#pragma message(DIS( \
MTK_BOXPLUS(vect3, acc) MTK_BOXPLUS(vect3, gyro) \
))
#pragma message(DIS( \
MTK_OPLUS(vect3, acc) MTK_OPLUS(vect3, gyro) \
))
#pragma message(DIS( \
MTK_BOXMINUS(vect3, acc) MTK_BOXMINUS(vect3, gyro) \
))
#pragma message(DIS( \
return __os MTK_OSTREAM(vect3, acc) MTK_OSTREAM(vect3, gyro); \
))
#pragma message(DIS( \
MTK_S2_state(vect3, acc) MTK_S2_state(vect3, gyro) \
))
#pragma message(DIS( \
MTK_vect_state(vect3, acc) MTK_vect_state(vect3, gyro) \
))
#pragma message(DIS( \
MTK_SO3_state(vect3, acc) MTK_SO3_state(vect3, gyro) \
))
#pragma message(DIS( \
MTK_S2_hat(vect3, acc) MTK_S2_hat(vect3, gyro) \
))
#pragma message(DIS( \
MTK_S2_Nx_yy(vect3, acc) MTK_S2_Nx_yy(vect3, gyro) \
))
#pragma message(DIS( \
MTK_S2_Mx(vect3, acc) MTK_S2_Mx(vect3, gyro) \
))
#pragma message(DIS( \
return __is MTK_ISTREAM(vect3, acc) MTK_ISTREAM(vect3, gyro); \
))
2) state_ikfom_build.hpp
#pragma once
#pragma message(DIS( \
MTK_BUILD_MANIFOLD(state_ikfom, \
((vect3, pos)) \
((SO3, rot)) \
((SO3, offset_R_L_I)) \
((vect3, offset_T_L_I)) \
((vect3, vel)) \
((vect3, bg)) \
((vect3, ba)) \
((S2, grav)) \
); \
))
#pragma message(DIS( \
MTK_ENTRIES_OUTPUT_I(8, (vect3, pos), ((SO3, rot)) ((SO3, offset_R_L_I)) ((vect3, offset_T_L_I)) ((vect3, vel)) ((vect3, bg)) ((vect3, ba)) ((S2, grav)) (~), 0, 0, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_PUT_TYPE ( vect3, pos, 0, 0, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_ENTRIES_OUTPUT_I(7, (SO3, rot), ((SO3, offset_R_L_I)) ((vect3, offset_T_L_I)) ((vect3, vel)) ((vect3, bg)) ((vect3, ba)) ((S2, grav)) (~), 0 + BOOST_PP_TUPLE_ELEM_2_0(vect3, pos)::DOF, 0 + BOOST_PP_TUPLE_ELEM_2_0(vect3, pos)::DIM, S2_state, SO3_state) MTK_ENTRIES_OUTPUT_I(6, (SO3, offset_R_L_I), ((vect3, offset_T_L_I)) ((vect3, vel)) ((vect3, bg)) ((vect3, ba)) ((S2, grav)) (~), 0 + vect3::DOF + BOOST_PP_TUPLE_ELEM_2_0(SO3, rot)::DOF, 0 + vect3::DIM + BOOST_PP_TUPLE_ELEM_2_0(SO3, rot)::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_PUT_TYPE(SO3, rot, 0 + vect3::DOF, 0 + vect3::DIM, S2_state, SO3_state) MTK_PUT_TYPE(SO3, offset_R_L_I, 0 + vect3::DOF + SO3::DOF, 0 + vect3::DIM + SO3::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_ENTRIES_OUTPUT_I(5, (vect3, offset_T_L_I), ((vect3, vel)) ((vect3, bg)) ((vect3, ba)) ((S2, grav)) (~), 0 + vect3::DOF + SO3::DOF + BOOST_PP_TUPLE_ELEM_2_0(SO3, offset_R_L_I)::DOF, 0 + vect3::DIM + SO3::DIM + BOOST_PP_TUPLE_ELEM_2_0(SO3, offset_R_L_I)::DIM, S2_state, SO3_state) MTK_ENTRIES_OUTPUT_I(4, (vect3, vel), ((vect3, bg)) ((vect3, ba)) ((S2, grav)) (~), 0 + vect3::DOF + SO3::DOF + SO3::DOF + BOOST_PP_TUPLE_ELEM_2_0(vect3, offset_T_L_I)::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + BOOST_PP_TUPLE_ELEM_2_0(vect3, offset_T_L_I)::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_PUT_TYPE(vect3, offset_T_L_I, 0 + vect3::DOF + SO3::DOF + SO3::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM, S2_state, SO3_state) MTK_PUT_TYPE(vect3, vel, 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_ENTRIES_OUTPUT_I(3, (vect3, bg), ((vect3, ba)) ((S2, grav)) (~), 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + BOOST_PP_TUPLE_ELEM_2_0(vect3, vel)::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + BOOST_PP_TUPLE_ELEM_2_0(vect3, vel)::DIM, S2_state, SO3_state) MTK_ENTRIES_OUTPUT_I(2, (vect3, ba), ((S2, grav)) (~), 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + vect3::DOF + BOOST_PP_TUPLE_ELEM_2_0(vect3, bg)::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + vect3::DIM + BOOST_PP_TUPLE_ELEM_2_0(vect3, bg)::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_PUT_TYPE(vect3, bg, 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + vect3::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + vect3::DIM, S2_state, SO3_state) MTK_PUT_TYPE(vect3, ba, 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + vect3::DOF + vect3::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + vect3::DIM + vect3::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_ENTRIES_OUTPUT_I(1, (S2, grav), (~), 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + vect3::DOF + vect3::DOF + BOOST_PP_TUPLE_ELEM_2_0(vect3, ba)::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + vect3::DIM + vect3::DIM + BOOST_PP_TUPLE_ELEM_2_0(vect3, ba)::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_PUT_TYPE_AND_ENUM(S2, grav, 0 + vect3::DOF + SO3::DOF + SO3::DOF + vect3::DOF + vect3::DOF + vect3::DOF + vect3::DOF, 0 + vect3::DIM + SO3::DIM + SO3::DIM + vect3::DIM + vect3::DIM + vect3::DIM + vect3::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
state_ikfom(BOOST_PP_SEQ_ENUM_8(const vect3& pos = vect3()) (const SO3& rot = SO3()) (const SO3& offset_R_L_I = SO3()) (const vect3& offset_T_L_I = vect3()) (const vect3& vel = vect3()) (const vect3& bg = vect3()) (const vect3& ba = vect3()) (const S2& grav = S2())) : BOOST_PP_SEQ_ENUM_8(pos(pos)) (rot(rot)) (offset_R_L_I(offset_R_L_I)) (offset_T_L_I(offset_T_L_I)) (vel(vel)) (bg(bg)) (ba(ba)) (grav(grav)) \
))
#pragma message(DIS( \
MTK_BOXPLUS(vect3, pos) MTK_BOXPLUS(SO3, rot) MTK_BOXPLUS(SO3, offset_R_L_I) MTK_BOXPLUS(vect3, offset_T_L_I) MTK_BOXPLUS(vect3, vel) MTK_BOXPLUS(vect3, bg) MTK_BOXPLUS(vect3, ba) MTK_BOXPLUS(S2, grav) \
))
#pragma message(DIS( \
MTK_OPLUS(vect3, pos) MTK_OPLUS(SO3, rot) MTK_OPLUS(SO3, offset_R_L_I) MTK_OPLUS(vect3, offset_T_L_I) MTK_OPLUS(vect3, vel) MTK_OPLUS(vect3, bg) MTK_OPLUS(vect3, ba) MTK_OPLUS(S2, grav) \
))
#pragma message(DIS( \
MTK_BOXMINUS(vect3, pos) MTK_BOXMINUS(SO3, rot) MTK_BOXMINUS(SO3, offset_R_L_I) MTK_BOXMINUS(vect3, offset_T_L_I) MTK_BOXMINUS(vect3, vel) MTK_BOXMINUS(vect3, bg) MTK_BOXMINUS(vect3, ba) MTK_BOXMINUS(S2, grav) \
### ))
#pragma message(DIS( \
return __os MTK_OSTREAM(vect3, pos) MTK_OSTREAM(SO3, rot) MTK_OSTREAM(SO3, offset_R_L_I) MTK_OSTREAM(vect3, offset_T_L_I) MTK_OSTREAM(vect3, vel) MTK_OSTREAM(vect3, bg) MTK_OSTREAM(vect3, ba) MTK_OSTREAM(S2, grav); \
))
#pragma message(DIS( \
MTK_S2_state(vect3, pos) MTK_S2_state(SO3, rot) MTK_S2_state(SO3, offset_R_L_I) MTK_S2_state(vect3, offset_T_L_I) MTK_S2_state(vect3, vel) MTK_S2_state(vect3, bg) MTK_S2_state(vect3, ba) MTK_S2_state(S2, grav) \
))
#pragma message(DIS( \
MTK_vect_state(vect3, pos) MTK_vect_state(SO3, rot) MTK_vect_state(SO3, offset_R_L_I) MTK_vect_state(vect3, offset_T_L_I) MTK_vect_state(vect3, vel) MTK_vect_state(vect3, bg) MTK_vect_state(vect3, ba) MTK_vect_state(S2, grav) \
))
#pragma message(DIS( \
MTK_SO3_state(vect3, pos) MTK_SO3_state(SO3, rot) MTK_SO3_state(SO3, offset_R_L_I) MTK_SO3_state(vect3, offset_T_L_I) MTK_SO3_state(vect3, vel) MTK_SO3_state(vect3, bg) MTK_SO3_state(vect3, ba) MTK_SO3_state(S2, grav) \
))
#pragma message(DIS( \
MTK_S2_hat(vect3, pos) MTK_S2_hat(SO3, rot) MTK_S2_hat(SO3, offset_R_L_I) MTK_S2_hat(vect3, offset_T_L_I) MTK_S2_hat(vect3, vel) MTK_S2_hat(vect3, bg) MTK_S2_hat(vect3, ba) MTK_S2_hat(S2, grav) \
))
#pragma message(DIS( \
MTK_S2_Nx_yy(vect3, pos) MTK_S2_Nx_yy(SO3, rot) MTK_S2_Nx_yy(SO3, offset_R_L_I) MTK_S2_Nx_yy(vect3, offset_T_L_I) MTK_S2_Nx_yy(vect3, vel) MTK_S2_Nx_yy(vect3, bg) MTK_S2_Nx_yy(vect3, ba) MTK_S2_Nx_yy(S2, grav) \
))
#pragma message(DIS( \
MTK_S2_Mx(vect3, pos) MTK_S2_Mx(SO3, rot) MTK_S2_Mx(SO3, offset_R_L_I) MTK_S2_Mx(vect3, offset_T_L_I) MTK_S2_Mx(vect3, vel) MTK_S2_Mx(vect3, bg) MTK_S2_Mx(vect3, ba) MTK_S2_Mx(S2, grav) \
))
#pragma message(DIS( \
return __is MTK_ISTREAM(vect3, pos) MTK_ISTREAM(SO3, rot) MTK_ISTREAM(SO3, offset_R_L_I) MTK_ISTREAM(vect3, offset_T_L_I) MTK_ISTREAM(vect3, vel) MTK_ISTREAM(vect3, bg) MTK_ISTREAM(vect3, ba) MTK_ISTREAM(S2, grav); \
))
3) process_noise_ikfom_build.hpp
#pragma once
#pragma message(DIS( \
MTK_BUILD_MANIFOLD(process_noise_ikfom, \
((vect3, ng)) \
((vect3, na)) \
((vect3, nbg)) \
((vect3, nba)) \
); \
))
#pragma message(DIS( \
MTK_ENTRIES_OUTPUT_I ( 4, (vect3, ng) , ((vect3, na)) ((vect3, nbg)) ((vect3, nba)) (~), 0, 0, S2_state, SO3_state ) \
))
#pragma message(DIS( \
MTK_PUT_TYPE ( vect3, ng, 0, 0, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_ENTRIES_OUTPUT_I(3, (vect3, na), ((vect3, nbg)) ((vect3, nba)) (~), 0 + BOOST_PP_TUPLE_ELEM_2_0(vect3, ng)::DOF, 0 + BOOST_PP_TUPLE_ELEM_2_0(vect3, ng)::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_PUT_TYPE(vect3, na, 0 + vect3::DOF, 0 + vect3::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_ENTRIES_OUTPUT_I(2, (vect3, nbg), ((vect3, nba)) (~), 0 + vect3::DOF + BOOST_PP_TUPLE_ELEM_2_0(vect3, na)::DOF, 0 + vect3::DIM + BOOST_PP_TUPLE_ELEM_2_0(vect3, na)::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_PUT_TYPE(vect3, nbg, 0 + vect3::DOF + vect3::DOF, 0 + vect3::DIM + vect3::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_ENTRIES_OUTPUT_I(1, (vect3, nba), (~), 0 + vect3::DOF + vect3::DOF + BOOST_PP_TUPLE_ELEM_2_0(vect3, nbg)::DOF, 0 + vect3::DIM + vect3::DIM + BOOST_PP_TUPLE_ELEM_2_0(vect3, nbg)::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
MTK_PUT_TYPE_AND_ENUM(vect3, nba, 0 + vect3::DOF + vect3::DOF + vect3::DOF, 0 + vect3::DIM + vect3::DIM + vect3::DIM, S2_state, SO3_state) \
))
#pragma message(DIS( \
process_noise_ikfom(BOOST_PP_SEQ_ENUM_4(const vect3& ng = vect3()) (const vect3& na = vect3()) (const vect3& nbg = vect3()) (const vect3& nba = vect3())) : BOOST_PP_SEQ_ENUM_4(ng(ng)) (na(na)) (nbg(nbg)) (nba(nba)) \
))
#pragma message(DIS( \
MTK_BOXPLUS(vect3, ng) MTK_BOXPLUS(vect3, na) MTK_BOXPLUS(vect3, nbg) MTK_BOXPLUS(vect3, nba) \
))
#pragma message(DIS( \
MTK_OPLUS(vect3, ng) MTK_OPLUS(vect3, na) MTK_OPLUS(vect3, nbg) MTK_OPLUS(vect3, nba) \
))
#pragma message(DIS( \
MTK_BOXMINUS(vect3, ng) MTK_BOXMINUS(vect3, na) MTK_BOXMINUS(vect3, nbg) MTK_BOXMINUS(vect3, nba) \
))
#pragma message(DIS( \
return __os MTK_OSTREAM(vect3, ng) MTK_OSTREAM(vect3, na) MTK_OSTREAM(vect3, nbg) MTK_OSTREAM(vect3, nba); \
))
#pragma message(DIS( \
MTK_S2_state(vect3, ng) MTK_S2_state(vect3, na) MTK_S2_state(vect3, nbg) MTK_S2_state(vect3, nba) \
))
#pragma message(DIS( \
MTK_vect_state(vect3, ng) MTK_vect_state(vect3, na) MTK_vect_state(vect3, nbg) MTK_vect_state(vect3, nba) \
))
#pragma message(DIS( \
MTK_SO3_state(vect3, ng) MTK_SO3_state(vect3, na) MTK_SO3_state(vect3, nbg) MTK_SO3_state(vect3, nba) \
))
#pragma message(DIS( \
MTK_S2_hat(vect3, ng) MTK_S2_hat(vect3, na) MTK_S2_hat(vect3, nbg) MTK_S2_hat(vect3, nba) \
))
#pragma message(DIS( \
MTK_S2_Nx_yy(vect3, ng) MTK_S2_Nx_yy(vect3, na) MTK_S2_Nx_yy(vect3, nbg) MTK_S2_Nx_yy(vect3, nba) \
))
#pragma message(DIS( \
MTK_S2_Mx(vect3, ng) MTK_S2_Mx(vect3, na) MTK_S2_Mx(vect3, nbg) MTK_S2_Mx(vect3, nba) \
))
#pragma message(DIS( \
return __is MTK_ISTREAM(vect3, ng) MTK_ISTREAM(vect3, na) MTK_ISTREAM(vect3, nbg) MTK_ISTREAM(vect3, nba); \
))
4) main.cpp
#include <iostream>
#include "use-ikfom.hpp"
// 定义用于显示宏内容的宏
#define M(x) #x
#define DIS(x) #x"=>\n\t"M(x)
#include "input_ikfom_build.hpp"
#include "state_ikfom_build.hpp"
#include "process_noise_ikfom_build.hpp"
int main()
{
return 0;
}