%% Create Ground Truth from Multiple Signals
% Create ground truth data for a video signal and a lidar point cloud
% sequence signal that captures the same driving scene. Specify the signal
% sources, label definitions, and ROI and scene label data.

% Copyright 2019 The MathWorks, Inc.
%%
% Create the video data source from an MP4 file.

sourceName = '01_city_c2s_fcw_10s.mp4';
sourceParams = [];
vidSource = vision.labeler.loading.VideoSource;
vidSource.loadSource(sourceName,sourceParams);

%%
% Create the point cloud sequence source from a folder of point cloud data
% (PCD) files.

pcSeqFolder = fullfile(toolboxdir('driving'),'drivingdata','lidarSequence');
addpath(pcSeqFolder)
load timestamps.mat
rmpath(pcSeqFolder)

lidarSourceData = load(fullfile(pcSeqFolder,'timestamps.mat'));

sourceName = pcSeqFolder;
sourceParams = struct;
sourceParams.Timestamps = timestamps;

pcseqSource = vision.labeler.loading.PointCloudSequenceSource;
pcseqSource.loadSource(sourceName,sourceParams);

%%
% Combine the signal sources into an array.

dataSource = [vidSource pcseqSource]

%%
% Create a table of label definitions for the ground truth data by using a
% |labelDefinitionCreatorMultisignal| object.
%
% * The |Car| label definition appears twice. Even though |Car| is defined
% as a rectangle, you can draw rectangles only for image signals, such as
% videos. The |labelDefinitionCreatorMultisignal| object creates an
% additional row for lidar point cloud signals. In these signal types, you
% can draw |Car| labels as cuboids only.
% * The label definitions have no descriptions and no assigned colors, so
% the |Description| and |LabelColor| columns are empty.
% * The label definitions have no assigned groups, so for all label
% definitions, the corresponding cell in the |Group| column is set to
% |'None'|.
% * |Road| is a pixel label definition, so the table includes a
% |PixelLabelID| column.
% * No label definitions have sublabels or attributes, so the table
% does not include a |Hierarchy| column for storing such information.
%

ldc = labelDefinitionCreatorMultisignal;
addLabel(ldc,'Car','Rectangle');
addLabel(ldc,'Truck','ProjectedCuboid');
addLabel(ldc,'Lane','Line');
addLabel(ldc,'Road','PixelLabel');
addLabel(ldc,'Sunny','Scene');
labelDefs = create(ldc)

%%
% Create ROI label data for the first frame of the video.

numVideoFrames = numel(vidSource.Timestamp{1});
carData = cell(numVideoFrames,1);
laneData = cell(numVideoFrames,1);
truckData = cell(numVideoFrames,1);
carData{1} = [304 212 37 33];
laneData{1} = [70 458; 311 261];
truckData{1} = [309,215,33,24,330,211,33,24];
videoData = timetable(vidSource.Timestamp{1},carData,laneData, ...
                      'VariableNames',{'Car','Lane'});

%%
% Create ROI label data for the first point cloud in the sequence.

numPCFrames = numel(pcseqSource.Timestamp{1});
carData = cell(numPCFrames, 1);
carData{1} = [27.35 18.32 -0.11 4.25 4.75 3.45 0 0 0];
lidarData = timetable(pcseqSource.Timestamp{1},carData,'VariableNames',{'Car'});

%%
% Combine the ROI label data for both sources.

signalNames = [dataSource.SignalName];
roiData = vision.labeler.labeldata.ROILabelData(signalNames,{videoData,lidarData})

%%
% Create scene label data for the first 10 seconds of the driving scene.

sunnyData = seconds([0 10]);
labelNames = ["Sunny"];
sceneData = vision.labeler.labeldata.SceneLabelData(labelNames,{sunnyData})

%%
% Create a ground truth object from the signal sources, label definitions,
% and ROI and scene label data. You can import this object into the *Ground
% Truth Labeler* app for manual labeling or to run a labeling automation
% algorithm on it. You can also extract training data from this object for
% deep learning models by using the |gatherLabelData| function.

gTruth = groundTruthMultisignal(dataSource,labelDefs,roiData,sceneData)