Promedio de pares de cuaterniones
Si está intentando promediar sólo dos cuaterniones, puede utilizar la interpolación de cuaterniones ( slerp ) con un factor de interpolación de 0,5 para encontrar el "punto medio rotacional" entre los dos cuaterniones.
(Nótese que la Ec. 19 del trabajo de Markley et al. citado más abajo también da una solución directa / de forma cerrada para la media de dos cuaterniones. Esto puede o no dar el mismo resultado que slerp con un factor de interpolación de 0,5, no lo he mirado de cerca).
Promedio de más de dos cuaterniones
Existen al menos dos métodos para promediar más de dos cuaterniones.
1. Promedio directo (rápido/aproximado)
Si los cuaterniones representan rotaciones similares, y los cuaterniones están normalizados, y se ha aplicado una corrección para el "problema de la doble cobertura", entonces se pueden promediar directamente los cuaterniones y luego normalizar de nuevo el resultado, tratándolos como vectores de 4 dimensiones, para producir un cuaternión que represente una rotación aproximadamente media.
El problema de la doble cobertura es cuando $q$ y $-q \,$ representan la misma rotación, como señalaba el cartel original. Este problema puede resolverse negando algún subconjunto de los cuaterniones para garantizar que el producto punto de cualquier par de cuaterniones es positivo (o, por ejemplo, negativo).
Tenga en cuenta que cuanto más disímiles sean los cuaterniones involucrados, más inexacto será este método, ya que esto es sólo una aproximación al método de eigendecomposition -- por lo que sólo desea promediar juntos cuaterniones que ya son bastante similares en términos de las rotaciones que representan.
He medido este método 2,56 veces más rápido que el de eigendecomposición.
(La sintaxis utilizada corresponde a la biblioteca Java JOML)
public static Quaterniond averageApprox(Quaterniond[] quats, double[] weights) {
if (weights != null && quats.length != weights.length) {
throw new IllegalArgumentException("Args are of different length");
}
Quaterniond qAvg = new Quaterniond(0.0, 0.0, 0.0, 0.0);
for (int i = 0; i < quats.length; i++) {
Quaterniond q = quats[i];
double weight = weights == null ? 1.0 : weights[i];
// Correct for double cover, by ensuring that dot product
// of quats[i] and quats[0] is positive
if (i > 0 && quats[i].dot(quats[0]) < 0.0) {
weight = -weight;
}
qAvg.add(weight * q.x, weight * q.y, weight * q.z, weight * q.w);
}
return qAvg.normalize();
}
2. Eigendecomposición de la suma de productos exteriores (método de máxima verosimilitud)
Este método se basa en Markley y otros, Averaging Quaternions, Journal of Guidance, Control, and Dynamics, 30(4):1193-1196, junio de 2007 ecuaciones (12) y (13). Los autores demostraron que la solución es única y que corresponde a un criterio de máxima verosimilitud. ( aplicación de tbirdal de este mismo algoritmo, además de algunas variantes más potentes, se enlazaron desde un par de respuestas más).
(La sintaxis utilizada corresponde a la biblioteca Java JOML y a la biblioteca Apache Commons Math Linear Algebra)
public static Quaterniond average(Quaterniond[] quats, double[] weights) {
if (weights != null && quats.length != weights.length) {
throw new IllegalArgumentException("Args are of different length");
}
RealMatrix accum = MatrixUtils.createRealMatrix(4, 4);
for (int i = 0; i < quats.length; i++) {
Quaterniond q = quats[i];
double weight = weights == null ? 1.0 : weights[i];
RealVector qVec = MatrixUtils.createRealVector(
new double[] { q.x, q.y, q.z, q.w });
RealMatrix qOuterProdWeighted = qVec.outerProduct(qVec)
.scalarMultiply(weight);
accum = accum.add(qOuterProdWeighted);
}
EigenDecomposition eigDecomp = new EigenDecomposition(accum);
double[] ev0 = eigDecomp.getEigenvector(0).toArray();
return new Quaterniond(ev0[0], ev0[1], ev0[2], ev0[3]).normalize();
}
0 votos
Google da es.wikipedia.org/wiki/interpolación_de_cuaterniones_generalizada Alguien que sepa más podrá ampliar la información.
0 votos
@PeterTaylor esa página de Wikipedia ya no existe, pero probablemente la que buscas es es.wikipedia.org/wiki/Slerp . Véase también mi nueva respuesta más abajo para más información.
0 votos
Para tratar específicamente la cuestión de la doble cubierta (es decir ${\bf q}$ y $-{\bf q}$ que representa la misma rotación), consulte esta pregunta y respuesta: math.stackexchange.com/preguntas/3888504 . Para saber cómo aplicar esto al promedio de cuaterniones, consulta mi respuesta a tu pregunta: math.stackexchange.com/a/3435296/365886
0 votos
Relacionados: stackoverflow.com/questions/12374087/