覆盖 MDF 文件中的通道组数据
此示例说明如何处理在 MDF 文件的通道组中记录的数据,并将更新后的数据写回同一通道组。此示例 VehicleData.mf4
中使用的 MDF 文件包含从两个通道组中的两个仿真记录的数据,但该示例仅处理通道组 1 中的数据。
您首先需要将通道组 1 中的数据读入一个时间表,然后对该数据副本执行校正和约简,最后用更新后的数据覆盖同一通道组。
查看文件和通道组详细信息
通过指定文件名,使用 mdfInfo
查看 MDF 文件的元数据。
mdfInfo("VehicleData.mf4")
ans = MDFInfo with properties: File Details Name: "VehicleData.mf4" Path: "/tmp/Bdoc24a_2511836_3070643/tp8879c7f7/vnt-ex75859393/VehicleData.mf4" Author: "" Department: "" Project: "" Subject: "" Comment: "Example file demonstrating workflows of writing to MDF files." Version: "4.10" InitialTimestamp: 2022-01-20 01:22:34.000000000 Creator Details ProgramIdentifier: "MATLAB" CreatorVendorName: "The MathWorks, Inc." CreatorToolName: "MATLAB" CreatorToolVersion: "9.12.0.1846952 (R2022a) Prerelease Update 1" CreatorUserName: "" CreatorComment: "" File Contents Attachment: [1x7 table] ChannelGroupCount: 2
使用 mdfChannelGroupInfo
检查有关两个通道组的详细信息。
mdfChannelGroupInfo("VehicleData.mf4")
ans=2×13 table
GroupNumber AcquisitionName Comment NumSamples DataSize Sorted SourceName SourcePath SourceComment SourceType SourceBusType SourceBusChannelNumber SourceSimulated
___________ _______________ ___________________________________________________________________________ __________ ________ ______ ___________ ___________ _____________ ___________ _____________ ______________________ _______________
1 <undefined> Simulation of an automatic transmission controller during passing maneuver. 751 43558 true <undefined> <undefined> <undefined> Unspecified Unspecified 0 false
2 <undefined> Simulation of engine gas dynamics. 92033 2208792 true <undefined> <undefined> <undefined> Unspecified Unspecified 0 false
读取包含元数据的通道组数据
使用可选参量 IncludeMetadata
设置为 true
的 mdfRead
函数从通道组 1 读取数据。输出时间表 chanGrp1TT
是通道组 1 中所有通道的数据的副本。
chanGrp1Data = mdfRead("VehicleData.mf4", GroupNumber=1, IncludeMetadata=true)
chanGrp1Data = 1x1 cell array
{751x8 timetable}
chanGrp1TT = chanGrp1Data{1}
chanGrp1TT=751×8 timetable
time EngineRPM Brake Throttle Gear ImpellerTorque OutputTorque TransmissionRPM VehicleSpeed
________ _________ _____ ________ ____ ______________ ____________ _______________ ____________
0 sec 1000 0 60 1 52.919 282.65 0 0
0.04 sec 1383.3 0 59.946 1 101.4 532.63 13.593 0
0.08 sec 1685.4 0 59.893 1 150.76 776.41 35.847 0
0.12 sec 1907.2 0 59.839 1 193.42 973.15 65.768 0
0.16 sec 2062 0 59.785 1 227.02 1117.6 101.53 0
0.2 sec 2161.2 0 59.732 1 251.11 1212.8 141.45 0
0.24 sec 2221.4 0 59.678 1 267.24 1264.3 183.86 0
0.28 sec 2257.2 0 59.624 1 276.35 1271.2 227.25 0
0.32 sec 2278.7 0 59.57 1 281.99 1259.5 270.52 0
0.36 sec 2292.4 0 59.517 1 283.39 1229 313.08 0
0.4 sec 2305.1 0 59.463 1 283.29 1193.4 354.43 0
0.44 sec 2317.4 0 59.409 1 282.91 1156.6 394.58 0
0.48 sec 2330.5 0 59.356 1 281.84 1112.8 433.27 0
0.52 sec 2344.5 0 59.302 1 281.19 1073.1 470.53 0
0.56 sec 2359.1 0 59.248 1 279.77 1032.9 506.43 0
0.6 sec 2376.4 0 59.195 1 277.89 993.97 540.92 0
⋮
由于在 mdfRead
函数调用期间 IncludeMetadata
设置为 true
,因此输出时间表还包含通道组 1 和此组中所有通道的元数据。一个通道组的元数据存储为整个表的时间表自定义属性,属性名称以“ChannelGroup”为前缀。各个通道的元数据存储为各变量的时间表自定义属性,属性名称以“Channel”为前缀。
查看通道组 1 和此组中所有通道的元数据。
chanGrp1TT.Properties.CustomProperties
ans = CustomProperties with properties: ChannelGroupAcquisitionName: "" ChannelGroupComment: "Simulation of an automatic transmission controller during passing maneuver." ChannelGroupSourceName: "" ChannelGroupSourcePath: "" ChannelGroupSourceComment: "" ChannelGroupSourceType: Unspecified ChannelGroupSourceBusType: Unspecified ChannelGroupSourceBusChannelNumber: 0 ChannelDisplayName: ["" "" "" "" "" "" "" ""] ChannelComment: ["" "" "" "" "" "" "" ""] ChannelUnit: ["rpm" "ft*lbf" "%" "" "ft*lbf" "ft*lbf" "rpm" "mph"] ChannelType: [FixedLength FixedLength FixedLength FixedLength FixedLength FixedLength FixedLength FixedLength] ChannelDataType: [RealLittleEndian IntegerUnsignedLittleEndian RealLittleEndian IntegerUnsignedLittleEndian RealLittleEndian RealLittleEndian RealLittleEndian RealLittleEndian] ChannelNumBits: [64 8 64 8 64 64 64 64] ChannelComponentType: [None None None None None None None None] ChannelCompositionType: [None None None None None None None None] ChannelSourceName: ["" "" "" "" "" "" "" ""] ChannelSourcePath: ["" "" "" "" "" "" "" ""] ChannelSourceComment: ["" "" "" "" "" "" "" ""] ChannelSourceType: [Unspecified Unspecified Unspecified Unspecified Unspecified Unspecified Unspecified Unspecified] ChannelSourceBusType: [Unspecified Unspecified Unspecified Unspecified Unspecified Unspecified Unspecified Unspecified] ChannelSourceBusChannelNumber: [0 0 0 0 0 0 0 0] ChannelReadOption: [All All All All All All All All]
请注意,当调用 mdfRead
函数时,默认情况下 IncludeMetadata
设置为 false
。因此,如果读取通道组数据的最终目标是覆盖从中读取数据的同一通道组,则 IncludeMetadata
必须设置为 true
。
校正数据副本中的选定采样
对于此特定应用,只有 4 个挡位,因此 Gear
的有效值应为 [1,4]
范围内的一个整数。然而,在每次换挡时,Gear
的值都会因可能的错误而被重置为零。
使用 stackedplot
创建一个堆叠图,以查看 Gear
中的值突然下降到零与 ImpellerTorque
和 OutputTorque
中的值突然变化是如何同步发生的。
stackedplot(chanGrp1TT, ["ImpellerTorque", "OutputTorque", "Gear"])
查找 Gear
的值等于零的行索引。
zeroIdx = find(chanGrp1TT.Gear == 0)
zeroIdx = 0x1 empty double column vector
在找到的索引处校正采样,以获取紧跟在零后面的值。
chanGrp1TT.Gear(zeroIdx) = chanGrp1TT.Gear(zeroIdx + 1)
chanGrp1TT=751×8 timetable
time EngineRPM Brake Throttle Gear ImpellerTorque OutputTorque TransmissionRPM VehicleSpeed
________ _________ _____ ________ ____ ______________ ____________ _______________ ____________
0 sec 1000 0 60 1 52.919 282.65 0 0
0.04 sec 1383.3 0 59.946 1 101.4 532.63 13.593 0
0.08 sec 1685.4 0 59.893 1 150.76 776.41 35.847 0
0.12 sec 1907.2 0 59.839 1 193.42 973.15 65.768 0
0.16 sec 2062 0 59.785 1 227.02 1117.6 101.53 0
0.2 sec 2161.2 0 59.732 1 251.11 1212.8 141.45 0
0.24 sec 2221.4 0 59.678 1 267.24 1264.3 183.86 0
0.28 sec 2257.2 0 59.624 1 276.35 1271.2 227.25 0
0.32 sec 2278.7 0 59.57 1 281.99 1259.5 270.52 0
0.36 sec 2292.4 0 59.517 1 283.39 1229 313.08 0
0.4 sec 2305.1 0 59.463 1 283.29 1193.4 354.43 0
0.44 sec 2317.4 0 59.409 1 282.91 1156.6 394.58 0
0.48 sec 2330.5 0 59.356 1 281.84 1112.8 433.27 0
0.52 sec 2344.5 0 59.302 1 281.19 1073.1 470.53 0
0.56 sec 2359.1 0 59.248 1 279.77 1032.9 506.43 0
0.6 sec 2376.4 0 59.195 1 277.89 993.97 540.92 0
⋮
从数据副本中删除通道
对于此特定应用,假设分析时不再需要 Brake
和 VehicleSpeed
。使用 removevars
从时间表中删除这两个变量。
chanGrp1TT = removevars(chanGrp1TT, ["Brake", "VehicleSpeed"])
chanGrp1TT=751×6 timetable
time EngineRPM Throttle Gear ImpellerTorque OutputTorque TransmissionRPM
________ _________ ________ ____ ______________ ____________ _______________
0 sec 1000 60 1 52.919 282.65 0
0.04 sec 1383.3 59.946 1 101.4 532.63 13.593
0.08 sec 1685.4 59.893 1 150.76 776.41 35.847
0.12 sec 1907.2 59.839 1 193.42 973.15 65.768
0.16 sec 2062 59.785 1 227.02 1117.6 101.53
0.2 sec 2161.2 59.732 1 251.11 1212.8 141.45
0.24 sec 2221.4 59.678 1 267.24 1264.3 183.86
0.28 sec 2257.2 59.624 1 276.35 1271.2 227.25
0.32 sec 2278.7 59.57 1 281.99 1259.5 270.52
0.36 sec 2292.4 59.517 1 283.39 1229 313.08
0.4 sec 2305.1 59.463 1 283.29 1193.4 354.43
0.44 sec 2317.4 59.409 1 282.91 1156.6 394.58
0.48 sec 2330.5 59.356 1 281.84 1112.8 433.27
0.52 sec 2344.5 59.302 1 281.19 1073.1 470.53
0.56 sec 2359.1 59.248 1 279.77 1032.9 506.43
0.6 sec 2376.4 59.195 1 277.89 993.97 540.92
⋮
将更新后的数据写回同一通道组
将更新后的数据写入 VehicleData.mf4
的通道组 1,这需要 MDF 文件的修改权限。检查您是否拥有 MDF 文件的写入访问权限。如果没有,请使 MDF 文件可写。
[~, values] = fileattrib("VehicleData.mf4"); if ~values.UserWrite fileattrib("VehicleData.mf4", "+w") end
调用函数 mdfWrite
,将可选参量 GroupNumber
设置为 1,用 chanGrp1TT
中更新后的数据覆盖通道组 1。
mdfWrite("VehicleData.mf4", chanGrp1TT, GroupNumber=1)
Warning: Channel "Brake" removed while overwriting an existing channel group. Data of the corresponding channel will be erased but the channel will still exist.
Warning: Channel "VehicleSpeed" removed while overwriting an existing channel group. Data of the corresponding channel will be erased but the channel will still exist.
在前一步骤中,从时间表 chanGrp1TT
中删除了 Brake
和 VehicleSpeed
这两个变量。但是,由于 MDF 是二进制文件格式,更改通道组结构体会导致文件损坏。因此,无法真正从现有通道组中删除通道。删除的通道的数据被擦除,但这些通道仍存在于通道组中。
检查数据
要验证数据是否已成功写入文件,请使用 mdfRead
只读取通道组 1 中不带元数据的数据。检查变量 Gear
中更新后的值。另请注意,对于已删除的变量 Brake
和 VehicleSpeed
,值已擦除并重置为零。
chanGrp1DataNew = mdfRead("VehicleData.mf4", GroupNumber=1)
chanGrp1DataNew = 1x1 cell array
{751x8 timetable}
chanGrp1TTNew = chanGrp1DataNew{1}
chanGrp1TTNew=751×8 timetable
time EngineRPM Brake Throttle Gear ImpellerTorque OutputTorque TransmissionRPM VehicleSpeed
________ _________ _____ ________ ____ ______________ ____________ _______________ ____________
0 sec 1000 0 60 1 52.919 282.65 0 0
0.04 sec 1383.3 0 59.946 1 101.4 532.63 13.593 0
0.08 sec 1685.4 0 59.893 1 150.76 776.41 35.847 0
0.12 sec 1907.2 0 59.839 1 193.42 973.15 65.768 0
0.16 sec 2062 0 59.785 1 227.02 1117.6 101.53 0
0.2 sec 2161.2 0 59.732 1 251.11 1212.8 141.45 0
0.24 sec 2221.4 0 59.678 1 267.24 1264.3 183.86 0
0.28 sec 2257.2 0 59.624 1 276.35 1271.2 227.25 0
0.32 sec 2278.7 0 59.57 1 281.99 1259.5 270.52 0
0.36 sec 2292.4 0 59.517 1 283.39 1229 313.08 0
0.4 sec 2305.1 0 59.463 1 283.29 1193.4 354.43 0
0.44 sec 2317.4 0 59.409 1 282.91 1156.6 394.58 0
0.48 sec 2330.5 0 59.356 1 281.84 1112.8 433.27 0
0.52 sec 2344.5 0 59.302 1 281.19 1073.1 470.53 0
0.56 sec 2359.1 0 59.248 1 279.77 1032.9 506.43 0
0.6 sec 2376.4 0 59.195 1 277.89 993.97 540.92 0
⋮