ANYbotics/kindr

Why is there a differentiation between Pose and HomogeneousTransformation?

Closed this issue · 14 comments

The documentation says:

The class kindr::poses::PoseBase serves as an interface for a pose of a rigid body, i.e. the position and orientation of a rigid body. All types of representations of a pose, such as homogeneous transformations and screw motions, are derived from this base class.

I don't understand the distinction here...

Distinction of what?

The difference between a pose, a homogeneous transformation, and a screw motion.

In my opinion the pose can be represented with different paramaterizations. One way is to use homogenous transformations, another ways is to describe the position and orientation with a screw motion.

I agree, but then I think it should be a one-depth class hierarchy:

TransformationBase --> all instantiations

to the user, all of them do the same thing: transform points from one frame to another.

Also, I like "TransformationBase" rather than "PoseBase". PoseBase and OrientationBase would be a pair whereas "TransformationBase" pairs with "RotationBase".

Please check out and comment on my implementation!

Thanks!

I also did not like the Pose/Rotation pairing. We could rename it to Transformation, but then we should rename everything... file names, namespaces, etc.

I looked at the code, but I don't like that you removed the layer with HomogenousTransformationBase.

For the rotations we have:
RotationBase (interface for all rotation types)
EulerAnglesBase (interface for all Euler angles representations)
EulerAnglesZyxBase (interface for z-y-x convention)
EulerAnglesZyx (implementation of z-y-x convention based on Eigen)

For the transformations, we would have:
TransformationBase (interface for all transformation types)
HomogeneousTransformationBase (Interface for all homogeneous transformations)
HomogeneousTransformation (implementation of homogeneous transformation based on Eigen)
HomogeneousTransformationPosition3RotationQuaternion (implementation of homogeneous transformation with specified data containers)

The methods getPosition() and getRotation() are methods of the homogeneous transformation, but not of the transformation.

@HannesSommer any comments?

Ah and yes, in the Rotatoin case we sometimes have some sublayers for 2. That happens if there are several mathematical variations of one construction. Eg. the different ways to have EulerAngles. @gehrinch brought up that example.

How could you have a transformation with no possibility to get the position or rotation.

And should we call it "Translation" to match "Rotation"? I feel like "Position" and "Attitude" are a pair.

I still don't understand the class hierarchy. What makes a quaternion and pose pair a homogeneous transformation?

I also don't understand what is gained from the extra layers. It looks to me as if the implementations are all using shadowing---not inheritance or concept checking---so there is no benefit in the second layer.

How about an example, what is gained from the EulerAnglesBase class?

We can add getters for position and rotation, but they should return copies only (not references). The screw motion would not store a position and a rotation.

We can rename position to translation in the transformation context.

"What makes a quaternion and pose pair a homogeneous transformation?"
-> I believe that some people want to store rather a rotation quaternion than a rotation matrix (or a 4x4 matrix) in a homogeneous transformation (could be for optimization reasons). If I remember correctly, ROS does this in a similar fashion. The homogeneous transformation object should have methods to get and set 4x4 matrices and operate on homogeneous coordinates. I admit that many features are missing.

@HannesSommer Can you comment on the shadowing/inheritance concept?

About the confusion of homogeneous transformation and what we need here as base class. I think we want to model 3d poses by there displacement brother. Whatever that is. Let's call it SE3 for the moment, because it is one way to look at them. To realize SE3 mathematically the 4x4 matrices - I would call homogeneous transformation are only one way. Pairs of rotation and translation are others.

But we should try to not mix the problem of SE3 vs. homogeneous transformation and for example position vs. translation. These discussions are totally different. The first is a question of being special case or instance or being the same. The second is the old question of proper distinction between position notions and displacement notions.

OH, I've just discovered, that my long comment about the layers is missing... Where has it gone? That happens already the second time to me. Writing a long comment but loosing it. Any Idea what was wrong? Could it be that the collision management for comments of github is a bit funny?

It was before my https://github.com/ethz-asl/kindr/issues/37#issuecomment-46827861 comment. That is why it seems so badly connected.. Sorry :(. I will try again soon.

So again:

I like the three layers in the hierarchy and there is good reason for them. I try to explain at the Rotation example.

  1. Layer:
    The abstract mathematical concept (like Rotation of Euclidean space) that is only given by properties (it rotates the Euclidean space) as required by modeling physics.

It defines the the interface how to apply it. (e.g. .rotate)

  1. Layer:
    The layer of mathematical construction. Here is defined how the properties are achieved by a mathematical construct and essentially how it is parametrized. E.g. have a rotation matrix or a rotation vector or Euler angles of some sort. In our case this layer is also parametrized on the primitive type - which fits somehow as the level of approximation is still a question of mathematical construction.

It defines the interface how to manipulate the construct.

So this layer should be enough for the user to apply and modify the whole thing. So basically how to employ rotation matrices or Euler angles in kindr. The only decision the user must make not based on information from the second and first layer is which implementation (third layer) too use.

For the library developer this is the place to put code that is implementation independent (so of the third layer, s. below). This functionality is easy to spot by exploiting the predicate : "This functionality makes sens already from the pure mathematical construct!". E.g. the exponential map or the conversions between different constructions. So the more we put here the better. However, it might be the short solution to delegate functionality of that kind to the third layer if one know that the math is already implemented in a library used by a particular implementation. To save some work here or gain speed by implementation specific code.

  1. Layer:
    This is the layer of implementation. It basically defines how the parameters are laid out in memory and how grouped in other objects (not part of the mathematical construct), which algebra library to use and depend.
    This is where to put all other code. So optimized based on memory layout and internal object structure.

The normal user should never need to look into that layer and never rely on anything there if not documented as specifically part of the public API of kindr.

So, @furgalep, which layers would you like to merge?

For the rigid body transformation case I would see this hierarchy :

SE3Base
->
(HomogeneousTransformationBase, all pairs of any rotation concept with any translation concept (all in the sense of the second Layer), screw motions (basically the analog of rotation vectors, right?) and so on)
->
All their implementations

I used SE3 because I think transformation is way to general!
I know it is very common. But I would really like to have a different abbreviation of "rigid body transformation" (what I believe this "transformation" stands for) that is somehow less too general. RBTransformation? Then still the 3d aspect is missing (there are 2d rigid body transformations as well, after all). That is why I suggest just SE3.

That this might be a bad model for a pose is a completely different topic (that is SE3 vs SO3xR3) and for kindr it doesn't really matter in the end - I believe.

My first version was better - sorry - I hate browsers or github or myself - whoever killed the first one :).

About the second layer and inheritance : The problem is that with static polymorphism there is no simple language construct like for virtual functions to enforce implementation. Only various tricks exist to implement a kind of concept checking. To maintain and think of that while starting a library in a more agile fashion (it was developed more test driven) is a waste of time in my opinion. But as I wrote somewhere else. Now could be the phase to think about implementing concept checking as part of stabilizing the internal interface for people extending the library.

I'm actually not sure whether we should start that now. But we could at least start to think about how to do it in the (near) future.
@furgalep : you can think of the first and second layer as the layers to put concept checks for the implementing classes in (but they are not there, yet) as well as providing documentation for the library user.

This is simplified now in kindr 1.0.0.