2022-2023 大创项目——定制化汽车动力系统

Eric Zhang Lv3

汽车功率需求仿真

模型初步搭建与仿真验证

每个驾驶员有自己的驾驶习惯,不同的驾驶习惯对应不同的驾驶模式,不同的驾驶模式对应不同的功率需求。因此,我们需要对不同的驾驶模式进行仿真。 于是我们使用了MATLAB/Simulink进行仿真,很简单粗暴,其公式依据是:

Variants Value meaning
? 车的质量
? 道路倾角
0.0065 滚动阻力系数1
滚动阻力系数2
? 车的速度
空气密度
车的正前方面积
0.8 气动阻力系数
暂不考虑 传输效率
暂不考虑 发动机效率
暂不考虑 反相器效率

可能有些参数设定的不是很准确(比如),再说吧。 模型需要参数输入,我个人采用了一种绕弯的思路:python生成h5数据文件,再用matlab转换成mat读取到simulink中(具体为什么,我也不知道我为啥这么干QAQ) 1. python生成h5数据文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import scipy.io as scio # 可能用不到
import h5py
import numpy as np
import json # 可能也用不到
simin_v = list(np.zeros(5)) + list(range(0,20)) + list(20 * np.ones(20)) + list(np.arange(20, 0, -0.5)) + list(np.zeros(5)) # 速度
simin_mass = list(2000 * np.ones(len(simin_v))) # 质量,由于simulink需要时间戳进行仿真,必须要一串相同的数,考虑相对论效应的另当别论(bushi)
simin_theta = list(np.zeros(len(simin_v))) # 路面倾角

h5file = h5py.File("./dataset/data_v.h5", 'w')
h5file.create_dataset('simin_v', data=simin_v)

h5file = h5py.File("./dataset/data_mass.h5", 'w')
h5file.create_dataset('simin_mass', data=simin_mass)

h5file = h5py.File("./dataset/data_theta.h5", 'w')
h5file.create_dataset('simin_theta', data=simin_theta)

h5file.close

  1. matlab读取h5数据文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    fileInfo_v = h5info('./dataset/data_v.h5');
    fileInfo_mass = h5info('./dataset/data_mass.h5');
    fileInfo_theta = h5info('./dataset/data_theta.h5');

    h5disp('./dataset/data_v.h5');
    h5disp('./dataset/data_mass.h5');
    h5disp('./dataset/data_theta.h5');

    v = h5read("./dataset/data_v.h5",'/simin_v');
    mass = h5read("./dataset/data_mass.h5",'/simin_mass');
    theta = h5read("./dataset/data_theta.h5",'/simin_theta');
    % 转换成时间表,不然simulink会报错
    v_time_table = array2timetable(v,'TimeStep',seconds(1));
    mass_time_table = array2timetable(mass,'TimeStep',seconds(1));
    theta_time_table = array2timetable(theta,'TimeStep',seconds(1));

    save('data_v.mat','v_time_table',"-v7.3");
    save('data_mass.mat','mass_time_table',"-v7.3");
    save('data_theta.mat','theta_time_table',"-v7.3");
    % 这里是队友写的路面仿真用于导入路面倾角的
    % load_system('Road_module');
    % road = sim('Road_module');

    % 运行模型
    load_system('force_model');
    out = sim('force_model');
    % 画出功率曲线
    plot(out.P_trac);

准备好所用的数据之后,就可以开始扔进simulink中进行仿真了。仿真模型如下: fig01 fig02 fig03

仿真结果:(以python中的数据为例) fig04

有负值的功率很正常,这涉及到制动过程中的反向充电等机电专业的知识(承认自己也不是很懂这一块)。

用户API的搭建实现个性化输入数据

如前所示,不同的人驾驶习惯不同,主要体现在加速度和速度的变化、车的质量喜好等等,所以我们需要一个用户API,让用户可以自定义输入数据,这样才能更好的模拟真实的驾驶情况。

由于本人之前从没接触过前端开发,队(WANG)友(LAO)曾经用过C++写过串口调试助手,于是也试一试基于C++开发上位机。所用IDE为Visual Studio 2022, 环境搭建参见Microsoft官方文档:https://learn.microsoft.com/zh-cn/cpp/windows/desktop-applications-visual-cpp?view=msvc-170 .跑了遍例程,发现报错:

严重性 代码 说明 项目 文件 禁止显示状态
错误 LNK2019 无法解析的外部符号 main,函数 "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) 中引用了该符号 DesktopApp D:FILES WorkSpace.lib(exe_main.obj) 1
错误 LNK1120 1 个无法解析的外部命令 DesktopApp D:FILES WorkSpace.exe 1

经过一番搜索,发现是因为项目配置不对。参考下面的博客https://blog.csdn.net/csshuaige/article/details/120313469 修改配置后无错运行,证明环境搭建成功。

跑完了,这个界面是真的丑……

果断放弃,转战Qt! Qt的安装参见官方文档:https://doc.qt.io/qt-5/windows.html#installing-qt-creator ,这里不再赘述。

Qt Creator初体验

打开Qt Creator,创建一个新工程。

fig04 fig04 fig04 fig04 fig04 fig04 fig04 fig04

至此,一个简单的Qt工程就创建好了。

该工程的目录结构如下: fig04

其中供用户操作的文件包括一个头文件,两个cpp,和一个ui文件。头文件中包含了用户API的声明,cpp文件中包含了用户API的实现,ui文件中包含了用户界面的设计。

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTextEdit>
#include <QFile>
#include <QDataStream>
#include <QMessageBox>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget

{
Q_OBJECT

public:
Widget(QWidget *parent = nullptr);
~Widget();

private slots:
void on_pushButton_clicked();

private:
QTextEdit *textEdit;
Ui::Widget *ui;
};

#endif // WIDGET_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//main.cpp
#include "widget.h"

#include <QApplication>
#include <QLocale>
#include <QTranslator>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

QTranslator translator;
const QStringList uiLanguages = QLocale::system().uiLanguages();
for (const QString &locale : uiLanguages) {
const QString baseName = "test01_" + QLocale(locale).name();
if (translator.load(":/i18n/" + baseName)) {
a.installTranslator(&translator);
break;
}
}
Widget w;
w.show();
return a.exec();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//widget.cpp
#include "widget.h"
#include "./ui_widget.h"


Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);

}

Widget::~Widget()
{
delete ui;
}

void Widget::on_pushButton_clicked()
{
QTextEdit *textEdit;
QString text_simulation_time = ui->textEdit->toPlainText();
QString text_car_mass = ui->textEdit_2->toPlainText();
QString text_velocity = ui->textEdit_3->toPlainText();
QString text_angle = ui->textEdit_4->toPlainText();
QFile file("D:/PERSONAL FILES/Qt_workspace/test01/testfile.txt");


if (!file.open(QFile::WriteOnly | QFile::Text)) //检测文件是否打开
{
QMessageBox::information(this, "Error Message", "Please Select a Text File!");
return;
}
QTextStream out(&file);
out << text_simulation_time;
out << "\n";
out << text_car_mass;
out << "\n";
out << text_velocity;
out << "\n";
out << text_angle;
}

ui文件负责设计界面样式,与源代码交互是通过“槽”来实现。比如,如果想在按钮点击的时候触发某些事件,需要在'.ui'文件中右击按钮,点击“转到槽”,然后在弹出的窗口中选择“on_pushButton_clicked”这个槽,这样就将按钮和槽连接起来了。在源代码中,只需要在槽函数中实现相应的功能即可。

下面是我用来实现点击按钮保存的槽函数代码部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void Widget::on_pushButton_clicked()
{
QTextEdit *textEdit;
QString text_simulation_time = ui->textEdit->toPlainText();
QString text_car_mass = ui->textEdit_2->toPlainText();
QString text_velocity = ui->textEdit_3->toPlainText();
QString text_angle = ui->textEdit_4->toPlainText();
QFile file("D:/PERSONAL FILES/Qt_workspace/test01/testfile.txt");


if (!file.open(QFile::WriteOnly | QFile::Text)) //检测文件是否打开
{
QMessageBox::information(this, "Error Message", "Please Select a Text File!");
return;
}
QTextStream out(&file);
out << text_simulation_time;
out << "\n";
out << text_car_mass;
out << "\n";
out << text_velocity;
out << "\n";
out << text_angle;
}

下面是初步设计的UI界面 fig04

实现效果: fig04

至此,初步完成了数据输入保存的操作。

数据有了,接下来的一部就是与之前的python文件结合了。以下为修改之后的用于读取生成数据的txt文件的python脚本代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import scipy.io as scio
import h5py
import numpy as np
import json
import os # 用于文件读写操作

file_path = 'D:/PERSONAL FILES/Qt_workspace/test01/testfile.txt'
with open(file_path, encoding='utf-8') as file_obj: # open函数返回一个表示文件的对象,python会将这个对象存储在我们的变量file_obj中
lines = file_obj.readlines()

for line in lines:
print(line.rstrip())


simin_time = int(lines[0])

list_simin_v = lines[2].strip().split(',')
list_simin_v_0 = list(map(lambda x: int(x), list_simin_v))

list_simin_mass = list(int(lines[1]) * np.ones(simin_time))

list_simin_theta = [int(lines[3])]
list_simin_theta_0 = list(map(lambda x: int(x), list_simin_theta))

print(" simin_time:%s;\n car mass:%s;\n car velocity:%s;\n road angle:%s\n" % (simin_time, int(lines[1]), list_simin_v_0, int(lines[3])))
print(list_simin_v_0)
print(list_simin_mass)
print(list_simin_theta_0)
h5file = h5py.File("./dataset/data_v.h5", 'w')
h5file.create_dataset('simin_v', data=list_simin_v_0)

h5file = h5py.File("./dataset/data_mass.h5", 'w')
h5file.create_dataset('simin_mass', data=list_simin_mass)

h5file = h5py.File("./dataset/data_theta.h5", 'w')
h5file.create_dataset('simin_theta', data=list_simin_theta_0)

h5file.close

路面状态仿真

锂电池参数仿真

氢氧燃料电池参数仿真

优化算法

  • 标题: 2022-2023 大创项目——定制化汽车动力系统
  • 作者: Eric Zhang
  • 创建于 : 2023-03-26 03:33:40
  • 更新于 : 2023-12-03 23:43:06
  • 链接: https://ericzhang1412.github.io/2023/03/26/01_大创/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
 评论