如何解决编译时检测坐标系转换错误
我正在制作一个简单的几何库,它由向量(在物理意义上,而不是 stl 容器意义上)和变换组成。对于我正在做的事情,变换仅限于旋转和平移。我正在尝试定义类型,以便在编译时可以检测到应用不当的转换,即所有的数学运算都是使用 Eigen::Matrix3d
和 Eigen::Vector3d
完成的,但是我试图给某些语义赋予含义Matrix3d
和 Vector3d
的定义,因此它们必须满足约束才能被允许。
例如,如果 Pj
是坐标系 P
中的向量 j
,而 Tjk
是采用坐标系 j
中表示的向量并表达的变换它在 k
帧中,然后 Pk = Tjk * Pj
和 Pj = Tkj * Pk
是有效的变换(使用 Tkj = Tjk.inverse()
)而 Pj = Tjk * Pk
和 Pk = Tkj * Pj
不是。变换也可以组合,即在 Pm = Tkm * Tjk *Pj
,Tkm*Tjk = Tjm
=> Pm = Tjm* Pj
在这种情况下,Pm = Tjk * Tkm * Pj
(变换交换)是错误的,如果它被捕获在编译时间。
这是我迄今为止尝试过的:
template <class FromCoord,class ToCoord>
class Transform{
public:
Transform() = default;
Transform(const RotationMatrix& r,const ToCoord& translation):
rotation_{r},translation_{translation} {}
ToCoord operator*(const FromCoord& v) const {
return FromCoord{rotation_*v + translation_};
}
// template<class ToNextCoord>
// friend Transform<FromCoord,ToNextCoord> operator*(const Transform<ToCoord,ToNextCoord> t2,const Transform<FromCoord,ToCoord>& t1 ){
// return Transform<FromCoord,ToNextCoord> {t2.rotation_ * t1.rotation_,t2 * t1.translation_};
// }
// compute transform inverse
Transform<ToCoord,FromCoord> inv(){
Transform<ToCoord,FromCoord> m_t;
m_t.rotation_ = rotation_.transpose();
m_t.translation_ = rotation_.transpose() * -translation_;
return m_t;
}
// should be private:
Eigen::Matrix3d rotation_;
ToCoord translation_;
};
template<class FromCoord2,class ToCoord3,class FromCoord1,class ToCoord2>
Transform<FromCoord1,ToCoord3> operator*(const Transform<FromCoord2,ToCoord3> t2,const Transform<FromCoord1,ToCoord2>& t1 ){
static_assert(std::is_same_v<ToCoord2,FromCoord2>,"bah this is not right");
return Transform<FromCoord1,ToCoord3> {t2.rotation_ * t1.rotation_,t2 * t1.translation_};
}
struct NedLocal: public Eigen::Vector3d {
using Eigen::Vector3d::Vector3d;
// NedLocal(double x,double y,double z): Eigen::Vector3d(x,y,z) {}
};
struct BodyFrame: public Eigen::Vector3d {using Eigen::Vector3d::Vector3d;};
struct CameraFrame: public Eigen::Vector3d {using Eigen::Vector3d::Vector3d;};
int main(){
CameraFrame ray_cam{};
Transform<CameraFrame,BodyFrame> Tcb{ };
Transform<BodyFrame,NedLocal> Tbi{ };
NedLocal inertial_los = Tbi*Tcb*ray_cam; // ok
NedLocal inertial_los1 = Tcb*ray_cam; // this should generate a compile time error on assignment
NedLocal inertial_los2 = Tbi*ray_cam; // this should generate a compile time error on operator*
}
但是在这种情况下,由于 using
语句,所有坐标系都可以相互隐式转换,因此不会给出编译错误。 static_assert
也没有抓住它。删除 using
语句会导致其他编译器错误
完整示例在这里:https://godbolt.org/z/drPYG3
我追求的是可能吗?如果是的话,我该怎么做?如果有一种方法可以使用概念来制作更友好的编译器消息,那就太好了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。