@@ -71,6 +71,29 @@ def plotFrame(
71
71
72
72
return base64 (fig )
73
73
74
+
75
+ def plotDiscardedFrames (
76
+ start ,
77
+ end ,
78
+ data ):
79
+ import matplotlib .pyplot as plt
80
+ from matplotlib .ticker import ScalarFormatter
81
+
82
+ fig , ax = plt .subplots (figsize = (8 , 2 ))
83
+
84
+ ax .set_title ("Discarded frames" )
85
+ ax .vlines (data , ymin = 0 , ymax = 1 , colors = 'red' , lw = 1 )
86
+ ax .set_xlim (start , end )
87
+ ax .set_ylim (0 , 1 )
88
+ ax .set_xlabel ("Time (s)" )
89
+ ax .get_yaxis ().set_visible (False )
90
+ ax .xaxis .set_major_formatter (ScalarFormatter ())
91
+ ax .ticklabel_format (style = 'plain' ,axis = 'x' ,useOffset = False )
92
+ fig .tight_layout ()
93
+
94
+ return base64 (fig )
95
+
96
+
74
97
class DiagnosisLevel (Enum ):
75
98
OK = 0
76
99
WARNING = 1
@@ -210,6 +233,18 @@ def toPercent(value):
210
233
f"Found { invalidTimestamps } ({ toPercent (invalidTimestamps )} ) "
211
234
"timestamps that don't overlap with IMU" )
212
235
236
+
237
+ def analyzeDiscardedFrames (self , start_time , end_time , timestamps ):
238
+ if len (timestamps ) == 0 : return
239
+ self .images .append (plotDiscardedFrames (start_time , end_time , timestamps ))
240
+ self .__addIssue (DiagnosisLevel .WARNING ,
241
+ f"Found { len (timestamps )} discarded frames. Typically this happens when disk I/O "
242
+ f"is too slow and prevents recording frames leading them to be discarded. You can "
243
+ f"alleviate this issue with larger in-memory buffer when recording using FFMpeg. "
244
+ f"In <i>vio_config.yaml</i>: <i>ffmpegWriteBufferCapacityMegabytes: 50</i>"
245
+ )
246
+
247
+
213
248
def analyzeArrivalTimes (
214
249
self ,
215
250
timestamps ,
@@ -652,13 +687,18 @@ def diagnoseCamera(data, output):
652
687
sensor = data ["cameras" ]
653
688
output ["cameras" ] = []
654
689
690
+ start_time = None
691
+ end_time = None
655
692
for ind in sensor .keys ():
656
693
camera = sensor [ind ]
657
694
timestamps = np .array (camera ["t" ])
658
695
deltaTimes = np .array (camera ["td" ])
659
696
660
697
if len (timestamps ) == 0 : continue
661
698
699
+ if start_time == None or start_time > timestamps [0 ]: start_time = timestamps [0 ]
700
+ if end_time == None or end_time < timestamps [- 1 ]: end_time = timestamps [- 1 ]
701
+
662
702
status = Status ()
663
703
status .analyzeTimestamps (
664
704
timestamps ,
@@ -700,6 +740,17 @@ def diagnoseCamera(data, output):
700
740
# Camera is required
701
741
output ["passed" ] = False
702
742
743
+ if len (data ["discardedFrames" ]) > 0 :
744
+ status = Status ()
745
+ status .analyzeDiscardedFrames (start_time , end_time , data ["discardedFrames" ])
746
+ output ["discardedFrames" ] = {
747
+ "diagnosis" : status .diagnosis .toString (),
748
+ "issues" : status .serializeIssues (),
749
+ "count" : len (timestamps ),
750
+ "images" : status .images
751
+ }
752
+
753
+
703
754
def diagnoseAccelerometer (data , output ):
704
755
ACC_MIN_FREQUENCY_HZ = 50.0
705
756
ACC_MAX_FREQUENCY_HZ = 1e4
0 commit comments