@@ -255,6 +255,59 @@ def test_osi_trace_su(self):
255255
256256 self .assertTrue (os .path .exists (path_output ))
257257
258+ def test_osi_trace_sv_and_sd (self ):
259+ with tempfile .TemporaryDirectory () as tmpdirname :
260+ path_output1 = os .path .join (tmpdirname , "output_svsd1.txth" )
261+ path_output2 = os .path .join (tmpdirname , "output_svsd2.txth" )
262+ path_output3 = os .path .join (tmpdirname , "output_svsd3.txth" )
263+ path_input = os .path .join (tmpdirname , "input_svsd.mcap" )
264+ create_sample_svsd (path_input )
265+
266+ # Select channel via type name
267+ trace = OSITrace (path_input , "SensorView" )
268+ with open (path_output1 , "wt" ) as f :
269+ count = 0
270+ for message in trace :
271+ self .assertIsInstance (message , SensorView )
272+ count += 1
273+ f .write (str (message ))
274+ self .assertEqual (count , 10 )
275+ trace .close ()
276+
277+ # Select channel via type name
278+ trace = OSITrace (path_input , "SensorData" )
279+ with open (path_output2 , "wt" ) as f :
280+ count = 0
281+ for message in trace :
282+ self .assertIsInstance (message , SensorData )
283+ count += 1
284+ f .write (str (message ))
285+ self .assertEqual (count , 10 )
286+ trace .close ()
287+
288+ # Select channel via channel name and type name
289+ trace = OSITrace (path_input , "SensorData" , False , "SensorDataTopic" )
290+ with open (path_output3 , "wt" ) as f :
291+ count = 0
292+ for message in trace :
293+ self .assertIsInstance (message , SensorData )
294+ count += 1
295+ f .write (str (message ))
296+ self .assertEqual (count , 10 )
297+ trace .close ()
298+
299+ # Mismatched channel name and type name
300+ with self .assertRaises (ValueError ):
301+ trace = OSITrace (path_input , "SensorData" , False , "SensorViewTopic" )
302+
303+ # Unknown channel name
304+ with self .assertRaises (ValueError ):
305+ trace = OSITrace (path_input , "SensorData" , False , "UnknownTopic" )
306+
307+ self .assertTrue (os .path .exists (path_output1 ))
308+ self .assertTrue (os .path .exists (path_output2 ))
309+ self .assertTrue (os .path .exists (path_output3 ))
310+
258311
259312def build_file_descriptor_set (message_class ) -> FileDescriptorSet :
260313 file_descriptor_set = FileDescriptorSet ()
@@ -766,3 +819,107 @@ def create_sample_su(path):
766819 )
767820
768821 mcap_writer .finish ()
822+
823+
824+ def create_sample_svsd (path ):
825+ mcap_writer = prepare_mcap_writer (path )
826+ channel_sv = add_channel (mcap_writer , SensorView , "SensorViewTopic" )
827+ channel_sd = add_channel (mcap_writer , SensorData , "SensorDataTopic" )
828+
829+ sensorview = SensorView ()
830+
831+ sensorview .version .version_major = 3
832+ sensorview .version .version_minor = 0
833+ sensorview .version .version_patch = 0
834+
835+ sensorview .timestamp .seconds = 0
836+ sensorview .timestamp .nanos = 0
837+
838+ sensorview .sensor_id .value = 42
839+
840+ sensorview .host_vehicle_id .value = 114
841+
842+ sv_ground_truth = sensorview .global_ground_truth
843+ sv_ground_truth .version .version_major = 3
844+ sv_ground_truth .version .version_minor = 0
845+ sv_ground_truth .version .version_patch = 0
846+
847+ sv_ground_truth .timestamp .seconds = 0
848+ sv_ground_truth .timestamp .nanos = 0
849+
850+ sv_ground_truth .host_vehicle_id .value = 114
851+
852+ moving_object = sv_ground_truth .moving_object .add ()
853+ moving_object .id .value = 114
854+
855+ sensordata = SensorData ()
856+
857+ sensordata .version .version_major = 3
858+ sensordata .version .version_minor = 0
859+ sensordata .version .version_patch = 0
860+
861+ sensordata .timestamp .seconds = 0
862+ sensordata .timestamp .nanos = 0
863+
864+ sensordata .sensor_id .value = 42
865+
866+ sdmoving_object = sensordata .moving_object .add ()
867+ sdmoving_object .header .tracking_id .value = 1
868+ gt_id = sdmoving_object .header .ground_truth_id .add ()
869+ gt_id .value = 114
870+
871+ # Generate 10 OSI messages for 9 seconds
872+ for i in range (10 ):
873+ # Increment the time
874+ sensorview .timestamp .seconds += 1
875+ sensorview .timestamp .nanos += 100000
876+
877+ sv_ground_truth .timestamp .seconds += 1
878+ sv_ground_truth .timestamp .nanos += 100000
879+
880+ sensordata .timestamp .seconds += 1
881+ sensordata .timestamp .nanos += 100000
882+
883+ # SensorView moving object
884+ moving_object .vehicle_classification .type = 2
885+
886+ moving_object .base .dimension .length = 5
887+ moving_object .base .dimension .width = 2
888+ moving_object .base .dimension .height = 1
889+
890+ moving_object .base .position .x = 0.0 + i
891+ moving_object .base .position .y = 0.0
892+ moving_object .base .position .z = 0.0
893+
894+ moving_object .base .orientation .roll = 0.0
895+ moving_object .base .orientation .pitch = 0.0
896+ moving_object .base .orientation .yaw = 0.0
897+
898+ # SensorData moving object
899+ sdmoving_object .base .dimension .length = 5
900+ sdmoving_object .base .dimension .width = 2
901+ sdmoving_object .base .dimension .height = 1
902+
903+ sdmoving_object .base .position .x = 0.0 + i
904+ sdmoving_object .base .position .y = 0.0
905+ sdmoving_object .base .position .z = 0.0
906+
907+ sdmoving_object .base .orientation .roll = 0.0
908+ sdmoving_object .base .orientation .pitch = 0.0
909+ sdmoving_object .base .orientation .yaw = 0.0
910+
911+ time = sensorview .timestamp .seconds + sensorview .timestamp .nanos / 1e9
912+ mcap_writer .add_message (
913+ channel_id = channel_sv ,
914+ log_time = int (time * 1000000000 ),
915+ data = sensorview .SerializeToString (),
916+ publish_time = int (time * 1000000000 ),
917+ )
918+ mcap_writer .add_message (
919+ channel_id = channel_sd ,
920+ log_time = int (time * 1000000000 ),
921+ data = sensordata .SerializeToString (),
922+ publish_time = int (time * 1000000000 ),
923+ )
924+
925+ mcap_writer .finish ()
0 commit comments