@@ -26,34 +26,77 @@ def define_subparser(subparsers):
26
26
def compute_full_trajectory (keyFrames , poseTrails , outputToCam ):
27
27
import spectacularAI
28
28
import numpy as np
29
+ from scipy .spatial .transform import Rotation as R
30
+ from scipy .spatial .transform import Slerp
31
+
32
+ deltas = []
33
+ for i , (tVio , trail ) in enumerate (poseTrails ):
34
+ if i == 0 : continue
35
+
36
+ t1Trail , p1 = trail [0 ]
37
+ t0Trail , p0 = trail [1 ]
38
+ assert (t0Trail < t1Trail )
39
+
40
+ # TODO: support using older deltas
41
+ t1 = tVio
42
+ t0 = poseTrails [i - 1 ][0 ]
43
+ assert (t0 < t1 )
44
+
45
+ fwd = np .linalg .inv (p0 ) @ p1
46
+ bwd = np .linalg .inv (p1 ) @ p0
47
+ deltas .append ((t0 , t1 , fwd , bwd ))
29
48
30
49
trajectory = {}
31
50
for kf in keyFrames .values ():
32
51
camPose = kf .frameSet .primaryFrame .cameraPose .pose
33
52
pose = camPose .asMatrix () @ outputToCam
34
53
trajectory [camPose .time ] = (0 , pose )
35
-
36
- # TODO: can be improved
37
- STEP_PENALTY = 0.5
38
- for tOlder , tNewer , newerToOlder in poseTrails [::- 1 ]:
39
- if tNewer in trajectory :
40
- olderToNewer = np .linalg .inv (newerToOlder )
41
- dt , poseNewer = trajectory [tNewer ]
42
- dt += tNewer - tOlder + STEP_PENALTY
43
- if tOlder not in trajectory or trajectory [tOlder ][0 ] > dt :
44
- trajectory [tOlder ] = (dt , poseNewer @ olderToNewer )
45
- if tOlder in trajectory :
46
- dt , poseOlder = trajectory [tOlder ]
47
- dt += tNewer - tOlder + STEP_PENALTY
48
- if tNewer not in trajectory or trajectory [tNewer ][0 ] > dt :
49
- trajectory [tNewer ] = (dt , poseOlder @ newerToOlder )
50
-
51
- for t in sorted (trajectory .keys ()):
52
- pose = spectacularAI .Pose .fromMatrix (t , trajectory [t ][1 ])
54
+ assert ([camPose .time in [t for t , _ in poseTrails ]])
55
+
56
+ trajectoryFwd = { k : v for k , v in trajectory .items () }
57
+ for t0 , t1 , fwd , _ in deltas :
58
+ if t0 not in trajectoryFwd : continue
59
+ dt , pose0 = trajectoryFwd [t0 ]
60
+ dt += t1 - t0
61
+ if t1 not in trajectoryFwd or trajectoryFwd [t1 ][0 ] > dt :
62
+ trajectoryFwd [t1 ] = (dt , pose0 @ fwd )
63
+
64
+ trajectoryBwd = { k : v for k , v in trajectory .items () }
65
+ for t0 , t1 , _ , bwd in deltas [::- 1 ]:
66
+ if t1 not in trajectoryBwd : continue
67
+ dt , pose1 = trajectoryBwd [t1 ]
68
+ dt += t1 - t0
69
+ if t0 not in trajectoryBwd or trajectoryBwd [t0 ][0 ] > dt :
70
+ trajectoryBwd [t0 ] = (dt , pose1 @ bwd )
71
+
72
+ for t , _ in poseTrails :
73
+ if t not in trajectoryFwd :
74
+ if t not in trajectoryBwd :
75
+ print (f"Warning: missing pose at time { t } " )
76
+ continue
77
+ pose = trajectoryBwd [t ][1 ]
78
+ elif t not in trajectoryBwd :
79
+ pose = trajectoryFwd [t ][1 ]
80
+ else :
81
+ dtFwd , poseFwd = trajectoryFwd [t ]
82
+ dtBwd , poseBwd = trajectoryBwd [t ]
83
+ if dtFwd == 0 :
84
+ pose = poseFwd
85
+ elif dtBwd == 0 :
86
+ pose = poseBwd
87
+ else :
88
+ thetaFwdToBwd = dtFwd / (dtFwd + dtBwd )
89
+ pose = np .eye (4 )
90
+ pose [:3 , 3 ] = poseFwd [:3 , 3 ] * (1 - thetaFwdToBwd ) + poseBwd [:3 , 3 ] * thetaFwdToBwd
91
+ rFwd = poseFwd [:3 , :3 ]
92
+ rBwd = poseBwd [:3 , :3 ]
93
+ pose [:3 , :3 ] = Slerp ([0 , 1 ], R .from_matrix ([rFwd , rBwd ]))([thetaFwdToBwd ])[0 ].as_matrix ()
94
+
95
+ p = spectacularAI .Pose .fromMatrix (t , pose )
53
96
yield ({
54
97
'time' : t ,
55
- 'position' : { c : getattr (pose .position , c ) for c in 'xyz' },
56
- 'orientation' : { c : getattr (pose .orientation , c ) for c in 'wxyz' }
98
+ 'position' : { c : getattr (p .position , c ) for c in 'xyz' },
99
+ 'orientation' : { c : getattr (p .orientation , c ) for c in 'wxyz' }
57
100
})
58
101
59
102
def smooth (args ):
@@ -114,9 +157,7 @@ def on_vio_output(vioOutput):
114
157
outToWorld = vioOutput .pose .asMatrix ()
115
158
outputToCam = np .linalg .inv (camToWorld ) @ outToWorld
116
159
117
- for p in vioOutput .poseTrail :
118
- currentToPastPose = np .linalg .inv (p .asMatrix ()) @ vioOutput .pose .asMatrix ()
119
- poseTrails .append ((p .time , vioOutput .pose .time , currentToPastPose ))
160
+ poseTrails .append ((vioOutput .pose .time , [(p .time , p .asMatrix ()) for p in vioOutput .poseTrail ]))
120
161
121
162
if visualizer is not None :
122
163
visualizer .onVioOutput (vioOutput .getCameraPose (0 ), status = vioOutput .status )
0 commit comments