2022-2023 大创项目——定制化汽车动力系统 
                
            
             
        
            
            汽车功率需求仿真 
模型初步搭建与仿真验证 
每个驾驶员有自己的驾驶习惯,不同的驾驶习惯对应不同的驾驶模式,不同的驾驶模式对应不同的功率需求。因此,我们需要对不同的驾驶模式进行仿真。
 
于是我们使用了MATLAB/Simulink进行仿真,很简单粗暴,其公式依据是:
 
 
? 
车的质量 
 
 
? 
 道路倾角 
 
 
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  h5pyimport  numpy as  npimport  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)))  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 
 
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' ); 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('force_model' ); out = sim('force_model' ); plot (out.P_trac);
 
 
准备好所用的数据之后,就可以开始扔进simulink中进行仿真了。仿真模型如下:
    
仿真结果:(以python中的数据为例) 
有负值的功率很正常,这涉及到制动过程中的反向充电等机电专业的知识(承认自己也不是很懂这一块)。
用户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,创建一个新工程。
   
          
至此,一个简单的Qt工程就创建好了。
该工程的目录结构如下: 
其中供用户操作的文件包括一个头文件,两个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 #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   
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #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 #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界面 
实现效果: 
至此,初步完成了数据输入保存的操作。
数据有了,接下来的一部就是与之前的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  scioimport  h5pyimport  numpy as  npimport  jsonimport  os file_path = 'D:/PERSONAL FILES/Qt_workspace/test01/testfile.txt'  with  open (file_path, encoding='utf-8' ) as  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 
 
路面状态仿真 
锂电池参数仿真 
氢氧燃料电池参数仿真 
优化算法