Skip to content

Commit 0fdd99d

Browse files
committed
Make slerp more robust
Make sure that slerp goes through the shortest path
1 parent 35e72d1 commit 0fdd99d

3 files changed

Lines changed: 39 additions & 1 deletion

File tree

source/Quaternion.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <deal.II/base/signaling_nan.h>
99

1010
#include <cmath>
11+
#include <numeric>
1112

1213
namespace adamantine
1314
{
@@ -81,6 +82,18 @@ Quaternion &Quaternion::operator*=(Quaternion const &other)
8182
return *this;
8283
}
8384

85+
Quaternion &Quaternion::operator*=(double const &scalar)
86+
{
87+
for (int i = 0; i < 4; ++i)
88+
{
89+
_quaternion[i] *= scalar;
90+
}
91+
92+
build_rotation_matrices();
93+
94+
return *this;
95+
}
96+
8497
Quaternion &Quaternion::operator/=(Quaternion const &other)
8598
{
8699
ASSERT(_is_valid, "");
@@ -162,4 +175,10 @@ void Quaternion::build_rotation_matrices()
162175
}
163176
}
164177
}
178+
179+
double dot_product(Quaternion const &p, Quaternion const &q)
180+
{
181+
return std::inner_product(p._quaternion.begin(), p._quaternion.end(),
182+
q._quaternion.begin(), 0.);
183+
}
165184
} // namespace adamantine

source/Quaternion.hh

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* SPDX-FileCopyrightText: Copyright (c) 2025, the adamantine authors.
1+
/* SPDX-FileCopyrightText: Copyright (c) 2025 - 2026, the adamantine authors.
22
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
33
*/
44

@@ -77,6 +77,11 @@ public:
7777
*/
7878
Quaternion &operator*=(Quaternion const &other);
7979

80+
/**
81+
* Multiply the quaternion with a scalar.
82+
*/
83+
Quaternion &operator*=(double const &scalar);
84+
8085
/**
8186
* Multiply the quaternions using the inverse of @p other.
8287
*/
@@ -88,6 +93,11 @@ public:
8893
*/
8994
void pow(double const exp);
9095

96+
/**
97+
* Compute the dot product of two quaternions.
98+
*/
99+
friend double dot_product(Quaternion const &p, Quaternion const &q);
100+
91101
private:
92102
/**
93103
* Build the different rotation matrices.

source/ScanPath.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,15 @@ Quaternion ScanPath::get_quaternion(double const time) const
325325

326326
Quaternion interpolated_rotation =
327327
_segment_list[current_segment].end_rotation;
328+
329+
// If the dot product of the initial quaternion and the final rotation is
330+
// negative, slerp will take the long way instead of the short path. In that
331+
// case, we need to negate one of the quaternion.
332+
if (dot_product(segment_start_rotation, interpolated_rotation) < 0.)
333+
{
334+
interpolated_rotation *= -1.;
335+
}
336+
328337
interpolated_rotation /= segment_start_rotation;
329338
interpolated_rotation.pow((time - segment_start_time) / duration);
330339
interpolated_rotation *= segment_start_rotation;

0 commit comments

Comments
 (0)