Re: [eigen] Euler-angles and partial reductions API design |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen@xxxxxxxxxxxxxxxxxxx
- Subject: Re: [eigen] Euler-angles and partial reductions API design
- From: "Gael Guennebaud" <gael.guennebaud@xxxxxxxxx>
- Date: Sat, 19 Jul 2008 00:04:36 +0200
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to :subject:in-reply-to:mime-version:content-type :content-transfer-encoding:content-disposition:references; bh=20MUt8KkG+8/C4PgOxNbjYd1e/o4XFuBTL2QVTSyN5s=; b=Gv7y6SotWAUEqSpO3uK5rb80e6akXBmlo51hhWX9tumdKmVW3RxsBMjQzlKyRJQDKA 0lIGqfyMcjsFqBsDctk20d7BqEIxDsiAl/o5iyTfPVqPSTRbfMnQuoqV3TPLRsTxv/CI j21trppe++7aF6fj7LnVm0KhIWQZc05iDHeMc=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:in-reply-to:mime-version :content-type:content-transfer-encoding:content-disposition :references; b=KpfKoaPttXhN4jdQbsMTceSDT3yCapgbaccJ/iV2PLNvEC1AGVO7Q+6ZiJ3xwYGXK9 d5vcc4XIgWk3GVY78dyJwrDpvOsK7YHyk1gQSmkX5qAwNKkD7ciHxX6UKZdTKnnIKclt Ex9CMzgEIKnKjTXmK2/s2ZUn+2y7q20NezC8Q=
On Fri, Jul 18, 2008 at 11:10 PM, Benoît Jacob <jacob@xxxxxxxxxxxxxxx> wrote:
> I agree with you that operation on the right should be the default, as it's
> what OpenGL does. Whence the naming used in Eigen1. What I don't understand
> is how this is any issue in Eigen2 and the draft eulerangles API ? I mean,
> when you write rotationX(angleX) * m it's obviously multiplying m on the
> left; in Eigen1 or OpenGL it's more problematic because of the API not using
> natural math notation.
the issue is if we have a class (or function) which build a rotation
directly from 3 angles:
EulerAngles<float>(a0, a1, a2)
there might be 24 interpretations !!
in my second mail, I suggested to create only elementary rotations and
compose them manually such that there is no ambiguity:
rotationX(a0) * rotationY(a1) * rotationX(a2)
> The idea that I like best, among the ones you propose, is static
> MatrixBase::rotation{XYZ} functions. Let's not use functor classes unless
> needed, and I don't see the need here.
I was not referring to functor, but something like that:
template<typename Scalar>
class RotationX : public Matrix<Scalar,3,3> {
public:
Rotation(Scalar angle) { *this << .....sin, cos,....; }
};
anyway, maybe not very good as it creates new types...
In that case we indeed build matrices, so the composition of several
elementary rotations would not be optimal but:
1 - not too bad, for 3 rotations (i.e., 2 products) we have 54 ops
versus 21 ops...
2 - I don't see any use case where the perf of euler angles is
critical, again for me euler angles are not an optimization,
they are just a convenient way to setup the orientation of an object.
So, if you think that:
Matrix3f m2 = AngleAxis<float>(a1, Vector3f(1,0,0))
* AngleAxis<float>(a2, Vector3f(0,1,0))
* AngleAxis<float>(a3, Vector3f(0,0,1));
is not verbose and as easy to read as the version with RotationX(),
then let's just forget about Euler angles, and we are done.
But I would prefer to propose a shorter and safer path... IMO, writing
the basis vectors manually with Vector3f(0,1,0) is quite error prone
(you know, dyslexia etc.).
So, maybe with two typedef for AngleAxis<float / double>, and more
general shortcuts to write the basis vectors would be a good option as
well:
Vector3f::UnitX();
Vector3f::UnitY();
Vector3f::UnitZ();
Vector4f::UnitW();
and a generic:
VectorXf::Unit(i)
and they could simply return "identity().col(i)".
what do you think ?
gael.
> Indeed a EulerAngles class is needed
> because if rotation{XYZ} returned a matrix then doing
> rotationX(angleX)*rotationY(angleY)*rotationZ(angleZ)
> would be terribly inefficient. So rotation{XYZ} returns a EulerAngles object
> and the actual rotationation matrix is computed in operator= or
> EulerAngles::operator*(vector) (yes this lends itself very well to
> optimization and suddenly I think this could be the most useful use case for
> EulerAngles).
>
> I'm not a fan of the last option with typedefs, because "Xf" means
> dynamic-size-float so at least the naming is misleading (and as I said I
> prefer functions over short functor classes anyway).
>
> There is one thing that needs to be discussed. The whole point of EulerAngles
> is performance -- otherwise we could do as in Eigen1, i.e. do only a generic
> rotation(angle,vector) method. In many cases, the user will use only one
> eulerAngle, i.e.
> Matrix3f::rotationY(pi/12) * vector
> We don't want the EulerAngle::operator* to compute three sin/cos pairs when
> only one is needed! So the EulerAngles class is not so trivial to implement,
> There are up to 7 cases to handle,
> X, Y, Z, XY, YZ, XZ, XYZ,
> it looks a bit tedious. It might be possible to avoid the tediousness at zero
> overhead using template magic, but that is probably even more cumbersome to
> write!
>
> Cheers,
>
> Benoit
>
>
> On Friday 18 July 2008 02:00:15 Gael Guennebaud wrotationatione:
>> I agree Euler angles are somewhat useless (and might even be dangerous
>> for the beginners because of their apparent simplicity). Nevertheless
>> they remain really conveniant to specify/initialize the orientation of
>> an object as a concatenation of elementary rotationationations. In this
> context
>> I think it very important to be able to specify the order, otherwise
>> we completely miss the convenience point. So if we agree this is the
>> only use case, then we can drop the EulerAngles class, and provide and
>> alternative, more explicit and generic API. Actually currently it is
>> possible to mimic the proposed:
>>
>> Matrix3f m = EulerAngles<float,XYZ>(1,2,3);
>>
>> by
>>
>> Matrix3f m2 = AngleAxis<float>(1, Vector3f(1,0,0))
>> * AngleAxis<float>(2, Vector3f(0,1,0))
>> * AngleAxis<float>(3, Vector3f(0,0,1));
>>
>> that is a bit heavy (though quite often 1 or 2 elementary
> rotationationations
>> are enough to reach the desired orientation).
>> So what we could do is to make easier the creation of elementary
>> rotationationations using either:
>>
>> * static functions of Matrix:
>> Matrix3f m = Matrix3f::rotationationX(1) * Matrix3f::rotationationY(2) *
> Matrix3f::rotationationZ(3);
>>
>> * super short classes inheriting Matrix<Scalar,3,3> (or global functions)
>> Matrix3f m = rotationationX<float>(1) * rotationationY<float>(2) *
> rotationationZ<float>(3);
>>
>> * the same with typedef (or alias):
>> Matrix3f m = rotationationXf(1) * rotationationYf(2) * rotationationZf(3);
>>
>> I have to say I like this last option, though someones might find the
>> names not explicit enough ? it might also be confusing with
> the "rotationation"
>> vector operator (curl) ?
>>
>> gael.
>>
>> On Thu, Jul 17, 2008 at 8:00 PM, Christian Mayer <mail@xxxxxxxxxxxxxxxxx>
> wrotationatione:
>> > -----BEGIN PGP SIGNED MESSAGE-----
>> > Hash: SHA256
>> >
>> > Gael Guennebaud schrieb:
>> >> Let's start with the EulerAngles class of the geometry module. [...]
>> >
>> > Apart from the fact that EulerAngles are quite useless for real work I
>> > can understand that beginners usually want them to get a quick start...
>> >
>> > Generally it's best to keep the libaray as small and generic as possible.
>> >
>> > So I'd offer only one function that generates the rotationationation
> matrix. This
>> > function should have a fixed order (that's identical to OpenGL -
>> > although I didn't find a gl, glu or glut function that uses euler
>> > angles...).
>> >
>> > If the user wants a left or a right multiplication is totally up to him,
>> > so the library should try to be smarter :)
>> >
>> > CU,
>> > Christian
>> > -----BEGIN PGP SIGNATURE-----
>> > Version: GnuPG v1.4.6 (GNU/Linux)
>> >
>> > iD8DBQFIf4itoWM1JLkHou0RCD8LAJ0fLw/XfnBezR5i43q4Izln9Hy0VgCfZGDr
>> > dXdk5TfQ8eSvSDRjtxzFuWU=
>> > =JZq/
>> > -----END PGP SIGNATURE-----
>
>
>