Python or Matlab rotate with spline interpolation order higher than 5 - rotation

I need to do a rotation with a spline interpolation of high order >5. I insist on the fact that it is for interpolating rotated data, not upsampling.
I found : https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.rotate.html?highlight=rotate#scipy.ndimage.rotate
but only up to splines order 5. (I know orders > 3 are unusual, nevertheless I do need it).
any idea of a Python/Matlab or way to implement higher order spline interpolation for rotation ?

Related

In ThreeJS Object3D.applyMatrix4 is not continuous

I was transforming an object with a matrix A using Object3D.applyMatrix4 and I found that at one point it didn't preserve an eigen vector's direction.
So I tried animating interpolation between Identity Matrix I and A and I found this:
How could the transformation be not continuous?
Linear interpolation of rotation matrices isn't mathematically sound. The vectors composing a rotation matrix need to be unit length.. or at least stay a consistent length.
Imagine a clock with a hand at 12, and a hand at 6.
If you Linearly interpolate the point at the tip of the 12 oclock hand, to the tip of the 6oclock hand, the point travels in a straight line from top of the clock to the bottom.
To interpolate the rotation represented by a 4x4 matrix, you can convert the rotations of the matrices, to quaternions, and .slerp (spherical linear interpolate) between those quaternions, then convert back to a matrix.
And then linearly interpolate the object.position. (although again.. this assumes linear motion between keyframes).
Now in the case that the rotation is small, you can get away with linearly interpolating the matrix, but you will need to orthonormalize it at each step, to reshape the mesh into one that has consistent length vectors that are orthogonal to each other. That isn't that hard.. you use a combination of dot products, multiplies and adds of the vectors forming the matrix rows (or columns, i forget) to orthonormalize the matrix. But its more of a pain, and less accurate than just using quaternions and .slerp.
#manthrax 's answer pointed out the fundamental problem of interpolating a matrix linearly which I wasn't aware of at the time and he was right about that. But the real problem was that Object3D.applyMatrix4 wasn't the right function for explicitly defining local matrix. I tried setting Object3D.matrix property directly and it worked. And the linear interpolation (although I shouldn't do that) became continuous.

Why is it difficult to use Quaternions for the LBS(Linear Blend Skinning) formula?

Why would be difficult to use quaternions for the LBS(Linear Blend Skinning) formula?:
See picture:
Linear Blend Skinning Formula
P': Point transformed
P: Point
wi: matrix of weights
wi(P): weight of point P in entry i
Ti: Transform at i
I couldn't really find an answer, I thought that maybe because a transform matrix can store 4x4 values rather than quaternions which can only represent a rotation in 4 values then we wouldn't have a way to represent both a translation and rotation for any bone using a quaternion but I'm not too sure.
You are absolutely right. The fact that quaternions can only represent rotations (and scalings) makes them unusable for this task. There are extensions to quaternions (dual quaternions) that circumvent this restriction. And then, blending linearly works pretty well.
Also, keep in mind how to transform a point with a quaternion - you have two multiplications instead of one. Therefore, you would usually first blend the quaternions and then transform the point. Although blending the transformed points can be done as well, this makes little sense as it is computational heavier and has the same problems as simple LBS.
Whether or not the question aims at something more is still open.

Is it possible to rotate an object around an arbitrary origin using quaternions?

I'm wondering if it's possible to define an object's rotation not around itself but around an arbitrary origin, effectively removing the need to pass XYZ position vectors to the GPU. So instead of having XYZ position + XYZW quaternion, we could pre-compute a quaternion that would solely define the object's position and rotation all by itself?
It is not possible with a pure quaternion. A quaternion has only four degrees of freedom. If you use it for transformation, these will be three degrees for rotation and one degree for scaling. There is just nothing more a quaternion can offer.
Dual Quaternions, however, can represent translations (and thus also rotations about arbitrary axes). This comes with the cost of four more numbers to store and usually it is not worth the trouble. The advantage of dual quaternions is that rigid body transforms can be expressed in a consolidated way with a nice algebraic background. It is usually used for animation to interpolate between multiple transforms in a consistent way.
In most cases, the advantages of dual quaternions do not outweigh their complexity. Hence, using a simple offset vector is more reasonable most of the time.

Average transformation matrix for a list of transformations

I have multiple estimates for a transformation matrix, from mapping two point clouds to each other via ICP (Iterative Closest Point).
How can I generate the average transformation matrix for all these matrices?
Each matrix consists of a rigid translation and a rotation only, no scale or skew.
Ideally I would also like to calculate a weighted average, but an unweighted one is fine for now.
Averaging the translation vectors is of course trivial, but the rotations are problematic. One approach I found is averaging the individual base vectors for the rotations, but I am not sure that will result in a new orthonormal base, and the approach seems a little ad-hoc.
Splitting the transformation in translation and rotation is a good start. Averaging the translation is trivial.
Averaging the rotation is not that easy. Most approaches will use quaternions. So you need to transform the rotation matrix to a quaternion.
The easiest way to approximate the average is a linear blending, followed by renormalization of the quaternion:
q* = w1 * q1 + w2 * q2 + ... + w2 * qn
normalize q*
However, this is only an approximation. The reason for that is that the combination of two rotations is not performed by adding the quaternions, but by multiplying them. If we convert quaternions to a logarithmic space, we can use a simple linear blend (because multiplication will become additions). Then transform the quaternion back to the original space. This is the idea of the Spherical Average (Buss 2001). If you're lucky, you find a library that supports log and exp of quaternions:
start with q* as above
do until convergence
for each input quaternion i (index)
diff = q[i] * inverse(q*)
u[i] = log(diff, base q*)
//Now perform the linear blend
adapt := zero quaternion
weights := 0
for each input quaternion i
adapt += weight[i] * u[i]
weights += weight[i]
adapt *= 1/weights
adaptInOriginalSpace = q* ^ adapt (^ is the power operator)
q* = adaptInOriginalSpace * q*
You can define a threshold for adaptInOriginalSpace. If it is a very very small rotation, you can break the loop. This algorithm is proven to preserve geodesic distances on a sphere.
http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation and http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion will give you some elegant mathematics and a way to turn a rotation matrix into an angle of rotation round an axis of rotation. There will be two possible representations of each rotation, with different signs for both angle of rotation and axis of rotation.
You could convert everything and normalize them to have +ve angles of rotation, then work out the average angle of rotation and the average axis of rotation, renormalising this into a unit vector.
OTOH if your intention is to work out the most accurate possible estimate of the transformation, you need to write down some measure of the goodness of fit of any candidate transformation - a sum of squared errors is often mathematically convenient - and then solve an optimization problem to work out which transformation minimizes the sum of squared errors. This is at least easier to justify than taking an average of individually error-prone estimates, and may well be more accurate.
If you have an existing lerp method, then there is a trivial solution:
count = 1
average_transform = Matrix.Identity(4)
for new_transform in list_of_matrices:
factor = 1/count
average_transform = lerp(average_transform, new_transform, factor)
count += 1
This is only useful because lots more mathermatics packages have the ability to lerp matrices than to average lots of them.
Because I haven't come across this method elsewhere, here's an informal proof:
If there is one matrix, use just that matrix (factor will equal 1 for first matrix)
If there are two matrices, we need 50% of the second one (second factor is 50% so we lerp to half way between the existing first one and the new one)
If there are three matrices we need 33% of each, or 66% of the average of the first two and 33% of the third. The lerp factor of 0.3333 makes this happen.
And so on.
I haven't tested extensively with matrices, but I've used this successfully as a rolling average for other datatypes.
The singular value decomposition (SVD) can be used here.
Take the SVD of the sum of the rotation matricies, and then the average rotation matrix is simply given by Ravg = UV'.
"sdfgeoff" I can't comment in your answer because I'm new here, but you are the most correct, I think. Beutifull and elegant solution, by the way. Would be perfect if you use Spherical Linear Interpolation (SLERP) with quaternions, instead of Linear Interpolation (LERP) because quaternions that map rotations (quaternions with norm 1) define a sphere in 4D, and interpolating between then is in fact interpolate between two point in a sphere surface.
With my experience from point cloud registration, I wuold like to say that this will not work. ICP don't return random rotations in the likehood of the correct rotation. You need to use a beter algorith to register you point clouds (Global Registration algorithms, like FPFH, 4PCS, K4PCS, BSC, FGR, etc). Or a better initial guess for the transformation. ICP will only give you totally wrong rotations (when stuck in local minima) or almost perfect rotations, when initialized with good initial transformations.
Conclusion: averaging it will not work.
I would suggest taking a look at "Average" of multiple quaternions? for a more elaborate discussion on how to compute the average of rotations.

Creating continuous splines / Making a smooth transition between splines

I'm working on a project that involves creating a spline from a defined set of points (tens of thousands of points).
I first create a spline for the first 1000 points and simulate "driving" on that path with an arrow (it is drawn using the tangent and the current point on spline). When I'm approaching the end of the path I take the next 1000 points and create a new spline and continue my "driving".
The problem that I have is the fact that the splines (previous spline and current spline) don't match at the end. By not matching I mean they don't have the same tangent (first derivative doesn't match) and there is a difference between the last point of the previous spline and first point on the new spline (this is because I'm not using an interpolating spline but a smooth spline - see NOTE1 below). This makes my arrow "jump" at the end of spline, when switching to the newly created spline.
NOTE1: I'm NOT using interpolating splines. I'm using smooth splines. See here and here for more details. This means that the set of points given as input may not be on the resulting spline (In my case they are quite close to the spline - but usually NOT on the spline).
NOTE2: Using an interpolating spline is out of the question because I have a lot of noise in the data used for computing spline.
NOTE3: Computing a spline for the entire set of points takes a lot of time (more than 30 seconds) on a 3Ghz PC with 2 GB RAM (our target platform for the application); so doing this is also out of the question.
I'd be interested to overcome that unwanted "jump" when switching splines.
So my questions are:
Are there some ways/algorithms for doing a smooth "jump"/transition to the new spline?
Can I do something with a special type of spline to overcome this? (This is what I tried so far without a considerable improvement).
Thank you for any ideas,
Iulian
This is a pretty unsophisticated suggestion, admittedly, but one obvious hack would be to fit overlapping rather than distinct subsets of points and then interpolate between the resulting splines in the overlapping region.
Eg, generate a smooth spline for points 1-1000. While you're animating from 1-900, generate the next spline from 901-1900. For the region between 901 and 1000, use a weighted combination of the corresponding positions in both splines, where the weighting is 1:0 at 901 and 0:1 at 1000. The same for 1801-1900 and so on.
I'd guess that a simple linear interpolation would suffice and the margins probably wouldn't need to be huge, but you could determine that empirically.

Resources