Skip to content

Commit bf8fd7a

Browse files
authored
Improve visualizer output queueing (#34)
1 parent ab85990 commit bf8fd7a

File tree

1 file changed

+63
-37
lines changed

1 file changed

+63
-37
lines changed

python/cli/visualization/visualizer.py

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import numpy as np
33
import time
44

5-
from threading import Lock
65
from enum import Enum
76
from OpenGL.GL import * # all prefixed with gl so OK to import *
87

@@ -244,8 +243,8 @@ def __init__(self, args=VisualizerArgs()):
244243
self.shouldQuit = False
245244
self.shouldPause = False
246245
self.displayInitialized = False
247-
self.outputQueue = []
248-
self.outputQueueMutex = Lock()
246+
self.vioOutputQueue = []
247+
self.mapperOutputQueue = []
249248
self.clock = pygame.time.Clock()
250249

251250
# Window
@@ -455,7 +454,8 @@ def onVioOutput(self, cameraPose, image=None, width=None, height=None, colorForm
455454
"image" : None,
456455
"width" : self.targetResolution[0],
457456
"height" : self.targetResolution[1],
458-
"colorFormat" : None
457+
"colorFormat" : None,
458+
"time" : time.time()
459459
}
460460
if image is not None:
461461
# Flip the image upside down for OpenGL.
@@ -464,9 +464,15 @@ def onVioOutput(self, cameraPose, image=None, width=None, height=None, colorForm
464464
output['width'] = width
465465
output['height'] = height
466466
output['colorFormat'] = colorFormat
467+
self.vioOutputQueue.append(output)
467468

468-
with self.outputQueueMutex:
469-
self.outputQueue.append(output)
469+
MAX_VIO_OUTPUT_QUEUE_SIZE = 25
470+
while len(self.vioOutputQueue) > MAX_VIO_OUTPUT_QUEUE_SIZE:
471+
if self.args.targetFps == 0:
472+
time.sleep(0.01) # Blocks replay, avoids dropping vio outputs
473+
else:
474+
self.vioOutputQueue.pop(0)
475+
print("Warning: Dropping vio output in visualizer (processing too slow!)")
470476

471477
# In live mode, future vio outputs are discarded
472478
# In replay mode, Replay API is blocked -> no more vio outputs
@@ -479,59 +485,79 @@ def onMappingOutput(self, mapperOutput):
479485

480486
output = {
481487
"type" : "slam",
482-
"mapperOutput" : mapperOutput
488+
"mapperOutput" : mapperOutput,
489+
"time" : time.time()
483490
}
491+
self.mapperOutputQueue.append(output)
484492

485-
with self.outputQueueMutex:
486-
self.outputQueue.append(output)
493+
MAX_MAPPER_OUTPUT_QUEUE_SIZE = 10
494+
if len(self.mapperOutputQueue) > MAX_MAPPER_OUTPUT_QUEUE_SIZE:
495+
self.mapperOutputQueue.pop(0)
496+
print("Warning: Dropping mapper output in visualizer (processing too slow!)")
487497

488498
def run(self):
489499
vioOutput = None
490500
prevVioOutput = None
491501
wasTracking = False
492502

503+
def getNextOutput():
504+
vioOutputTime = None if len(self.vioOutputQueue) == 0 else self.vioOutputQueue[0]["time"]
505+
mapperOutputTime = None if len(self.mapperOutputQueue) == 0 else self.mapperOutputQueue[0]["time"]
506+
if vioOutputTime is None:
507+
if mapperOutputTime is None: return None
508+
return self.mapperOutputQueue.pop(0)
509+
if mapperOutputTime is None:
510+
return self.vioOutputQueue.pop(0)
511+
return self.vioOutputQueue.pop(0) if vioOutputTime < mapperOutputTime else self.mapperOutputQueue.pop(0)
512+
513+
def processVioOutput(output):
514+
nonlocal vioOutput, prevVioOutput, wasTracking
515+
vioOutput = output
516+
if vioOutput['isTracking']:
517+
wasTracking = True
518+
cameraPose = vioOutput["cameraPose"]
519+
self.poseTrail.append(cameraPose.getPosition())
520+
else:
521+
vioOutput = None
522+
if wasTracking:
523+
self.__resetAfterLost()
524+
wasTracking = False
525+
526+
def processMapperOutput(output):
527+
nonlocal vioOutput, prevVioOutput, wasTracking
528+
529+
mapperOutput = output["mapperOutput"]
530+
if wasTracking: # Don't render if not tracking. Messes up this visualization easily
531+
self.map.onMappingOutput(mapperOutput)
532+
if mapperOutput.finalMap:
533+
if self.args.keepOpenAfterFinalMap:
534+
self.showCameraFrustum = False
535+
self.showCameraModel = False
536+
if self.args.targetFps == 0: self.args.targetFps = 30 # No vio outputs -> set 30fps mode instead
537+
if self.cameraSmooth: self.cameraSmooth.reset() # Stop camera moving automatically
538+
vioOutput = prevVioOutput
539+
else:
540+
self.shouldQuit = True
541+
493542
while not self.shouldQuit:
494543
self.__processUserInput()
495544

496545
# Process VIO & Mapping API outputs
497546
while True:
498547
if self.shouldPause: break
499548

500-
with self.outputQueueMutex:
501-
if len(self.outputQueue) > 0:
502-
output = self.outputQueue.pop(0)
503-
else:
504-
break
549+
output = getNextOutput()
550+
if output is None: break
505551

506552
if output["type"] == "vio":
507-
vioOutput = output
508-
if vioOutput['isTracking']:
509-
wasTracking = True
510-
cameraPose = vioOutput["cameraPose"]
511-
self.poseTrail.append(cameraPose.getPosition())
512-
else:
513-
vioOutput = None
514-
if wasTracking:
515-
self.__resetAfterLost()
516-
wasTracking = False
553+
processVioOutput(output)
517554

518555
# Render on all outputs if using target fps 0 (i.e. render on vio output mode)
519-
# unless they were dropped because visualization is running too slow.
520556
if self.args.targetFps == 0: break
521557

522558
elif output["type"] == "slam":
523-
mapperOutput = output["mapperOutput"]
524-
if wasTracking: # Don't render if not tracking. Messes up this visualization easily
525-
self.map.onMappingOutput(mapperOutput)
526-
if mapperOutput.finalMap:
527-
if self.args.keepOpenAfterFinalMap:
528-
self.showCameraFrustum = False
529-
self.showCameraModel = False
530-
if self.args.targetFps == 0: self.args.targetFps = 30 # No vio outputs -> set 30fps mode instead
531-
if self.cameraSmooth: self.cameraSmooth.reset() # Stop camera moving automatically
532-
vioOutput = prevVioOutput
533-
else:
534-
self.shouldQuit = True
559+
processMapperOutput(output)
560+
535561
else:
536562
print("Unknown output type: {}".format(output["type"]))
537563

0 commit comments

Comments
 (0)