Random Quaternions


Hello!

How can I generate random quaternions (with the probability is distributed along the rotation space)?

And the same for normalized vectors?

These would be interesing addons to the engine if they are not already there (I couldn't find them).

Thank you!

I have a statistically random 3D vector algorithm that could easy be converted to a quaternion. I don't know if that is of any use to you but, I use it for 3D spacial random maneuvers.

Err… it all depends what you mean by random… Do you mean uniform? In what sense?



A rotation Quaternion is composed of w, x, y and z components, such that w+x+y+z = 1, so the easiest way to do this would be to create it like this:



Quaternion q = new Quaternion();

float sum;

sum = q.w = FastMath.nextRandomFloat();

sum += q.x = FastMath.nextRandomFloat()(1-sum);

sum += q.y = FastMath.nextRandomFloat()
(1-sum);

sum += q.z = FastMath.nextRandomFloat()*(1-sum);



But you have to take into account that this is by no means uniform in rotation space… actually it does not make ANY sense to talk about uniformity there unless you define a (probability) measure there, and even then I am not sure one exists.

A uniformly distributed point on a sphere in x, y and z. You can then do a uniformly distributed rotation around (x, y, z) giving you (x', y', z', w) so you have a completely uniform direction AND orientation.

Better still, I decided to add to my Random library. Here is what I believe you need:



    public Vector nextVector() {

        double theta = nextUniform(0.0, 2.0Math.PI);

        double rawX = Math.sin(theta);

        double rawY = Math.cos(theta);

        double z = nextUniform(-1.0, 1.0);

        double phi = Math.asin(z);

        double scalar = Math.cos(phi);

        double x = rawX
scalar;

        double y = rawYscalar;

        return new Vector(x, y, z);

    }



    public Vector nextQuaterion(){

        Vector v = nextVector();

        double x = v.getX();

        double y = v.getY();

        double z = v.getZ();

        double theta = nextUniform(0.0, 2.0
Math.PI);

        double cosTheta = Math.cos(theta);

        double sinTheta = Math.sin(theta);

        return new Vector(xsinTheta, ysinTheta, z*sinTheta, cosTheta);

       

    }



Note these Vectors are general n-dimensional vectors but I am only using 3 and 4 dimensions in this code.

Scorpius said:

A uniformly distributed point on a sphere in x, y and z. You can then do a uniformly distributed rotation around (x, y, z) giving you (x', y', z', w) so you have a completely uniform direction AND orientation.


When you claim that x,y,z is a uniformly distributed point in the unit sphere, which measure are you suggesting? It is clear from your code that you are using a variant of polar coordinates, and that is far from uniform... Also, your implementation is much slower than what I suggested... I realized what I suggested does not make sense, because the condition for a quaternion to be a rotational quaternion is that w^2 + x^2 + y^2 + z^2 = 1... Sorry about that, but still no uniformity.

A correct version of that code would be:


Quaternion q = new Quaternion();
float sum = 0;
q.w = FastMath.nextRandomFloat()*2 - 1;
sum += q.w*q.w;
q.x = FastMath.sqrt( 1-sum )*( FastMath.nextRandomFloat()*2 - 1 );
sum += q.x*q.x;
q.y = FastMath.sqrt( 1-sum )*( FastMath.nextRandomFloat()*2 - 1 );
sum += q.y*q.y;
q.z = FastMath.sqrt( 1-sum )*( FastMath.nextRandomFloat() < 0.5 ? -1 : 1 );

I know a fair amount about mathematical statistics. The algorithm above has been thoroughly tested and confirmed. The mathematics has also been checked and rechecked. As I said before, this is a tried and tested method for determining a uniformly random direction.

I don't mean to doubt that you know math… it is just that I am asking in which sense you mean uniform… If you mean uniform in spherical coordinates, then I agree… but that is far from uniform in cartesian coordinates. Also, your code is less efficient than the one I provided, you are always creating new objects which is somewhat wasteful.



Anyway… Don't worry, I don't want to start a flame-war here… two solutions have been provided… Use the one that suits you better.

See pg 19, equation 33 of the Global Illumination Compendium.  Generating a random point on a sphere.










Nice article harsha, thanks, and it proves my point.



I believe the question was about random spherical homogeneity, and in that sense I mean uniform. I then added homogeneous rotation to form a quaternion, just for a twist (sorry, couldn't avoid the joke). If you are unhappy with the efficiency of the algorithm, please feel free to post a more efficient version without removing its generality. I'm sure we would all appreciate that. I would.



:smiley:

Thank you very much guys for your comments. You solved my question.



I was asking (without really knowing it) for that random spherical homogeneity, including the twist.



The reason I asked is because I don't really know if there could be some kind of equivalence between two apparently different quaternions. I suspected that there had to be an adequate way of forming a "rotation" with the same probability than any other "rotation".



Later I realized that a quaternion doesn't represent a natural inertial rotation, but that's a different story.



You have been very useful, thanks again all.