Skip to content

Commit 33ebe1c

Browse files
committed
Improved smoothed trajectory
1 parent a59299a commit 33ebe1c

File tree

1 file changed

+64
-23
lines changed

1 file changed

+64
-23
lines changed

python/cli/smooth.py

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,77 @@ def define_subparser(subparsers):
2626
def compute_full_trajectory(keyFrames, poseTrails, outputToCam):
2727
import spectacularAI
2828
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))
2948

3049
trajectory = {}
3150
for kf in keyFrames.values():
3251
camPose = kf.frameSet.primaryFrame.cameraPose.pose
3352
pose = camPose.asMatrix() @ outputToCam
3453
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)
5396
yield({
5497
'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' }
57100
})
58101

59102
def smooth(args):
@@ -114,9 +157,7 @@ def on_vio_output(vioOutput):
114157
outToWorld = vioOutput.pose.asMatrix()
115158
outputToCam = np.linalg.inv(camToWorld) @ outToWorld
116159

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]))
120161

121162
if visualizer is not None:
122163
visualizer.onVioOutput(vioOutput.getCameraPose(0), status=vioOutput.status)

0 commit comments

Comments
 (0)