Get Started with Writing Timetable Data to MDF-Files
This example shows how to write timetable data into an MDF-file. The MAT-file used in this example MDFTimetables.mat
contains two timetables.
Timetable
TT1
has variables of numeric data types including uint8, uint16, uint32, uint64, int8, int16, int32, int64, single and double.Timetable
TT2
has variables of string and byte array data types including both fixed-length and variable-length data.
Introduction
A simplified model to represent the structure of an ASAM MDF-file is a three-level hierarchy composed of the file, the channel group and the channel. A file consists of a number of channel groups; a channel group consists of a number of channels.
There are two important elements to the content of an MDF-file: the data and the metadata.
Signal or channel data written into an MDF-file is generally either acquired or calculated. Typical signals for an automotive application are sensor data, ECU-internal variables/states, bus traffic in a vehicle network, or internally calculated values. In most applications, data in all channels of a channel group is synchronized by time, but it is also possible for them to be synchronized by angle, distance, or index. In rare cases, there could be no synchronization domain or multiple synchronization domains. Currently, the MDF functions in MATLAB only support one synchronization domain by time.
Metadata are additional descriptive information about the measurement environment. They are applicable to the three hierarchical levels: the file, the channel group and the channel. Each level has a set of metadata fields defined by the ASAM MDF standard.
In this example, data in TT1
and TT2
are written into channel group 1 and 2 respectively of a new MDF-file. You should use this workflow if there is no need to custom set metadata at any of the three hierarchical levels.
If you need to custom set metadata when writing to an MDF-file, use the advanced workflow in example Custom Set Metadata When Writing Timetable Data to MDF-Files.
Load Timetables into Workspace
Load the timetable variables, TT1
and TT2
, from MDFTimetables.mat
into the workspace.
load("MDFTimetables.mat")
Write Timetable Data Directly to a New MDF-File
Use the mdfWrite
function with the target MDF-file name and the timetable variable TT1
specified as input arguments. Because the target file TimetableBasic.mf4
does not exist yet, the function creates the file automatically and displays a warning to inform the path of the newly created file. Data in TT1
is written to the first available channel group index of the file, which is channel group 1 since TimetableBasic.mf4
is a newly created file.
mdfWrite("TimetableBasic.mf4", TT1)
Warning: Specified target file did not exist. Created file: /tmp/Bdoc22a_1891349_156950/tp07074cff/vnt-ex65847646/TimetableBasic.mf4
Call mdfWrite
again to write TT2
to the next available channel group index 2.
mdfWrite("TimetableBasic.mf4", TT2)
Examine the Default File Metadata
Using this workflow, default values for file metadata were applied by mdfWrite
while creating the MDF-file. To examine the file metadata of TimetableBasic.mf4
, call mdfInfo
with the MDF-file name specified.
info = mdfInfo("TimetableBasic.mf4")
info = struct with fields:
Name: 'TimetableBasic.mf4'
Path: '/tmp/Bdoc22a_1891349_156950/tp07074cff/vnt-ex65847646/TimetableBasic.mf4'
Author: ''
Department: ''
Project: ''
Subject: ''
Comment: ''
Version: '4.20'
ProgramIdentifier: 'MATLAB'
InitialTimestamp: 2022-02-26 17:55:45.000000000
Creator: [1x1 struct]
Attachment: [0x1 struct]
Query the Creator
field of the file information structure info
to examine the metadata about creator of the file.
info.Creator
ans = struct with fields:
VendorName: 'The MathWorks, Inc.'
ToolName: 'MATLAB'
ToolVersion: '9.12.0.1884302 (R2022a)'
UserName: ''
Comment: ''
Open the MDF-File
Open access to the created MDF-file using the mdf
function. You can use the returned object to examine the metadata for channel groups and channels, and to read channel data into MATLAB for verification.
mdfObj = mdf("TimetableBasic.mf4");
Examine the Channel Group Metadata
Examine the metadata for channel group 1. Metadata fields AcquisitionName
, Comment
and SourceInfo
were assigned default values. Other fields such as NumSamples
, DataSize
and Sorted
are dependent on the data.
mdfObj.ChannelGroup(1)
ans = struct with fields:
AcquisitionName: ''
Comment: ''
NumSamples: 100
DataSize: 5000
Sorted: 1
SourceInfo: [1x1 struct]
Channel: [11x1 struct]
mdfObj.ChannelGroup(1).SourceInfo
ans = struct with fields:
Name: ''
Path: ''
Comment: ''
SourceType: Unspecified
BusType: Unspecified
BusChannelNumber: 0
Simulated: 0
Similarly, examine the metadata for channel group 2.
mdfObj.ChannelGroup(2)
ans = struct with fields:
AcquisitionName: ''
Comment: ''
NumSamples: 10
DataSize: 340
Sorted: 1
SourceInfo: [1x1 struct]
Channel: [5x1 struct]
mdfObj.ChannelGroup(2).SourceInfo
ans = struct with fields:
Name: ''
Path: ''
Comment: ''
SourceType: Unspecified
BusType: Unspecified
BusChannelNumber: 0
Simulated: 0
Examine the Channel Metadata
To examine the metadata for channels in channel group 1, convert the channel metadata structure into a table for easier visualization. Row times of the timetable were written into a time channel, while variables of the timetable were written into respective data channels.
Metadata fields Type
, DataType
and NumBits
were derived from the data stored in the corresponding timetable variable by mdfWrite
. For instance, variable named uint8_data
in TT1
contains 8-bit unsigned integers, so Type
of the channel is asam.mdf.ChannelType.FixedLength
(0), DataType
is asam.mdf.ChannelDataType.IntegerUnsignedLittleEndian
(0), and NumBits
is 8.
Other metadata fields were assigned default values by mdfWrite
. In the case of the time channel, Unit
is known to be second, so it was assigned value 's'
.
struct2table(mdfObj.ChannelGroup(1).Channel(:))
ans=11×13 table
Name DisplayName ExtendedNamePrefix Description Comment Unit Type DataType NumBits ComponentType CompositionType ConversionType SourceInfo
_______________ ___________ __________________ ___________ __________ __________ ___________ ___________________________ _______ _____________ _______________ ______________ __________
{'uint8_data' } {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} FixedLength IntegerUnsignedLittleEndian 8 None None None 1x1 struct
{'uint16_data'} {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} FixedLength IntegerUnsignedLittleEndian 16 None None None 1x1 struct
{'uint32_data'} {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} FixedLength IntegerUnsignedLittleEndian 32 None None None 1x1 struct
{'uint64_data'} {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} FixedLength IntegerUnsignedLittleEndian 64 None None None 1x1 struct
{'int8_data' } {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} FixedLength IntegerSignedLittleEndian 8 None None None 1x1 struct
{'int16_data' } {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} FixedLength IntegerSignedLittleEndian 16 None None None 1x1 struct
{'int32_data' } {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} FixedLength IntegerSignedLittleEndian 32 None None None 1x1 struct
{'int64_data' } {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} FixedLength IntegerSignedLittleEndian 64 None None None 1x1 struct
{'single_data'} {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} FixedLength RealLittleEndian 32 None None None 1x1 struct
{'double_data'} {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} FixedLength RealLittleEndian 64 None None None 1x1 struct
{'time' } {0x0 char} {0x0 char} {0x0 char} {0x0 char} {'s' } Master RealLittleEndian 64 None None None 1x1 struct
Similarly, examine the metadata for channels in channel group 2. Metadata fields Type
, DataType
and NumBits
were also derived from the data stored in the corresponding timetable variable by mdfWrite
.
Data samples in variables
fixed_length_string_data
andfixed_length_byte_array_data
ofTT2
are fixed-length, soType
of these two channels areasam.mdf.ChannelType.FixedLength
(0). Variablesvariable_length_string_data
andvariable_length_byte_array_data
contain data samples with variable lengths, soType
of these two channels areasam.mdf.ChannelType.VariableLength
(1).For the two variables that have string data,
fixed_length_string_data
andvariable_length_string_data
,DataType
isasam.mdf.ChannelDataType.StringASCII
(6). For the two variables that have byte array data,fixed_length_byte_array_data
andvariable_length_byte_array_data
,DataType
isasam.mdf.ChannelDataType.ByteArray
(10).NumBits
for a fixed-length channel is derived from the data. For a variable-length channel,NumBits
has a default value of 64.
struct2table(mdfObj.ChannelGroup(2).Channel(:))
ans=5×13 table
Name DisplayName ExtendedNamePrefix Description Comment Unit Type DataType NumBits ComponentType CompositionType ConversionType SourceInfo
___________________________________ ___________ __________________ ___________ __________ __________ ______________ ________________ _______ _____________ _______________ ______________ __________
{'fixed_length_string_data' } {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} FixedLength StringASCII 40 None None None 1x1 struct
{'fixed_length_byte_array_data' } {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} FixedLength ByteArray 40 None None None 1x1 struct
{'variable_length_string_data' } {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} VariableLength StringASCII 64 None None None 1x1 struct
{'variable_length_byte_array_data'} {0x0 char} {0x0 char} {0x0 char} {0x0 char} {0x0 char} VariableLength ByteArray 64 None None None 1x1 struct
{'time' } {0x0 char} {0x0 char} {0x0 char} {0x0 char} {'s' } Master RealLittleEndian 64 None None None 1x1 struct
Examine the Data
To verify that data was successfully written to file, read from each channel group and examine the result.
chanGrp1 = read(mdfObj, 1)
chanGrp1=100×11 timetable
Time uint8_data uint16_data uint32_data uint64_data int8_data int16_data int32_data int64_data single_data double_data time
_______ __________ ___________ ___________ ___________ _________ __________ __________ __________ ___________ ___________ ____
0 sec 0 200 600 1400 -99 -198 -396 -794 -9.8 -19.6 0
0.1 sec 2 204 608 1416 -97 -194 -388 -778 -9.6 -19.2 0.1
0.2 sec 4 208 616 1432 -95 -190 -380 -762 -9.4 -18.8 0.2
0.3 sec 6 212 624 1448 -93 -186 -372 -746 -9.2 -18.4 0.3
0.4 sec 8 216 632 1464 -91 -182 -364 -730 -9 -18 0.4
0.5 sec 10 220 640 1480 -89 -178 -356 -714 -8.8 -17.6 0.5
0.6 sec 12 224 648 1496 -87 -174 -348 -698 -8.6 -17.2 0.6
0.7 sec 14 228 656 1512 -85 -170 -340 -682 -8.4 -16.8 0.7
0.8 sec 16 232 664 1528 -83 -166 -332 -666 -8.2 -16.4 0.8
0.9 sec 18 236 672 1544 -81 -162 -324 -650 -8 -16 0.9
1 sec 20 240 680 1560 -79 -158 -316 -634 -7.8 -15.6 1
1.1 sec 22 244 688 1576 -77 -154 -308 -618 -7.6 -15.2 1.1
1.2 sec 24 248 696 1592 -75 -150 -300 -602 -7.4 -14.8 1.2
1.3 sec 26 252 704 1608 -73 -146 -292 -586 -7.2 -14.4 1.3
1.4 sec 28 256 712 1624 -71 -142 -284 -570 -7 -14 1.4
1.5 sec 30 260 720 1640 -69 -138 -276 -554 -6.8 -13.6 1.5
⋮
chanGrp2 = read(mdfObj, 2)
chanGrp2=10×5 timetable
Time fixed_length_string_data fixed_length_byte_array_data variable_length_string_data variable_length_byte_array_data time
_____ ________________________ ____________________________ ___________________________ _______________________________ ____
0 sec {'abcd'} {[255 255 255 255 255]} {'zero' } {[ 255 255]} 0
1 sec {'efgh'} {[ 18 35 52 69 86]} {'one' } {[ 18 35 52 69 86]} 1
2 sec {'ijkl'} {[ 0 1 2 3 4]} {'two' } {[ 0 1 2 3 4 5 6 7]} 2
3 sec {'mnop'} {[ 4 3 2 1 0]} {'three'} {[ 4 3 2 1 0]} 3
4 sec {'qrst'} {[255 254 253 252 251]} {'four' } {[ 253 252 251]} 4
5 sec {'uvwx'} {[250 249 248 247 246]} {'five' } {[250 249 248 247 246]} 5
6 sec {'yzAB'} {[245 244 243 242 241]} {'six' } {[245 244 243 242 241]} 6
7 sec {'CDEF'} {[240 239 238 237 236]} {'seven'} {[ 240 238 236]} 7
8 sec {'GHIJ'} {[235 234 233 232 231]} {'eight'} {[ 235 233 231]} 8
9 sec {'KLMN'} {[255 255 255 255 255]} {'nine' } {[255 255 255 255 255]} 9
Close MDF-File
Close access to the MDF-file by clearing its variable from the workspace.
clear mdfObj