db2日期格式转换为yyyymmdd_MATLAB GUI制作——转换mdf/mf4格式为mat格式

前言:作为一名汽车软件开发或测试工程师,经常会碰到各种分析困难的问题,这就需要将测试数据导出至simulink中进行mil仿真,看看到底是哪里出了问题?Canape软件支持将mdf或mf4格式数据转换为mat格式的数据,但对于采集的长时间数据在导出过程中,想要保持一定的采样精度和连续性,经常会碰到导出报错“内存不足”、导出数据失败。这就需要想另外的办法,怎样保持采样精度也能保证连续性?本文将介绍怎样将mdf/mf4格式的数据保持采样精度和连续性导出为mat格式。

4436cfbb18e88ee768f76d0a9669bdf0.png
长时间的数据导出报错“内存不足”

准备工具:MATLAB 2016B、CANape。

正文:如果需要将mdf/mf4格式数据保存为mat格式,我们需要知道mdf/mf4格式文件的数据结构是什么样的?MATLAB 2016B中针对mdf/mf4格式文件有一个专门的函数可用于打开此文件,函数名为“mdf( )”。本文以CANape软件示例的一个mdf文件为例,首先用CANape打开一个mdf文件,查看文件有哪些信号?示例文件在CANape安装目录下,如本机为:D:Program Files (x86)VectorExamplesExamplesinus.mdf。

31e5c132df14c2467f87db1ac3aca7f7.png
示例文件的信号列表

查看信号SinusPhase0,就是一个正弦波。

c7d700fc1abdaaec5de1398eda952b4c.png

查看完信号列表后,再用MATLAB打开对应的文件,看看在哪些地方能找到对应的信号。

baf4bdedf75e5cbe84300dce6572a8ef.png
用mdf( )函数打开示例mdf文件

打开后,看到文件的数据结构如下,在ChannelNames中能找到对应的信号名。

b4ccfe415b3ac4c06da049f932ed2a1c.png
mdf文件数据结构

691837bf7f471a526d923bf4eab039b4.png
ChannelNames查找到对应的信号

通过read( )函数读取对应信号,并使用plot( )函数画图,发现信号与CANape中曲线能完美对应上。

5af7b1b7cf37d38014268fbad7498919.png
read( )函数读取信号

98b5e511b8dec1f027f6f8dbbf1bc2c4.png
plot对应信号

了解了mdf数据文件结构后,我们就开始使用脚本实现自动化读取想要的信号了。

制作完成的GUI界面如下:

aa14add1228a738e7634c5ef6b1596af.png

通过如下代码,可以实现打开并读取mdf数据文件。

[

在读取文件后,我们需要判断选取的文件是否是一个有效的mdf或mf4文件。

FileName = app.FilePath.Value;
FileNameLen = length(FileName);
if ~(strcmpi(FileName(FileNameLen-3:1:FileNameLen), '.mdf') || strcmpi(FileName(FileNameLen-3:1:FileNameLen), '.mf4'))
     msgbox('无效mdf或mf4文件,请重新选择数据文件!');
else
     ...
end

读取并判断文件的有效性后,我们接下来就是读取所有需要的信号。我们将所有需要的信号以空格字符或“;”作为分隔符,将信号进行分割。如“SinusPhase0;SinusPhase90;SinusPhase180;SinusPhase270;”

%切割信号名序列
Variables = split(app.SignalName.Value, {' ',';'});
VariablesNum = length(Variables);

信号分割完成后,就是对各个信号进行罗列查找了。

VariableName(countFind) = read(app.DataFile, VariableNamei, char(Variables(i)), 'OutputFormat', 'timeseries');

为了了解到转换的进度,可通过添加数字进度,进行转换进度的展示。

%转换进度
percent = min(i/VariablesNum*100, 99);
percentStr = strcat(num2str(percent), '%');
app.StartMake.Text = strcat('转换进度:', percentStr);

所有信号查找完成后,需要将信号统一时间刻度,然后保存为mat格式。

eval(strcat(VariableName(i).Name, ' = interp1(VariableName(i).Time, VariableName(i).Data, t, ''linear'', ''extrap'');'));
save(char(DataName), VariableName(i).Name, '-append');

如果想要将所有缺失的信号展示出来,可通过如下代码实现。

if 

通过以上主要的函数接口和代码,即可实现将mdf/mf4格式数据转换为mat格式。

如需具体代码,可留言联系。

应各位知友的要求,本帖将源代码贴上。

classdef CANape_DataFormat_Conversion < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        mdftomatUIFigure  matlab.ui.Figure
        FilePath          matlab.ui.control.EditField
        mdfmf4Label       matlab.ui.control.Label
        SelectFile        matlab.ui.control.Button
        StartMake         matlab.ui.control.Button
        Label_2           matlab.ui.control.Label
        SignalName        matlab.ui.control.TextArea
        Lamp              matlab.ui.control.Lamp
        Label_3           matlab.ui.control.Label
        signalPeriod      matlab.ui.control.NumericEditField
        msLabel           matlab.ui.control.Label
    end

    
    properties (Access = public)
        DataFile; % Description
    end
    

    methods (Access = private)

        % Callback function: FilePath, SelectFile
        function SelectA2LFile(app, event)
            [FileName, PathName] = uigetfile('*.mf4;*.mdf', '选择一个mdf或mf4文件');
            app.FilePath.Value = strcat(PathName, FileName);
            app.DataFile = mdf(app.FilePath.Value);
        end

        % Button pushed function: StartMake
        function StartMakeButtonPushed(app, event)
            app.StartMake.Enable = 'off';
            FileName = app.FilePath.Value;
            FileNameLen = length(FileName);
            if ~(strcmpi(FileName(FileNameLen-3:1:FileNameLen), '.mdf') || strcmpi(FileName(FileNameLen-3:1:FileNameLen), '.mf4'))
                msgbox('无效mdf或mf4文件,请重新选择数据文件!');
            else
                app.Lamp.Color = [1,0,0];
                %设定待保存文件名
                FileNameSplit = split(app.FilePath.Value, '');
                tempName = char(FileNameSplit(length(FileNameSplit)));
                DataName = strcat(tempName(1:length(tempName)-4), '.mat');
                %切割信号名序列
                Variables = split(app.SignalName.Value, {' ',';'});
                VariablesNum = length(Variables);
                %逐个查找信号名并保存至文件
                countMiss = 0;
                countFind = 0;
                for i = 1:VariablesNum
                    if strcmp(Variables(i), '')==0
                        flag = 0;
                        for VariableNamei = 1:length(app.DataFile.ChannelNames)
                            for VariableNamej = 1:length(app.DataFile.ChannelNames{VariableNamei})
                                if strcmp(Variables(i), app.DataFile.ChannelNames{VariableNamei}{VariableNamej})==1
                                    flag = 1;
                                    break;
                                end
                            end
                            if flag==1
                                break;
                            end
                        end
                        if VariableNamei==length(app.DataFile.ChannelNames) && flag==0
                            countMiss = countMiss + 1;
                            missVariable(countMiss) = i;
                        else
                            try
                                countFind = countFind + 1;
                                VariableName(countFind) = read(app.DataFile, VariableNamei, char(Variables(i)), 'OutputFormat', 'timeseries');
                                %转换进度
                                percent = min(i/VariablesNum*100, 99);
                                percentStr = strcat(num2str(percent), '%');
                                app.StartMake.Text = strcat('转换进度:', percentStr);
                            catch
                                countFind = countFind - 1;
                                countMiss = countMiss + 1;
                                missVariable(countMiss) = i;
                            end
                        end                      
                    end
                end
                
                % 数据统一时间
                if countFind>0
                    if app.signalPeriod.Value/1000.0 > max(VariableName(1).Time)
                        msgbox('设定的信号周期超过了信号的最大时间,请重新设定合适的信号周期!');
                        return;
                    end
                    t = [0:app.signalPeriod.Value/1000.0:max(VariableName(1).Time)]';
                    save(char(DataName), 't');
                    for i = 1:countFind
                        eval(strcat(VariableName(i).Name, ' = interp1(VariableName(i).Time, VariableName(i).Data, t, ''linear'', ''extrap'');'));
                        save(char(DataName), VariableName(i).Name, '-append');
                    end
                end
                
                app.StartMake.Text = strcat('转换进度:', '100%');
                
                if countMiss>=1
                    fid = fopen('missSignalName.txt','w');
                    fprintf(fid, '缺失的信号如下:');
                    fprintf(fid, 'n');
                    for i = 1:countMiss
                        fprintf(fid, char(Variables(missVariable(i))));
                        fprintf(fid, ';');
                    end
                    msgbox('该数据文件缺失部分信号,详见同目录下missSignalName.txt!');
                end
                
                msgbox('数据格式转换完成!');
                app.StartMake.Text = '开始转换';
                app.StartMake.Enable = 'on';
                app.Lamp.Color = [0,1,0];
            end
        end
    end

    % App initialization and construction
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Create mdftomatUIFigure
            app.mdftomatUIFigure = uifigure;
            app.mdftomatUIFigure.Position = [100 100 640 480];
            app.mdftomatUIFigure.Name = 'mdf to mat';
            app.mdftomatUIFigure.Resize = 'off';
            setAutoResize(app, app.mdftomatUIFigure, true)

            % Create FilePath
            app.FilePath = uieditfield(app.mdftomatUIFigure, 'text');
            app.FilePath.ValueChangedFcn = createCallbackFcn(app, @SelectA2LFile, true);
            app.FilePath.Position = [169 437 370 22];

            % Create mdfmf4Label
            app.mdfmf4Label = uilabel(app.mdftomatUIFigure);
            app.mdfmf4Label.HorizontalAlignment = 'right';
            app.mdfmf4Label.FontWeight = 'bold';
            app.mdfmf4Label.Position = [17 441 153 15];
            app.mdfmf4Label.Text = '待处理的mdf或mf4文件:';

            % Create SelectFile
            app.SelectFile = uibutton(app.mdftomatUIFigure, 'push');
            app.SelectFile.ButtonPushedFcn = createCallbackFcn(app, @SelectA2LFile, true);
            app.SelectFile.FontWeight = 'bold';
            app.SelectFile.Position = [558 437 69 22];
            app.SelectFile.Text = '选择';

            % Create StartMake
            app.StartMake = uibutton(app.mdftomatUIFigure, 'push');
            app.StartMake.ButtonPushedFcn = createCallbackFcn(app, @StartMakeButtonPushed, true);
            app.StartMake.FontSize = 14;
            app.StartMake.FontWeight = 'bold';
            app.StartMake.Position = [152 22 432 32];
            app.StartMake.Text = '开始转换';

            % Create Label_2
            app.Label_2 = uilabel(app.mdftomatUIFigure);
            app.Label_2.HorizontalAlignment = 'right';
            app.Label_2.FontWeight = 'bold';
            app.Label_2.Position = [17 402 109 15];
            app.Label_2.Text = '待转换的信号名:';

            % Create SignalName
            app.SignalName = uitextarea(app.mdftomatUIFigure);
            app.SignalName.Position = [27 70 600 323];

            % Create Lamp
            app.Lamp = uilamp(app.mdftomatUIFigure);
            app.Lamp.Position = [596 28 20 20];

            % Create Label_3
            app.Label_3 = uilabel(app.mdftomatUIFigure);
            app.Label_3.HorizontalAlignment = 'right';
            app.Label_3.FontWeight = 'bold';
            app.Label_3.Position = [17 31 57 15];
            app.Label_3.Text = '信号周期';

            % Create signalPeriod
            app.signalPeriod = uieditfield(app.mdftomatUIFigure, 'numeric');
            app.signalPeriod.Limits = [1 10000];
            app.signalPeriod.Position = [76 27 37 22];
            app.signalPeriod.Value = 5;

            % Create msLabel
            app.msLabel = uilabel(app.mdftomatUIFigure);
            app.msLabel.Position = [116 31 25 15];
            app.msLabel.Text = 'ms';
        end
    end

    methods (Access = public)

        % Construct app
        function app = CANape_DataFormat_Conversion()

            % Create and configure components
            createComponents(app)

            % Register the app with App Designer
            registerApp(app, app.mdftomatUIFigure)

            if nargout == 0
                clear app
            end
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            delete(app.mdftomatUIFigure)
        end
    end
end
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值