本页面提供的是上一版软件的文档。当前版本中已删除对应的英文页面。

对多个 MDF 文件进行数据分析

以下示例说明如何研究多个驾驶周期间放电模式下的车辆电池电量。用于此分析的数据包含在一组 MDF 格式的车辆日志文件中。对于此示例,我们需要建立一种机制,用于“检测”车辆电池何时处于给定模式。我们真正要做的是建立一个探测器,以确定何时关注的信号(在本例中为电池电量)满足特定条件。当条件得到满足时,我们称之为一个“事件”。每个事件都需要满足一定的时间限制才算是“合格”事件。也就是说,事件至少要持续 5 秒,才算是一个“合格的”事件。这种验证步骤有助于限制噪声和消除瞬变。此示例中显示的阈值仅用于举例说明。

设置数据源位置

定义要分析的文件集的位置。

dataDir = '*.dat';

获取文件集信息

将要分析的所有 MDF 文件的名称放入一个元胞数组中。

fileList = dir(dataDir);
fileName = {fileList(:).name}';
fileDir  = {fileList(:).folder}';
fullFilePath = fullfile(fileDir, fileName)
fullFilePath = 10×1 cell array
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\ADAC.dat' }
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\ECE.dat'  }
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\FTP75.dat'}
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\HUDDS.dat'}
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\HWFET.dat'}
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\JC08.dat' }
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\LA92.dat' }
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\NEDC.dat' }
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\SC03.dat' }
    {'\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\US06.dat' }

预分配输出数据元胞数组

使用一个元胞数组来捕获一组迷你表,这些表用来表示每个 MDF 文件所关注的事件数据。

numFiles = size(fullFilePath, 1);
eventSet = cell(numFiles, 1)
eventSet = 10×1 cell array
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}
    {0×0 double}

定义事件检测和通道信息条件

chName = 'Power';         % Name of the signal of interest in the MDF files
thdValue = [5, 55];       % Threshold in KW
thdDuration = seconds(5); % Threshold for event qualification

循环遍历每个 MDF 文件并应用事件检测器函数

eventSet 是一个元胞数组,其中包含已分析的每个文件的摘要表。您可以将这个由表组成的元胞数组视为一组迷你表,所有这些迷你表都具有相同的格式,但每个迷你表的内容分别对应于不同的 MDF 文件。

在此示例中,事件检测器不仅报告事件的开始和结束时间,还报告有关事件本身的一些描述性统计量。这种聚合和报告可用于发现活动和对活动进行故障排除。要更详细地了解 MDF 文件对接和数据处理,请打开并探查此示例中的 processMDF 函数。

请注意本例的数据处理方式,它以原子方式解析每个 MDF 文件,并将解析结果返回到结果元胞数组中对应的索引位置。这允许处理函数通过 parfor 利用并行计算功能。parfor 和标准 for 在输出方面可以互换,但两者在完成分析所需的处理时间上有所不同。要试验并行计算,只需将下面的 for 调用更改为 parfor 并运行示例即可。

for i = 1:numFiles
    eventSet{i} = processMDF(fullFilePath{i}, chName, thdValue, thdDuration);
end
eventSet{1}
ans=20×8 table
    FileName    EventNumber    EventDuration    EventStart    EventStop     MeanPower_KW    MaxPower_KW    MinPower_KW
    ________    ___________    _____________    __________    __________    ____________    ___________    ___________

    ADAC.dat        2            00:01:22       19.345 sec    101.79 sec       28.456           53.5              5   
    ADAC.dat        3            00:00:08       107.82 sec    116.36 sec       21.295           53.5           5.09   
    ADAC.dat        5            00:00:55        123.8 sec    179.67 sec       28.642           37.2           5.01   
    ADAC.dat        6            00:00:10       189.83 sec    200.36 sec       11.192           54.4            5.1   
    ADAC.dat        8            00:00:40        212.4 sec    252.79 sec       28.539           37.4           5.01   
    ADAC.dat        9            00:00:08       258.76 sec    267.37 sec       21.289           53.7           5.02   
    ADAC.dat        11           00:00:44       274.81 sec    319.79 sec       28.554           37.2           5.08   
    ADAC.dat        12           00:00:08       325.75 sec    334.37 sec       21.279           53.7           5.05   
    ADAC.dat        14           00:00:44       341.81 sec    386.79 sec       28.554           37.2           5.08   
    ADAC.dat        15           00:00:08       392.75 sec    401.37 sec       21.278           53.7           5.04   
    ADAC.dat        17           00:00:44       408.81 sec    453.67 sec       28.579           37.2           5.08   
    ADAC.dat        18           00:00:07       463.77 sec    471.37 sec       11.895         54.676           5.04   
    ADAC.dat        20           00:00:40       483.44 sec    523.79 sec       28.544         37.363         5.0682   
    ADAC.dat        21           00:00:08       529.75 sec    538.37 sec       21.279           53.7           5.05   
    ADAC.dat        23           00:00:44       545.81 sec    590.79 sec       28.553           37.2           5.08   
    ADAC.dat        24           00:00:08       596.75 sec    605.37 sec       21.279           53.7           5.05   
      ⋮

串联结果

将元胞数组 eventSet 的内容合并到一个表中。我们现在可以使用表 eventSummary 进行后续分析。head 函数用于显示表 eventSummary 的前 5 行。

eventSummary = vertcat(eventSet{:});
disp(head(eventSummary, 5))
    FileName    EventNumber    EventDuration    EventStart    EventStop     MeanPower_KW    MaxPower_KW    MinPower_KW
    ________    ___________    _____________    __________    __________    ____________    ___________    ___________

    ADAC.dat         2           00:01:22       19.345 sec    101.79 sec       28.456          53.5              5    
    ADAC.dat         3           00:00:08       107.82 sec    116.36 sec       21.295          53.5           5.09    
    ADAC.dat         5           00:00:55        123.8 sec    179.67 sec       28.642          37.2           5.01    
    ADAC.dat         6           00:00:10       189.83 sec    200.36 sec       11.192          54.4            5.1    
    ADAC.dat         8           00:00:40        212.4 sec    252.79 sec       28.539          37.4           5.01    

可视化摘要结果以确定后续步骤

查看事件持续时间的概览。

histogram(eventSummary.EventDuration)
grid on
title 'Distribution of Event Duration'
xlabel 'Event Duration (minutes)'
ylabel 'Frequency'

现在看看均值电量与事件持续时间。

scatter(eventSummary.MeanPower_KW, minutes(eventSummary.EventDuration))
grid on
xlabel 'MeanPower(KW)'
ylabel 'Event Duration (minutes)'
title 'Mean Power vs. Event Duration'

深入分析关注的事件

检查持续时间超过 4 分钟的事件。首先,创建一个封装来查找关注的情形。msk 是逻辑索引,用于显示表 eventSummary 的哪些行满足指定的条件。

msk = eventSummary.EventDuration > minutes(4);

提取表 eventSummary 中满足指定条件的行并显示结果。

eventOfInterest = eventSummary(msk, :);
disp(eventOfInterest)
    FileName     EventNumber    EventDuration    EventStart    EventStop     MeanPower_KW    MaxPower_KW    MinPower_KW
    _________    ___________    _____________    __________    __________    ____________    ___________    ___________

    HWFET.dat        18           00:04:43       297.22 sec    580.37 sec       12.275          30.2          5.0024   

在整个驾驶周期背景中可视化此事件

我们需要完整的文件路径和文件名来从 MDF 文件中读取数据。表 eventOfInterest 具有文件名,因为我们对其进行了跟踪。它没有该文件的完整文件路径。为了获得这些信息,我们会对原始文件名和路径列表进行一些集合处理。首先,找到关注的文件的完整文件路径。

fileMsk = find(ismember(fileName, eventOfInterest.FileName))
fileMsk = 5

创建一个 MDF 对象以从 MDF 文件中读取数据。

mdfObj = mdf(fullFilePath{fileMsk})
mdfObj = 
  MDF with properties:

   File Details
                 Name: 'HWFET.dat'
                 Path: '\\central-mi\home\jpyle\documents\MATLAB\examples\vnt-ex86857001\HWFET.dat'
               Author: ''
           Department: ''
              Project: ''
              Subject: ''
              Comment: ''
              Version: '3.00'
             DataSize: 3167040
     InitialTimestamp: 2017-08-09 12:20:03.000000000

   Creator Details
    ProgramIdentifier: 'MDA v7.1'
              Creator: [0×0 struct]

   File Contents
           Attachment: [0×0 struct]
         ChannelNames: {{5×1 cell}}
         ChannelGroup: [1×1 struct]

使用 channelList 标识通道并读取此文件中的所有数据。

chInfo = channelList(mdfObj, chName)
chInfo=1×9 table
    ChannelName    ChannelGroupNumber    ChannelGroupNumSamples    ChannelGroupAcquisitionName    ChannelGroupComment    ChannelDisplayName    ChannelUnit    ChannelComment    ChannelDescription
    ___________    __________________    ______________________    ___________________________    ___________________    __________________    ___________    ______________    __________________

      "Power"              1                     79176                     <undefined>                cg comment                 ""            cg comment       cg comment              ""        

data = read(mdfObj, chInfo)
data = 1×1 cell array
    {79176×1 timetable}

请注意,从 channelList 的输出读取数据会返回一个包含结果的元胞数组。

data{1}(1:10,:)
ans=10×1 timetable
        Time           Power  
    _____________    _________

    0.0048987 sec            0
    0.0088729 sec            0
    0.01 sec                 0
    0.013223 sec             0
    0.016446 sec             0
    0.019668 sec             0
    0.02 sec                 0
    0.021658 sec      -2.4e-28
    0.023878 sec     -3.42e-15
    0.026098 sec     -1.04e-14

使用自定义绘图函数进行可视化

自定义绘图函数可用于封装和重用。在整个驾驶周期背景中可视化事件。要了解可视化的创建方式,请打开并探查此示例中的 eventPlotter 函数。

eventPlotter(data{1}, eventOfInterest)