Skip to content

Commit c54d1d9

Browse files
committed
利用四元数实现三维里程的加减,并在 xy 面上测试
1 parent 937cd9d commit c54d1d9

5 files changed

Lines changed: 67 additions & 6 deletions

File tree

src/main/kotlin/org/mechdancer/geometry/transformation/Builder.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ import org.mechdancer.geometry.angle.toVector
99
import kotlin.math.cos
1010
import kotlin.math.sin
1111

12-
fun pose(x: Number = 0, y: Number = 0, theta: Number = 0) =
12+
fun pose2D(x: Number = 0, y: Number = 0, theta: Number = 0) =
1313
Pose2D(vector2DOf(x, y), theta.toRad())
1414

1515
fun odometry(x: Number = 0, y: Number = 0, theta: Number = 0) =
1616
Pose2D(vector2DOf(x, y), theta.toRad())
1717

18+
fun pose3D(x: Number = 0, y: Number = 0, z: Number = 0, d: Vector3D = vector3DOfZero()) =
19+
Pose3D(vector3DOf(x, y, z), d)
20+
1821
fun quaternion(a: Number = 0, b: Number = 0, c: Number = 0, d: Number = 0) =
1922
Quaternion(a.toDouble(), b.toDouble(), c.toDouble(), d.toDouble())
2023

@@ -71,6 +74,6 @@ fun Pose3D.toTransformation(): Transformation {
7174
})
7275
}
7376

74-
fun Pose2D.toPose3D(): Pose3D =
77+
fun Pose2D.to3D(): Pose3D =
7578
Pose3D(p = vector3DOf(p.x, p.y, 0),
76-
d = vector3DOf(0, 0, d.asRadian()))
79+
d = vector3DOf(0, 0, d.asRadian() / 2))

src/main/kotlin/org/mechdancer/geometry/transformation/Pose3D.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,23 @@ data class Pose3D(
3838
val (v0, q0) = toQuaternions()
3939
val (v1, q1) = delta.toQuaternions()
4040
return pose3D(v0 + q0 * v1 * q0.conjugate,
41-
q0 * q1)
41+
q1 * q0)
42+
}
43+
44+
/** 里程回滚到增量 [delta] 之前 */
45+
infix fun minusDelta(delta: Pose3D): Pose3D {
46+
val (v0, q0) = toQuaternions()
47+
val (v1, q1) = delta.toQuaternions()
48+
val qi = q1.conjugate * q0
49+
return pose3D(v0 - qi * v1 * qi.conjugate, qi)
50+
}
51+
52+
/** 计算里程从标记 [mark] 到当前状态的增量 */
53+
infix fun minusState(mark: Pose3D): Pose3D {
54+
val (v0, q0) = mark.toQuaternions()
55+
val (v1, q1) = toQuaternions()
56+
return pose3D(q0.conjugate * (v1 - v0) * q0,
57+
q1 * q0.conjugate)
4258
}
4359

4460
override fun toString() = "p = ${p.simpleString()}, u = ${u.simpleString()}, θ = $theta"

src/main/kotlin/org/mechdancer/geometry/transformation/Quaternion.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ data class Quaternion(
2828
/** 求逆 */
2929
val inverse get() = conjugate / square
3030

31+
operator fun unaryMinus() =
32+
Quaternion(-a, -b, -c, -d)
33+
3134
operator fun plus(others: Quaternion) =
3235
Quaternion(a + others.a,
3336
b + others.b,

src/test/kotlin/org/mechdancer/geometry/transformation/TestPose2D.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import org.junit.Test
44
import org.mechdancer.algebra.implement.vector.vector2DOf
55
import org.mechdancer.algebra.implement.vector.vector2DOfZero
66
import org.mechdancer.geometry.angle.toRad
7-
import org.mechdancer.geometry.transformation.Pose2D.Companion.pose
87
import kotlin.math.PI
98

109
class TestPose2D {
@@ -13,7 +12,7 @@ class TestPose2D {
1312
*/
1413
@Test
1514
fun test() {
16-
val step0 = pose()
15+
val step0 = pose2D()
1716
assert(step0 == Pose2D(vector2DOfZero(), .0.toRad())) {
1817
"里程计初始化错误:$step0"
1918
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package org.mechdancer.geometry.transformation
2+
3+
import org.junit.Test
4+
import org.mechdancer.algebra.implement.vector.vector2DOf
5+
import org.mechdancer.algebra.implement.vector.vector3DOfZero
6+
import org.mechdancer.geometry.angle.toRad
7+
import kotlin.math.PI
8+
9+
class TestPose3D {
10+
/**
11+
* 测试里程计算法
12+
*/
13+
@Test
14+
fun test() {
15+
val step0 = pose3D()
16+
assert(step0 == Pose3D(vector3DOfZero(), vector3DOfZero())) {
17+
"里程计初始化错误:$step0"
18+
}
19+
20+
val delta1 = Pose2D(vector2DOf(3.0, 4.0), (PI / 2).toRad()).to3D()
21+
22+
val step1 = step0 plusDelta delta1
23+
assert(step1 == delta1) {
24+
"里程计累加错误:$step1$delta1"
25+
}
26+
27+
val step2 = step1 minusDelta delta1
28+
assert(step2 == step0) {
29+
"里程计回滚错误:$step2$step0"
30+
}
31+
32+
val delta2 = Pose2D(vector2DOf(1.0, 1.0), (-PI / 4).toRad()).to3D()
33+
34+
val step3 = step2 plusDelta delta1
35+
val step4 = step3 plusDelta delta2 minusState step3
36+
assert(step4 == delta2) {
37+
"里程计标记错误:$step4$delta2"
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)