Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
155 views
in Technique[技术] by (71.8m points)

c++ - Detect coordinate frame conversion error at compile time

I'm making a simple geometry library that consists of vectors (in the physics sense, not stl container sense) and transforms. For what I'm doing, a transform is limited to a rotation and a translation. I'm trying to define the types such that improperly applied transforms can be detected at compile time, i.e. all the math is done using Eigen::Matrix3d and Eigen::Vector3d, however I'm trying to give semantic meaning to certain definitions of Matrix3d and Vector3d so they must meet constraints in order be allowed.

For example if Pj is a vector P in coordinate frame j and Tjk is a transform that takes a vector expressed in frame j and expresses it in frame k then Pk = Tjk * Pj and Pj = Tkj * Pk are valid transforms (with Tkj = Tjk.inverse()) whereas Pj = Tjk * Pk and Pk = Tkj * Pj are not. Transforms can also be combined, i.e. in Pm = Tkm * Tjk *Pj, Tkm*Tjk = Tjm=> Pm = Tjm* Pj In this case,Pm = Tjk * Tkm * Pj (transforms swapped) is erroneous and would be nice if it was caught at compile time.

Here's what I've tried so far:

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*
}

however in this case, because of the using statements all of the coordinate frames can be implicitly converted to each other and so no compile errors are given. The static_assert also doesn't catch it. Removing the using statement cause other compiler errors full example is here: https://godbolt.org/z/drPYG3

Is what I'm after possible and if so how would I do this? It would be a bonus if there was a way to use concepts to make friendlier compiler messages.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...