diff --git a/RRS.pro b/RRS.pro index 7ad0fc3b..5c77d8aa 100644 --- a/RRS.pro +++ b/RRS.pro @@ -22,7 +22,7 @@ SUBDIRS += ./addons/vl60 SUBDIRS += ./addons/tep70 #SUBDIRS += ./addons/chs4t SUBDIRS += ./addons/chs2t -#SUBDIRS += ./addons/ep20 +SUBDIRS += ./addons/ep20 SUBDIRS += ./launcher SUBDIRS += ./launcher2 diff --git a/addons/ep20/ep20/include/ac-motor-compressor.h b/addons/ep20/ep20/include/ac-motor-compressor.h new file mode 100644 index 00000000..ce2993aa --- /dev/null +++ b/addons/ep20/ep20/include/ac-motor-compressor.h @@ -0,0 +1,64 @@ +#ifndef AC_MOTOR_COMPRESSOR_H +#define AC_MOTOR_COMPRESSOR_H + +#include "device.h" + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +class ACMotorCompressor : public Device +{ +public: + + ACMotorCompressor(QObject *parent = Q_NULLPTR); + + ~ACMotorCompressor(); + + void setExternalPressure(double press); + + double getAirFlow() const; + + void setU_power(double value); + +private: + + /// Внешнее противодавление + double p; + + /// Расход возхуа + double Q; + + /// "Подача" компрессора + double p0; + + double Mmax; + + double s_kr; + + double Un; + + double U_power; + + double omega0; + + double J; + + double Mxx; + + double Vnk; + + enum + { + NUM_COEFFS = 6 + }; + + std::array K; + + void preStep(state_vector_t &Y, double t); + + void ode_system(const state_vector_t &Y, state_vector_t &dYdt, double t); + + void load_config(CfgReader &cfg); +}; + +#endif // ACMOTORCOMPRESSOR_H diff --git a/addons/ep20/ep20/include/auxiliary-converter.h b/addons/ep20/ep20/include/auxiliary-converter.h new file mode 100644 index 00000000..7d5150da --- /dev/null +++ b/addons/ep20/ep20/include/auxiliary-converter.h @@ -0,0 +1,63 @@ +#ifndef AUXILIARY_CONVERTER_H +#define AUXILIARY_CONVERTER_H + +#include "device.h" + +/// Класс Преобразователя Собственных Нужд +class AuxiliaryConverter : public Device +{ + +public: + + /// Конструктор + AuxiliaryConverter(QObject *parent = Q_NULLPTR); + + /// Деструктор + ~AuxiliaryConverter(); + + /// Установить напряжение преобразователя собственных нужд + void setU4(double U4); + + /// Получить напряжение + double getU1(); + + /// Получить частоту + double getF(); + + /// получить напряжение (380 В) + double getU2(); + +private: + + /// Напряжение преобразователя собственных нужд + double U4; + + /// Частота + double Fref; + + /// Напряжение + double Uref; + + /// Коэффициент напряжения + double Koef; + + /// Напряжение на выход + double U1; + + /// Частота на выход + double F; + + /// Напряжение 380 на выход + double U2; + + /// Предварительный шаг + void preStep(state_vector_t &Y, double t); + + /// Вычисление напряжения + void ode_system(const state_vector_t &Y, state_vector_t &dYdt, double t); + + /// Загрузка конфига + void load_config(CfgReader &cfg); +}; + +#endif // AUXILIARYCONVERTER_H diff --git a/addons/ep20/ep20/include/ep20-brake-mech.h b/addons/ep20/ep20/include/ep20-brake-mech.h new file mode 100644 index 00000000..870d9a0e --- /dev/null +++ b/addons/ep20/ep20/include/ep20-brake-mech.h @@ -0,0 +1,22 @@ +#ifndef EP20_BRAKE_MECH_H +#define EP20_BRAKE_MECH_H + +#include "brake-mech.h" + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +class EP20BrakeMech : public BrakeMech +{ +public: + + EP20BrakeMech(QObject *parent = Q_NULLPTR); + + ~EP20BrakeMech(); + +private: + + void load_config(CfgReader &cfg); +}; + +#endif // EP20_BRAKE_MECH_H diff --git a/addons/ep20/ep20/include/ep20-signals.h b/addons/ep20/ep20/include/ep20-signals.h new file mode 100644 index 00000000..b3cd6e39 --- /dev/null +++ b/addons/ep20/ep20/include/ep20-signals.h @@ -0,0 +1,16 @@ +#ifndef EP20_SIGNALS_H +#define EP20_SIGNALS_H + +enum +{ + KONTROLLER = 0, + RUK_KRM130 = 1, + RUK_KVT224 = 2, + + STRELKA_pTM = 10, + STRELKA_pGR = 11, + STRELKA_pTC = 12, + STRELKA_pUR = 13 +}; + +#endif // EP20_SIGNALS_H diff --git a/addons/ep20/ep20/include/ep20.h b/addons/ep20/ep20/include/ep20.h index f9d46cc4..52d0720f 100644 --- a/addons/ep20/ep20/include/ep20.h +++ b/addons/ep20/ep20/include/ep20.h @@ -19,6 +19,12 @@ #include "pant-description.h" #include "current-kind-switch.h" #include "protective-device.h" +#include "traction-transformer.h" +#include "traction-converter.h" +#include "auxiliary-converter.h" +#include "ac-motor-compressor.h" +#include "ep20-signals.h" +#include "ep20-brake-mech.h" /*! * \class @@ -37,6 +43,8 @@ class EP20 : public Vehicle /// Деструктор ~EP20(); + void initBrakeDevices(double p0, double pTM, double pFL); + private: // /// Выбор кабины @@ -54,6 +62,36 @@ class EP20 : public Vehicle /// Аппарат защиты (БВ) ProtectiveDevice *fastSwitch; + /// Тяговый трансформатор + TractionTransformer *tractionTrans; + + /// Нумератор тяговых преобразователей + enum + { + NUM_TRAC_CONV = 3 + }; + + /// Массив тяговых преобразователей + std::array trac_conv; + + enum + { + NUM_AUX_CONV = 4 + }; + + /// Преобразователь собственных нужд + std::array auxConv; + + /// Резервуар + Reservoir *main_reservoir; + + /// Запасный резервуар (ЗР) + Reservoir *spareReservoir; + + /// Мотор компрессор + std::array motorCompAC; +// ACMotorCompressor *motorCompAC; + /// Входные значения mpcs_input_t mpcsInput; @@ -63,12 +101,45 @@ class EP20 : public Vehicle /// Массив токоприемников std::array pantograph; + /// Зарядное давление + double charge_press; + + /// Поездной кран машиниста (КрМ) + BrakeCrane *krm; + + /// Кран вспомогательного тормоза (КВТ) + LocoCrane *kvt; + + /// Переключательный клапан (ЗПК) + SwitchingValve *zpk; + + /// Воздухораспределитель (ВР) + AirDistributor *airDistr; + + /// Электро-воздухораспределитель (ЭВР) + ElectroAirDistributor *electroAirDistr; + + enum + { + NUM_TROLLEYS = 3, + FWD_TROLLEY = 0, + MDL_TROLLEY = 1, + BWD_TROLLEY = 2 + }; + + std::array brake_mech; + std::array rd304; + std::array pSplit; + /// Инициализация void initialization(); /// Инициализация высоковольтной схемы void initHighVoltageScheme(); + /// Инициализация тормозного крана + void initBrakeControls(QString modules_dir); + /// Инициализация МПСУ void initMPCS(); @@ -81,11 +152,18 @@ class EP20 : public Vehicle /// Шаг моделирования высоковольтной схемы void stepHighVoltageScheme(double t, double dt); + /// Шаг моделирования тормозного крана + void stepBrakeControls(double t, double dt); + /// Загрузка данных из конфигурационных файлов void loadConfig(QString cfg_path); /// Обработчик клавиш void keyProcess(); + + void load_brakes_config(QString path); + + void stepSignals(); }; #endif // EP20_H diff --git a/addons/ep20/ep20/include/mpcs-data.h b/addons/ep20/ep20/include/mpcs-data.h index 08cfa64e..53cf2cd7 100644 --- a/addons/ep20/ep20/include/mpcs-data.h +++ b/addons/ep20/ep20/include/mpcs-data.h @@ -9,17 +9,50 @@ //------------------------------------------------------------------------------ struct mpcs_input_t { + /// Род тока int current_kind; + /// Поднятые ТП std::array pant_up; + /// Опущеные ТП std::array pant_down; + /// Отключен ли БВ + bool isOff_fs; + + /// ПРТ + int current_kind_switch_state; + + /// Входное напряжение на ГВ + double Uin_ms; + + /// Отключен ли ГВ + bool isOff_ms; + + /// Входное напряжение на БВ + double Uin_fs; + + std::array aux_const_U; + + // принимать данные давление в ГР + /// Входное давление с главного резервуара + double PressMR; + mpcs_input_t() { current_kind = 0; std::fill(pant_up.begin(), pant_up.end(), false); std::fill(pant_down.begin(), pant_down.end(), false); + + isOff_fs = false; + current_kind_switch_state = 0; + Uin_ms = 0; + + isOff_ms = false; + Uin_fs = 0; + + std::fill(aux_const_U.begin(), aux_const_U.end(), 0); } }; @@ -28,11 +61,24 @@ struct mpcs_input_t //------------------------------------------------------------------------------ struct mpcs_output_t { + /// Состояние ТП std::array pant_state; + /// Включение ГВ + bool turn_on_ms = false; + + /// Включение БВ + bool turn_on_fs = false; + + /// Тумблеры управления мотор-компрессорами + std::array toggleSwitchMK; + + double MKstate; + mpcs_output_t() { std::fill(pant_state.begin(), pant_state.end(), false); + std::fill(toggleSwitchMK.begin(), toggleSwitchMK.end(), false); } }; diff --git a/addons/ep20/ep20/include/mpcs.h b/addons/ep20/ep20/include/mpcs.h index d393f2a0..e9f24dc8 100644 --- a/addons/ep20/ep20/include/mpcs.h +++ b/addons/ep20/ep20/include/mpcs.h @@ -6,6 +6,7 @@ #include "pant-description.h" #include "timer.h" #include "mpcs-task-pant.h" +#include "auxiliary-converter.h" class MPCS : public Device { @@ -41,19 +42,52 @@ class MPCS : public Device /// Выходные значения mpcs_output_t mpcs_output; + /// Кнопка ГВ/БВ + Trigger ms_fs_on; + + AuxiliaryConverter *auxConv; + + Timer mkStartTimer; + + std::array mk_start; + + size_t mk_count; + + double p_prev; + + double p_min; + + double p_max; + /// Управление клавишами void stepKeysControl(double t, double dt); void stepDiscrete(double t, double dt); + /// Контроль ГВ + void stepMainSwitchControl(double t, double dt); + + /// Контроль БВ + void stepFastSwitchControl(double t, double dt); + + void stepToggleSwitchMK(double t, double dt); + + void PressureReg(); + /// Предварительный шаг void preStep(state_vector_t &Y, double t); + void postStep(state_vector_t &Y, double t); + /// Вычисление напряжения void ode_system(const state_vector_t &Y, state_vector_t &dYdt, double t); /// Загрузка конфига void load_config(CfgReader &cfg); + +private slots: + + void slotMKStart(); }; #endif // MPCS_H diff --git a/addons/ep20/ep20/include/traction-converter.h b/addons/ep20/ep20/include/traction-converter.h new file mode 100644 index 00000000..615909a7 --- /dev/null +++ b/addons/ep20/ep20/include/traction-converter.h @@ -0,0 +1,58 @@ +#ifndef TRACTION_CONVERTER_H +#define TRACTION_CONVERTER_H + +#include "device.h" + +/// Класс Тягового Преобразователя +class TractionConverter : public Device +{ + +public: + + /// Конструктор + TractionConverter(QObject *parent = Q_NULLPTR); + + /// Деструктор + ~TractionConverter(); + + /// Установить напряжение с тяговых обмоток + void setUt(double Ut, size_t i); + + /// Установить напряжение постоянного тока + void setUdcIn(double Udc_in); + + /// Получить напряжение на преобразователь собственных нужд + double getU4(size_t i); + +private: + + /// Напряжение с тяговых обмоток + std::array Ut; + + /// Напряжение постоянного тока + double Udc_in; + + /// Напряжение с выхода 4QS-преобразователя + std::array U4QS; + + /// Коэффициент 4QS-преобразователя + double K4QS; + + /// Напряжение звена постоянного тока + std::array Udc; + + /// Напряжение преобразователя собственных нужд + std::array U4; + + /// Предварительный шаг + void preStep(state_vector_t &Y, double t); + + /// Вычисление напряжения + void ode_system(const state_vector_t &Y, state_vector_t &dYdt, double t); + + /// Загрузка конфига + void load_config(CfgReader &cfg); + +}; + +#endif // TRACTIONCONVERTER_H diff --git a/addons/ep20/ep20/include/traction-transformer.h b/addons/ep20/ep20/include/traction-transformer.h new file mode 100644 index 00000000..d94e949e --- /dev/null +++ b/addons/ep20/ep20/include/traction-transformer.h @@ -0,0 +1,56 @@ +#ifndef TRACTION_TRANSFORMER_H +#define TRACTION_TRANSFORMER_H + +#include "device.h" + + +/// Класс Тягового Трансформатора +class TractionTransformer : public Device +{ + +public: + + /// Конструктор + TractionTransformer(QObject *parent = Q_NULLPTR); + + /// Деструктор + ~TractionTransformer(); + + /// Установить напряжение с выхода ГВ + void setU1(double U1); + + /// Получить напряжение тяговой обмотки + double getTractionVoltage(size_t i); + + /// Получить напряжение обмотки отопления + double getVoltageHeatingCoil(); + +private: + + /// Напряжение с выхода ГВ + double U1; + + /// Коэффициент тяговой обмотки + double traction_coefficient; + + /// Коэффициент обмотки отопления + double heating_coil_coefficient; + + /// Катушка обмотки отопления + double winding_coils_heating; + + /// Катушки тяговой обмотки + std::array traction_winding_coils; + + /// Предварительный шаг + void preStep(state_vector_t &Y, double t); + + /// Вычисление напряжения + void ode_system(const state_vector_t &Y, state_vector_t &dYdt, double t); + + /// Загрузка конфига + void load_config(CfgReader &cfg); + +}; + +#endif // TRACTIONTRANSFORMER_H diff --git a/addons/ep20/ep20/scripts/loco-windeploy.bat b/addons/ep20/ep20/scripts/loco-windeploy.bat new file mode 100644 index 00000000..180338a1 --- /dev/null +++ b/addons/ep20/ep20/scripts/loco-windeploy.bat @@ -0,0 +1,25 @@ +set DEPLOY_DIR=%1 + +set LOCO_NAME=ep20 + +mkdir %DEPLOY_DIR% +mkdir %DEPLOY_DIR%\modules + +mkdir %DEPLOY_DIR%\cfg +mkdir %DEPLOY_DIR%\cfg\vehicles\ +mkdir %DEPLOY_DIR%\cfg\trains\ + +rem mkdir %DEPLOY_DIR%\data +rem mkdir %DEPLOY_DIR%\data\animations\ +rem mkdir %DEPLOY_DIR%\data\models\ +rem mkdir %DEPLOY_DIR%\data\sounds\ + +set SOURCE_DIR=..\..\..\..\.. + +xcopy /S %SOURCE_DIR%\modules\%LOCO_NAME%\*.dll %DEPLOY_DIR%\modules\%LOCO_NAME%\ +xcopy /S %SOURCE_DIR%\cfg\vehicles\%LOCO_NAME%\*.* %DEPLOY_DIR%\cfg\vehicles\%LOCO_NAME%\ +copy %SOURCE_DIR%\cfg\trains\%LOCO_NAME%.xml %DEPLOY_DIR%\cfg\trains\%LOCO_NAME%.xml + +xcopy /S %SOURCE_DIR%\data\animations\%LOCO_NAME%\*.* %DEPLOY_DIR%\data\animations\%LOCO_NAME%\ +xcopy /S %SOURCE_DIR%\data\models\%LOCO_NAME%\*.* %DEPLOY_DIR%\data\models\%LOCO_NAME%\ +xcopy /S %SOURCE_DIR%\data\sounds\%LOCO_NAME%\*.* %DEPLOY_DIR%\data\sounds\%LOCO_NAME%\ \ No newline at end of file diff --git a/addons/ep20/ep20/src/ac-motor-compressor.cpp b/addons/ep20/ep20/src/ac-motor-compressor.cpp new file mode 100644 index 00000000..537b5f84 --- /dev/null +++ b/addons/ep20/ep20/src/ac-motor-compressor.cpp @@ -0,0 +1,106 @@ +#include "ac-motor-compressor.h" + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +ACMotorCompressor::ACMotorCompressor(QObject *parent) : Device(parent) + , p(0.0) + , Q(0.0) + , p0(1.5) + , Mmax(455.8) + , s_kr(0.154) + , Un(380.0) + , U_power(0.0) + , omega0(157.08) + , J(0.1) + , Mxx(110.0) + , Vnk(0.05) + +{ + std::fill(K.begin(), K.end(), 0); +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +ACMotorCompressor::~ACMotorCompressor() +{ + +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void ACMotorCompressor::setExternalPressure(double press) +{ + p = press; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +double ACMotorCompressor::getAirFlow() const +{ + return Q; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void ACMotorCompressor::setU_power(double value) +{ + U_power = value; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void ACMotorCompressor::preStep(state_vector_t &Y, double t) +{ + Q_UNUSED(t) + + Q = K[4] * pf(Y[1] - p); + + emit soundSetPitch("Motor_Compressor", static_cast(Y[0] / omega0)); +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void ACMotorCompressor::ode_system(const state_vector_t &Y, + state_vector_t &dYdt, + double t) +{ + Q_UNUSED(t) + + // Расчитывает текущее скольжение ротора + double s = 1 - Y[0] / omega0; + + // Рачитываем максимальный момент при данном напряжении питания + double M_maximal = Mmax * pow(U_power / Un, 2.0); + + // Расчитываем электромагнитный момент (формула Клосса) + double Ma = 2 * M_maximal / ( s / s_kr + s_kr / s ); + + double Mr = Physics::fricForce(Mxx, Y[0]); + + double Qnk = K[1] * Y[0] - K[2] * Y[1] - K[3] * pf(Y[1] - p); + + dYdt[0] = (Ma - Mr) / J; + + dYdt[1] = Qnk / Vnk; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void ACMotorCompressor::load_config(CfgReader &cfg) +{ + QString secName = "Device"; + + for (size_t i = 1; i < K.size(); ++i) + { + QString coeff = QString("K%1").arg(i); + cfg.getDouble(secName, coeff, K[i]); + } +} diff --git a/addons/ep20/ep20/src/auxiliary-converter.cpp b/addons/ep20/ep20/src/auxiliary-converter.cpp new file mode 100644 index 00000000..658548f7 --- /dev/null +++ b/addons/ep20/ep20/src/auxiliary-converter.cpp @@ -0,0 +1,85 @@ +#include "auxiliary-converter.h" + + +//------------------------------------------------------------------------------ +// Конструктор +//------------------------------------------------------------------------------ +AuxiliaryConverter::AuxiliaryConverter(QObject *parent) : Device (parent) + ,U4(0) + ,Fref(1) + ,Uref(1) + ,Koef(0.1267) + ,U1(0) + ,F(0) + ,U2(0) +{ + +} + +//------------------------------------------------------------------------------ +// Деструктор +//------------------------------------------------------------------------------ +AuxiliaryConverter::~AuxiliaryConverter() +{ + +} + +//------------------------------------------------------------------------------ +// Установить значение от ПСН +//------------------------------------------------------------------------------ +void AuxiliaryConverter::setU4(double U4) +{ + this->U4 = U4; +} + +//------------------------------------------------------------------------------ +// Получить значение напряжения +//------------------------------------------------------------------------------ +double AuxiliaryConverter::getU1() +{ + return U1; +} + +//------------------------------------------------------------------------------ +// Получить значение частоты +//------------------------------------------------------------------------------ +double AuxiliaryConverter::getF() +{ + return F; +} + +//------------------------------------------------------------------------------ +// Получить значение напряжения 380 +//------------------------------------------------------------------------------ +double AuxiliaryConverter::getU2() +{ + return U2; +} + +//------------------------------------------------------------------------------ +// Пердварительные шаги +//------------------------------------------------------------------------------ +void AuxiliaryConverter::preStep(state_vector_t &Y, double t) +{ + U1 = Uref; + + F = Fref; + + U2 = Koef * U4; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void AuxiliaryConverter::ode_system(const state_vector_t &Y, state_vector_t &dYdt, double t) +{ + +} + +//------------------------------------------------------------------------------ +// Загрузка конфига +//------------------------------------------------------------------------------ +void AuxiliaryConverter::load_config(CfgReader &cfg) +{ + +} diff --git a/addons/ep20/ep20/src/ep20-brake-mech.cpp b/addons/ep20/ep20/src/ep20-brake-mech.cpp new file mode 100644 index 00000000..8ebacfc7 --- /dev/null +++ b/addons/ep20/ep20/src/ep20-brake-mech.cpp @@ -0,0 +1,46 @@ +#include "ep20-brake-mech.h" + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +EP20BrakeMech::EP20BrakeMech(QObject *parent) + : BrakeMech(parent) +{ + +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +EP20BrakeMech::~EP20BrakeMech() +{ + +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void EP20BrakeMech::load_config(CfgReader &cfg) +{ + QString secName = "Device"; + + cfg.getString(secName, "ShoeType", shoeType); + cfg.getInt(secName, "ShoesCyl", shoesCyl); + cfg.getInt(secName, "ShoesAxis", shoesAxis); + cfg.getInt(secName, "CylNum", cylNum); + cfg.getDouble(secName, "DeadVolume", V0); + + cfg.getDouble(secName, "CylinderDiameter", cylDiam); + S = Physics::PI * cylDiam * cylDiam / 4.0; + + cfg.getDouble(secName, "MechCoeff", ip); + cfg.getDouble(secName, "StockOut", Lmax); + cfg.getDouble(secName, "SpringForce", F0); + + cfg.getDouble(secName, "effRadius", effRadius); + + double p_cyl_begin = 0.0; + cfg.getDouble(secName, "InitPressure", p_cyl_begin); + + setY(0, p_cyl_begin); +} diff --git a/addons/ep20/ep20/src/ep20-signals-output.cpp b/addons/ep20/ep20/src/ep20-signals-output.cpp new file mode 100644 index 00000000..3bfa77d8 --- /dev/null +++ b/addons/ep20/ep20/src/ep20-signals-output.cpp @@ -0,0 +1,12 @@ +#include "ep20.h" + +void EP20::stepSignals() +{ + analogSignal[STRELKA_pTM] = static_cast(pTM / 1.0); + analogSignal[STRELKA_pGR] = static_cast(main_reservoir->getPressure() / 1.6); + analogSignal[STRELKA_pTC] = static_cast(brake_mech[FWD_TROLLEY]->getBrakeCylinderPressure() / 1.6); + analogSignal[STRELKA_pUR] = static_cast(krm->getEqReservoirPressure() / 1.0); + + analogSignal[RUK_KRM130] = krm->getHandlePosition(); + analogSignal[RUK_KVT224] = static_cast(kvt->getHandlePosition()); +} diff --git a/addons/ep20/ep20/src/ep20.cpp b/addons/ep20/ep20/src/ep20.cpp index faf9e3c1..a6b7d223 100644 --- a/addons/ep20/ep20/src/ep20.cpp +++ b/addons/ep20/ep20/src/ep20.cpp @@ -1,15 +1,17 @@ -#include "ep20.h" + #include "ep20.h" #include #include +#include "filesystem.h" + //------------------------------------------------------------------------------ // Конструктор //------------------------------------------------------------------------------ EP20::EP20() { - Uks = 3000.0; - current_kind = 2; + Uks = 25000.0; + current_kind = 1; } //------------------------------------------------------------------------------ @@ -20,16 +22,34 @@ EP20::~EP20() } +void EP20::initBrakeDevices(double p0, double pTM, double pFL) +{ + main_reservoir->setY(0, pFL); + charge_press = p0; + + load_brakes_config(config_dir + QDir::separator() + "brakes-init.xml"); + + krm->init(pTM, pFL); + kvt->init(pTM, pFL); + spareReservoir->setY(0, pTM); +} + //------------------------------------------------------------------------------ // Инициализация //------------------------------------------------------------------------------ void EP20::initialization() { + FileSystem &fs = FileSystem::getInstance(); + QString modules_dir(fs.getModulesDir().c_str()); + // Вызваем метод initMPCS(); // Вызываем метод initHighVoltageScheme(); + + // Вызываем метод + initBrakeControls(modules_dir); } //------------------------------------------------------------------------------ @@ -64,11 +84,66 @@ void EP20::initHighVoltageScheme() mainSwitch = new ProtectiveDevice(); fastSwitch = new ProtectiveDevice(); + + tractionTrans = new TractionTransformer(); + + for (size_t i = 0; i < trac_conv.size(); ++i) + trac_conv[i] = new TractionConverter(); + + for (size_t i = 0; i read_custom_config(config_dir + QDir::separator() + "ac-motor-compressor"); + } +} + +void EP20::initBrakeControls(QString modules_dir) +{ + krm = loadBrakeCrane(modules_dir + QDir::separator() + "krm130"); + krm->read_config("krm130"); + + kvt = loadLocoCrane(modules_dir + QDir::separator() + "kvt224"); + kvt->read_config("kvt224"); + + zpk = new SwitchingValve(); + zpk->read_config("zpk"); + + airDistr = loadAirDistributor(modules_dir + QDir::separator() + "vr242"); + airDistr->read_config("vr242"); + + electroAirDistr = loadElectroAirDistributor(modules_dir + QDir::separator() + "evr305"); + electroAirDistr->read_config("evr305"); + + for (size_t i = 0; i < brake_mech.size(); ++i) + { + brake_mech[i] = new EP20BrakeMech(); + rd304[i] = new PneumoReley(); + rd304[i]->read_config("rd304"); + } + + brake_mech[FWD_TROLLEY]->read_custom_config(config_dir + QDir::separator() + "fwd-trolley-brake-mech"); + brake_mech[MDL_TROLLEY]->read_custom_config(config_dir + QDir::separator() + "mdl-trolley-brake-mech"); + brake_mech[BWD_TROLLEY]->read_custom_config(config_dir + QDir::separator() + "bwd-trolley-brake-mech"); + + pSplit[0] = new PneumoSplitter(); + pSplit[1] = new PneumoSplitter(); + + pSplit[0]->read_config("pneumo-splitter"); + pSplit[1]->read_config("pneumo-splitter"); } + //------------------------------------------------------------------------------ // Общие шаги моделирования //------------------------------------------------------------------------------ + void EP20::step(double t, double dt) { // Вызываем метод @@ -77,13 +152,31 @@ void EP20::step(double t, double dt) // Вызываем метод stepHighVoltageScheme(t, dt); + stepBrakeControls(t, dt); + // Выводим на экран симулятор, высоту подъема/спуска, выходное напряжение, род ток! - DebugMsg = QString("t: %1 s, UoutDC: %2, UoutAC: %3, MainSwitch: %4, FastSwitch: %5") + DebugMsg = QString("t: %1 s, U2_4: %2, Q: %3, pUR: %4, pTM: %5, KrM: %6, pTC_2: %7, pTC_1: %8 pZR: %9 pos: %10") .arg(t, 10, 'f', 2) - .arg(kindSwitch->getUoutDC(), 4, 'f', 2) - .arg(kindSwitch->getUoutAC(), 4, 'f', 2) - .arg(mainSwitch->getU_out(), 4, 'f', 2) - .arg(fastSwitch->getU_out(), 4, 'f', 2); + .arg(auxConv[3]->getU2(), 5, 'f', 1) + .arg(main_reservoir->getPressure(), 4, 'f', 2) + .arg(krm->getEqReservoirPressure(), 4, 'f', 2) + .arg(pTM, 4, 'f', 2) + .arg(krm->getPositionName(), 4) + .arg(brake_mech[FWD_TROLLEY]->getBrakeCylinderPressure(), 4, 'f', 2) + .arg(brake_mech[BWD_TROLLEY]->getBrakeCylinderPressure(), 4, 'f', 2) + .arg(spareReservoir->getPressure(), 4, 'f', 2) + .arg(kvt->getHandlePosition(), 4, 'f', 2); + + stepSignals(); + //________________________________________________ + +// .arg(t, 10, 'f', 2) +// .arg(kindSwitch->getUoutDC(), 4, 'f', 2) +// .arg(kindSwitch->getUoutAC(), 4, 'f', 2) +// .arg(mainSwitch->getU_out(), 4, 'f', 2) +// .arg(fastSwitch->getU_out(), 4, 'f', 2) +// .arg(tractionTrans->getTractionVoltage(0)) +// .arg(auxConv[1]->getU2()); } //------------------------------------------------------------------------------ @@ -134,14 +227,157 @@ void EP20::stepHighVoltageScheme(double t, double dt) kindSwitch->setState(current_kind - 1); kindSwitch->step(t, dt); - // Передаем данные для ГВ + // Передаем данные для ГВ/БВ mainSwitch->setU_in(kindSwitch->getUoutAC()); fastSwitch->setU_in(kindSwitch->getUoutDC()); -// mainSwitch->setState(); -// fastSwitch->setState(); + + + // Передаем данные для ГВ + mpcsInput.Uin_ms = kindSwitch->getUoutAC(); + mpcsInput.current_kind_switch_state = current_kind - 1; + mpcsInput.isOff_fs = fastSwitch->getState(); + mainSwitch->setReturn(true); + mainSwitch->setHoldingCoilState(true); + mainSwitch->setState(mpcsOutput.turn_on_ms); + + // Передаем данные для БВ + mpcsInput.Uin_fs = kindSwitch->getUoutDC(); + mpcsInput.current_kind_switch_state = current_kind - 1; + mpcsInput.isOff_ms = mainSwitch->getState(); + fastSwitch->setReturn(true); + fastSwitch->setHoldingCoilState(true); + fastSwitch->setState(mpcsOutput.turn_on_fs); mainSwitch->step(t, dt); fastSwitch->step(t, dt); + + // Передаем данные для тягового трансформатора + tractionTrans->setU1(mainSwitch->getU_out()); + tractionTrans->step(t, dt); + + // Передаем данные для тягового преобразователя + for (size_t i = 0; i < trac_conv.size(); ++i) + { + trac_conv[i]->setUdcIn(fastSwitch->getU_out()); + trac_conv[i]->setUt(tractionTrans->getTractionVoltage(2 * i), 0); + trac_conv[i]->setUt(tractionTrans->getTractionVoltage(2 * i + 1), 1); + trac_conv[i]->step(t, dt); + } + + // Передаем данные для преобразователя собственных нужд + auxConv[0]->setU4(trac_conv[0]->getU4(0)); + auxConv[1]->setU4(trac_conv[1]->getU4(0)); + auxConv[2]->setU4(trac_conv[1]->getU4(1)); + auxConv[3]->setU4(trac_conv[2]->getU4(0)); + for (size_t i = 0; i < auxConv.size(); ++i) + { + mpcsInput.aux_const_U[i] = auxConv[i]->getU2(); + auxConv[i]->step(t, dt); + } + + // Передаем данные на Мотор-компрессоры и Главный резервуар! + main_reservoir->setAirFlow(motorCompAC[0]->getAirFlow() + motorCompAC[1]->getAirFlow()); + main_reservoir->step(t, dt); + + mpcsInput.PressMR = main_reservoir->getPressure(); + + for(size_t i = 0; i < motorCompAC.size(); ++i) + { + motorCompAC[i]->setExternalPressure(main_reservoir->getPressure()); + motorCompAC[i]->setU_power(auxConv[3]->getU2() * static_cast(mpcsOutput.toggleSwitchMK[i]) * mpcsOutput.MKstate); + motorCompAC[i]->step(t, dt); + } +} + +void EP20::stepBrakeControls(double t, double dt) +{ + krm->setChargePressure(charge_press); + krm->setFeedLinePressure(main_reservoir->getPressure()); + krm->setBrakePipePressure(pTM); + krm->setControl(keys); + krm->step(t, dt); + + p0 = krm->getBrakePipeInitPressure(); + + kvt->setFeedlinePressure(main_reservoir->getPressure()); + kvt->setBrakeCylinderPressure(zpk->getPressure2()); + kvt->setControl(keys); + kvt->step(t, dt); + + zpk->setInputFlow1(electroAirDistr->getQbc_out()); + zpk->setInputFlow2(kvt->getBrakeCylinderFlow()); + zpk->setOutputPressure(pSplit[0]->getP_in()); + zpk->step(t, dt); + +// electroAirDistr->setPbc_in(airSplit->getP_in()); + + electroAirDistr->setPbc_in(zpk->getPressure1()); + + // Устанавливаем подачу давления с запасного резервуара + electroAirDistr->setSupplyReservoirPressure(spareReservoir->getPressure()); + + // Устанавливаем входной поток воздуха Qзр + electroAirDistr->setInputSupplyReservoirFlow(airDistr->getAirSupplyFlow()); + // Устанавливаем воздушный поток Qтц + electroAirDistr->setQbc_in(airDistr->getBrakeCylinderAirFlow()); + +// electroAirDistr->setControlLine(handleEDT->getControlSignal() + ept_control[0]); + electroAirDistr->step(t, dt); + + + + spareReservoir->setAirFlow(electroAirDistr->getOutputSupplyReservoirFlow()); + spareReservoir->step(t, dt); + + + + airDistr->setAirSupplyPressure(electroAirDistr->getSupplyReservoirPressure()); + airDistr->setBrakeCylinderPressure(electroAirDistr->getPbc_out()); + airDistr->setBrakepipePressure(pTM); + airDistr->step(t, dt); + + pSplit[0]->setQ_in(zpk->getOutputFlow()); + pSplit[0]->setP_out1(rd304[FWD_TROLLEY]->getWorkPressure()); + pSplit[0]->setP_out2(pSplit[1]->getP_in()); + pSplit[0]->step(t, dt); + + pSplit[1]->setQ_in(pSplit[0]->getQ_out2()); + pSplit[1]->setP_out1(rd304[MDL_TROLLEY]->getWorkPressure()); + pSplit[1]->setP_out2(rd304[BWD_TROLLEY]->getWorkPressure()); + pSplit[1]->step(t, dt); + + rd304[FWD_TROLLEY]->setWorkAirFlow(pSplit[0]->getQ_out1()); + rd304[FWD_TROLLEY]->setPipelinePressure(main_reservoir->getPressure()); + rd304[FWD_TROLLEY]->setBrakeCylPressure(brake_mech[FWD_TROLLEY]->getBrakeCylinderPressure()); + rd304[FWD_TROLLEY]->step(t, dt); + + rd304[MDL_TROLLEY]->setWorkAirFlow(pSplit[1]->getQ_out1()); + rd304[MDL_TROLLEY]->setPipelinePressure(main_reservoir->getPressure()); + rd304[MDL_TROLLEY]->setBrakeCylPressure(brake_mech[MDL_TROLLEY]->getBrakeCylinderPressure()); + rd304[MDL_TROLLEY]->step(t, dt); + + rd304[BWD_TROLLEY]->setWorkAirFlow(pSplit[1]->getQ_out2()); + rd304[BWD_TROLLEY]->setPipelinePressure(main_reservoir->getPressure()); + rd304[BWD_TROLLEY]->setBrakeCylPressure(brake_mech[BWD_TROLLEY]->getBrakeCylinderPressure()); + rd304[BWD_TROLLEY]->step(t, dt); + + brake_mech[FWD_TROLLEY]->setAirFlow(rd304[FWD_TROLLEY]->getBrakeCylAirFlow()); + brake_mech[FWD_TROLLEY]->step(t, dt); + + brake_mech[MDL_TROLLEY]->setAirFlow(rd304[MDL_TROLLEY]->getBrakeCylAirFlow()); + brake_mech[MDL_TROLLEY]->step(t, dt); + + brake_mech[BWD_TROLLEY]->setAirFlow(rd304[BWD_TROLLEY]->getBrakeCylAirFlow()); + brake_mech[BWD_TROLLEY]->step(t, dt); + + Q_r[1] = brake_mech[FWD_TROLLEY]->getBrakeTorque(); + Q_r[2] = brake_mech[FWD_TROLLEY]->getBrakeTorque(); + + Q_r[3] = brake_mech[MDL_TROLLEY]->getBrakeTorque(); + Q_r[4] = brake_mech[MDL_TROLLEY]->getBrakeTorque(); + + Q_r[5] = brake_mech[BWD_TROLLEY]->getBrakeTorque(); + Q_r[6] = brake_mech[BWD_TROLLEY]->getBrakeTorque(); } //------------------------------------------------------------------------------ @@ -157,9 +393,57 @@ void EP20::loadConfig(QString cfg_path) } } +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ void EP20::keyProcess() { -// pantograph[PANT_AC1]->setState(getKeyState(KEY_P)); + // pantograph[PANT_AC1]->setState(getKeyState(KEY_P)); +} + +void EP20::load_brakes_config(QString path) +{ + CfgReader cfg; + + if (cfg.load(path)) + { + QString secName = "BrakesState"; + + double pFL = 0.0; + + if (cfg.getDouble(secName, "MainReservoirPressure", pFL)) + { + main_reservoir->setY(0, pFL); + } + + double k_flow = 0.0; + + if (cfg.getDouble(secName, "MainReservoirFlow", k_flow)) + { + main_reservoir->setFlowCoeff(k_flow); + } + + double ch_press = 0.0; + + if (cfg.getDouble(secName, "ChargingPressure", ch_press)) + { + charge_press = ch_press; + } + + int train_crane_pos = 6; + + if (cfg.getInt(secName, "TrainCranePos", train_crane_pos)) + { + krm->setPosition(train_crane_pos); + } + + int loco_crane_pos = 0; + + /*if (cfg.getInt(secName, "LocoCranePos", loco_crane_pos)) + { + loco_crane->setHandlePosition(loco_crane_pos); + }*/ + } } GET_VEHICLE(EP20) diff --git a/addons/ep20/ep20/src/mpcs-task.cpp b/addons/ep20/ep20/src/mpcs-task.cpp index 7b9d776f..60f83b02 100644 --- a/addons/ep20/ep20/src/mpcs-task.cpp +++ b/addons/ep20/ep20/src/mpcs-task.cpp @@ -1,20 +1,32 @@ #include "mpcs-task.h" +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ Task::Task(QObject *parent) : QObject (parent) { } +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ Task::~Task() { } +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ void Task::init() { } +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ void Task::step(state_vector_t &Y, double t, double dt, const mpcs_input_t &mpcs_input, mpcs_output_t &mpcs_output) diff --git a/addons/ep20/ep20/src/mpcs.cpp b/addons/ep20/ep20/src/mpcs.cpp index 4847c5a7..f90640ca 100644 --- a/addons/ep20/ep20/src/mpcs.cpp +++ b/addons/ep20/ep20/src/mpcs.cpp @@ -10,7 +10,18 @@ //------------------------------------------------------------------------------ MPCS::MPCS(QObject *parent) : Device(parent) { + p_prev = 0; + p_min = 0.75; + + p_max = 0.9; + + std:fill(mk_start.begin(), mk_start.end(), 0); + + mkStartTimer.setTimeout(1.0); + connect(&mkStartTimer, &Timer::process, this, &MPCS::slotMKStart); + + mk_count = 0; } //------------------------------------------------------------------------------ @@ -22,25 +33,36 @@ MPCS::~MPCS() } //------------------------------------------------------------------------------ -// +// Инициализация //------------------------------------------------------------------------------ void MPCS::init() { taskPant = new TaskPant(); taskPant->init(); + + auxConv = new AuxiliaryConverter(); } +//------------------------------------------------------------------------------ +// Установить входной сигнал МПСУ +//------------------------------------------------------------------------------ void MPCS::setSignalInputMPCS(const mpcs_input_t &mpcs_input) { this->mpcs_input = mpcs_input; } +//------------------------------------------------------------------------------ +// Установить путь к файлу +//------------------------------------------------------------------------------ void MPCS::setStoragePath(QString path) { pathStorage = path; } +//------------------------------------------------------------------------------ +// Получить выходной сигнал МПСУ +//------------------------------------------------------------------------------ mpcs_output_t MPCS::getSignalOutputMPCS() { return mpcs_output; @@ -74,19 +96,108 @@ void MPCS::stepKeysControl(double t, double dt) taskPant->setControlSignal(FORWARD_DOWN, true); } } + + if (getKeyState(KEY_P)) + { + if (isShift()) + ms_fs_on.set(); + else + ms_fs_on.reset(); + } + } +//------------------------------------------------------------------------------ +// Шаг +//------------------------------------------------------------------------------ void MPCS::stepDiscrete(double t, double dt) { taskPant->step(y, t, dt, mpcs_input, mpcs_output); + + stepMainSwitchControl(t, dt); + + stepFastSwitchControl(t, dt); + + stepToggleSwitchMK(t, dt); +} + +//------------------------------------------------------------------------------ +// Шаг контроля ГВ +//------------------------------------------------------------------------------ +void MPCS::stepMainSwitchControl(double t, double dt) +{ + mpcs_output.turn_on_ms = ms_fs_on.getState(); + mpcs_output.turn_on_ms = mpcs_output.turn_on_ms && mpcs_input.isOff_fs; + mpcs_output.turn_on_ms = mpcs_output.turn_on_ms && (mpcs_input.current_kind_switch_state == 0); + mpcs_output.turn_on_ms = mpcs_output.turn_on_ms && (mpcs_input.Uin_ms >= 19000.0) + && (mpcs_input.Uin_ms <= 29000.0); +} + +//------------------------------------------------------------------------------ +// Шаг контроля БВ +//------------------------------------------------------------------------------ +void MPCS::stepFastSwitchControl(double t, double dt) +{ + mpcs_output.turn_on_fs = ms_fs_on.getState(); + mpcs_output.turn_on_fs = mpcs_output.turn_on_fs && mpcs_input.isOff_ms; + mpcs_output.turn_on_fs = mpcs_output.turn_on_fs && (mpcs_input.current_kind_switch_state == 1); + mpcs_output.turn_on_fs = mpcs_output.turn_on_fs && (mpcs_input.Uin_fs >= 2200.0) + && (mpcs_input.Uin_fs <= 4000.0); } +//------------------------------------------------------------------------------ +// Шаг контроля MK +//------------------------------------------------------------------------------ +void MPCS::stepToggleSwitchMK(double t, double dt) +{ + bool is_all_mk_started = true; + + for (size_t i = 0; i < mpcs_output.toggleSwitchMK.size(); ++i) + { + is_all_mk_started = is_all_mk_started && static_cast(mk_start[i]); + mpcs_output.toggleSwitchMK[i] = static_cast(mk_start[i]); + } + + if ( (mpcs_input.aux_const_U[3] >= 300.0)) + { + if (!mkStartTimer.isStarted() && !is_all_mk_started) + { + mk_count = 0; + mkStartTimer.start(); + } + } + + mkStartTimer.step(t, dt); +} + +void MPCS::PressureReg() +{ + double dp = mpcs_input.PressMR - p_prev; + + if (mpcs_input.PressMR < p_min) + mpcs_output.MKstate = 1.0; + + if (mpcs_input.PressMR > p_max) + mpcs_output.MKstate = 0.0; + + if ( (mpcs_input.PressMR >= p_min) && (mpcs_input.PressMR <= p_max) ) + { + mpcs_output.MKstate = hs_p(dp); + } +} + + //------------------------------------------------------------------------------ // Пердварительные шаги //------------------------------------------------------------------------------ void MPCS::preStep(state_vector_t &Y, double t) { + PressureReg(); +} +void MPCS::postStep(state_vector_t &Y, double t) +{ + p_prev = mpcs_input.PressMR; } //------------------------------------------------------------------------------ @@ -104,3 +215,16 @@ void MPCS::load_config(CfgReader &cfg) { } + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void MPCS::slotMKStart() +{ + mk_start[mk_count] = 1; + + mk_count++; + + if (mk_count == 2) + mkStartTimer.stop(); +} diff --git a/addons/ep20/ep20/src/traction-converter.cpp b/addons/ep20/ep20/src/traction-converter.cpp new file mode 100644 index 00000000..f05a0b48 --- /dev/null +++ b/addons/ep20/ep20/src/traction-converter.cpp @@ -0,0 +1,80 @@ +#include "traction-converter.h" + +//------------------------------------------------------------------------------ +// Конструктор +//------------------------------------------------------------------------------ +TractionConverter::TractionConverter(QObject *parent) : Device (parent) + ,Udc_in(0) + ,K4QS(1.808) +{ + std::fill(Ut.begin(), Ut.end(), 0); + std::fill(U4QS.begin(), U4QS.end(), 0); + std::fill(Udc.begin(), Udc.end(), 0); + std::fill(U4.begin(), U4.end(), 0); +} + +//------------------------------------------------------------------------------ +// Деструктор +//------------------------------------------------------------------------------ +TractionConverter::~TractionConverter() +{ + +} + +//------------------------------------------------------------------------------ +// Установить напряжение с тяговых обмоток +//------------------------------------------------------------------------------ +void TractionConverter::setUt(double Ut, size_t i) +{ + if (i < this->Ut.size()) + this->Ut[i] = Ut; +} + +//------------------------------------------------------------------------------ +// Установить напряжение постоянного тока +//------------------------------------------------------------------------------ +void TractionConverter::setUdcIn(double Udc_in) +{ + this->Udc_in = Udc_in; +} + +//------------------------------------------------------------------------------ +// Получить напряжение ПСН +//------------------------------------------------------------------------------ +double TractionConverter::getU4(size_t i) +{ + if (i < U4.size()) + return U4[i]; + else + return 0; +} + +//------------------------------------------------------------------------------ +// Предварительные шаги +//------------------------------------------------------------------------------ +void TractionConverter::preStep(state_vector_t &Y, double t) +{ + + for (size_t i = 0; i < U4QS.size(); ++i) + { + U4QS[i] = K4QS * Ut[i]; + Udc[i] = max(U4QS[i], Udc_in); + U4[i] = Udc[i]; + } +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void TractionConverter::ode_system(const state_vector_t &Y, state_vector_t &dYdt, double t) +{ + +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void TractionConverter::load_config(CfgReader &cfg) +{ + +} diff --git a/addons/ep20/ep20/src/traction-transformer.cpp b/addons/ep20/ep20/src/traction-transformer.cpp new file mode 100644 index 00000000..f673c664 --- /dev/null +++ b/addons/ep20/ep20/src/traction-transformer.cpp @@ -0,0 +1,81 @@ +#include "traction-transformer.h" + +//------------------------------------------------------------------------------ +// Конструктор +//------------------------------------------------------------------------------ +TractionTransformer::TractionTransformer(QObject *parent) : Device (parent) + ,U1(0) + ,traction_coefficient(15.07) + ,heating_coil_coefficient(8.33) + ,winding_coils_heating(0) +{ + std::fill(traction_winding_coils.begin(), traction_winding_coils.end(), 0); +} + +//------------------------------------------------------------------------------ +// Деструктор +//------------------------------------------------------------------------------ +TractionTransformer::~TractionTransformer() +{ + +} + +//------------------------------------------------------------------------------ +// Установить напряжение с выхода ГВ +//------------------------------------------------------------------------------ +void TractionTransformer::setU1(double U1) +{ + this->U1 = U1; +} + +//------------------------------------------------------------------------------ +// Получить напряжение тяговой обмотки +//------------------------------------------------------------------------------ +double TractionTransformer::getTractionVoltage(size_t i) +{ + if (i < traction_winding_coils.size()) + { + return traction_winding_coils[i]; + } + else + { + return 0; + } +} + +//------------------------------------------------------------------------------ +// Получить напряжение обмотки отопления +//------------------------------------------------------------------------------ +double TractionTransformer::getVoltageHeatingCoil() +{ + return winding_coils_heating; +} + +//------------------------------------------------------------------------------ +// Предварительные шаги +//------------------------------------------------------------------------------ +void TractionTransformer::preStep(state_vector_t &Y, double t) +{ + for (size_t i = 0; i < traction_winding_coils.size(); ++i) + { + traction_winding_coils[i] = U1 / traction_coefficient; + } + + winding_coils_heating = U1 / heating_coil_coefficient; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void TractionTransformer::ode_system(const state_vector_t &Y, state_vector_t &dYdt, double t) +{ + +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void TractionTransformer::load_config(CfgReader &cfg) +{ + +} diff --git a/cfg/control-panel.xml b/cfg/control-panel.xml deleted file mode 100644 index e8e2f81e..00000000 --- a/cfg/control-panel.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - modbus - vehicles/chs2t/modbus - 0 - 50 - - diff --git a/cfg/devices/krm130.xml b/cfg/devices/krm130.xml new file mode 100644 index 00000000..51a4964c --- /dev/null +++ b/cfg/devices/krm130.xml @@ -0,0 +1,52 @@ + + + + + 6 + 0.02 + 1e-4 + 1e-4 + + + 1e-6 + + + 0.0368e-4 + + + + 0.5e-3 + + + + 3e-1 + + + 2.5e-4 + + + 0.1e-3 + + + 0.7e-3 + + + 0.1e-3 + + + 1e-1 + + + 1e-3 + + 100.0 + 1.3 + 1.0 + 10.0 + + 1.0 + + 10.0 + + + \ No newline at end of file diff --git a/cfg/devices/kvt224.xml b/cfg/devices/kvt224.xml new file mode 100644 index 00000000..f2f39cee --- /dev/null +++ b/cfg/devices/kvt224.xml @@ -0,0 +1,45 @@ + + + + + 3 + + 1e-4 + + 1e-4 + + 3e-4 + + + 1e-3 + + + 1.56e-3 + + 0.40 + + 12e-3 + + 5e-3 + + 0.4e-3 + + 1e-4 + + 1.0e-5 + + 10.0 + + 10.0 + + 0.1 + + 0.01 + + 0.0 0.13 0.20 0.30 0.40 + + 0.0 + 1.0 + + + \ No newline at end of file diff --git a/cfg/vehicles/ep20/ac-motor-compressor.xml b/cfg/vehicles/ep20/ac-motor-compressor.xml new file mode 100644 index 00000000..81b305c3 --- /dev/null +++ b/cfg/vehicles/ep20/ac-motor-compressor.xml @@ -0,0 +1,18 @@ + + + + + 2 + + 0.001 + + 0.001 + + 0.01 + + 0.0005 + + 2.0 + + + diff --git a/cfg/vehicles/ep20/brakes-init.xml b/cfg/vehicles/ep20/brakes-init.xml new file mode 100644 index 00000000..28b920fb --- /dev/null +++ b/cfg/vehicles/ep20/brakes-init.xml @@ -0,0 +1,21 @@ + + + + + + 0.9 + + + 1.1e-4 + + + 0.5 + + + 2 + + + 1 + + + \ No newline at end of file diff --git a/cfg/vehicles/ep20/bwd-trolley-brake-mech.xml b/cfg/vehicles/ep20/bwd-trolley-brake-mech.xml new file mode 100644 index 00000000..8126ded3 --- /dev/null +++ b/cfg/vehicles/ep20/bwd-trolley-brake-mech.xml @@ -0,0 +1,16 @@ + + + + 1 + iron + 6 + 4 + 2 + 0.0 + 0.356 + 5.9 + 0.1 + 10082 + 0.0 + + \ No newline at end of file diff --git a/cfg/vehicles/ep20/ep20.xml b/cfg/vehicles/ep20/ep20.xml index 5056c434..24b8ab00 100644 --- a/cfg/vehicles/ep20/ep20.xml +++ b/cfg/vehicles/ep20/ep20.xml @@ -1,16 +1,23 @@ - - 129000 - 0 - 22.532 - 1.25 - default - 6 - 2.0 + + 54200 + 4500 + 25.0 + 0.95 + passcar + 4 + 5 + 2.0 + + ep20/EP20_2.osgt + ep20/Cab.osgt + + + 0.6 9.0 3.35 + + - - diff --git a/cfg/vehicles/ep20/fwd-trolley-brake-mech.xml b/cfg/vehicles/ep20/fwd-trolley-brake-mech.xml new file mode 100644 index 00000000..1fab2cbd --- /dev/null +++ b/cfg/vehicles/ep20/fwd-trolley-brake-mech.xml @@ -0,0 +1,17 @@ + + + + 1 + composite + 2 + 4 + 4 + 0.0 + 0.254 + 5.9 + 0.1 + 10082 + 0.5 + 0.0 + + \ No newline at end of file diff --git a/cfg/vehicles/ep20/mdl_trolley-brake-mech.xml b/cfg/vehicles/ep20/mdl_trolley-brake-mech.xml new file mode 100644 index 00000000..8126ded3 --- /dev/null +++ b/cfg/vehicles/ep20/mdl_trolley-brake-mech.xml @@ -0,0 +1,16 @@ + + + + 1 + iron + 6 + 4 + 2 + 0.0 + 0.356 + 5.9 + 0.1 + 10082 + 0.0 + + \ No newline at end of file diff --git a/simulator/device/include/pantograph.h b/simulator/device/include/pantograph.h index 86f56c7b..1cdc9af0 100644 --- a/simulator/device/include/pantograph.h +++ b/simulator/device/include/pantograph.h @@ -35,6 +35,7 @@ class DEVICE_EXPORT Pantograph : public Device /// Получить род на выходе int getCurrentKindOut() const; + bool isUp() const; bool isDown() const; diff --git a/simulator/device/include/protective-device.h b/simulator/device/include/protective-device.h index 475f3ef5..7923adf9 100644 --- a/simulator/device/include/protective-device.h +++ b/simulator/device/include/protective-device.h @@ -28,15 +28,19 @@ class DEVICE_EXPORT ProtectiveDevice : public Device float getLampState() const; + bool getState() const; + private: /// Напряжение на входе ГВ double U_in; + /// Напряжение на выходе ГВ double U_out; /// Сигнал включения ГВ bool is_on; + /// Возврат защиты bool is_return; diff --git a/simulator/device/src/protective-device.cpp b/simulator/device/src/protective-device.cpp index 25f5e414..8551d2ae 100644 --- a/simulator/device/src/protective-device.cpp +++ b/simulator/device/src/protective-device.cpp @@ -81,6 +81,11 @@ float ProtectiveDevice::getLampState() const return lamp_state; } +bool ProtectiveDevice::getState() const +{ + return static_cast(lamp_state); +} + //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ diff --git a/simulator/krm130/include/krm130.h b/simulator/krm130/include/krm130.h new file mode 100644 index 00000000..78648b23 --- /dev/null +++ b/simulator/krm130/include/krm130.h @@ -0,0 +1,143 @@ +#ifndef KRM130_H +#define KRM130_H + +#include "brake-crane.h" + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +enum +{ + MAX_FLOW_COEFFS = 14, + NUM_POSITIONS = 7 +}; + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +enum +{ + EC_PRESSURE = 2 +}; + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +enum +{ + POS_I = 0, + POS_II = 1, + POS_III = 2, + POS_IV = 3, + POS_Va = 4, + POS_V = 5, + POS_VI = 6 +}; + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +class BrakeCrane130 : public BrakeCrane +{ + Q_OBJECT + +public: + + BrakeCrane130(QObject *parent = Q_NULLPTR); + + ~BrakeCrane130(); + + void setPosition(int &position); + + QString getPositionName(); + + float getHandlePosition(); + + void init(double pTM, double pFL); + +private: + + double k_leek; + + double k_stab; + + double Vec; + + double A1; + + double k1; + + double k2; + + double k3; + + double k4; + + double T1; + + double T2; + + double K4_power; + + double Qbp; + + int old_input; + + int old_output; + + bool pulse_II; + + bool pulse_I; + + double t_old; + double dt; + + int handle_pos; + + double pos_angle; + + double pos_delay; + + int min_pos; + + int max_pos; + + double pos_duration; + + int dir; + + bool pos_switch; + + double tau; + + Timer *incTimer; + Timer *decTimer; + + DebugLog *debug_log; + + std::array K; + + std::array pos; + + QStringList positions_names; + + std::vector positions; + + void preStep(state_vector_t &Y, double t); + + void postStep(state_vector_t &Y, double t); + + void ode_system(const state_vector_t &Y, state_vector_t &dYdt, double t); + + void load_config(CfgReader &cfg); + + void stepKeysControl(double t, double dt); + +private slots: + + void inc(); + + void dec(); +}; + +#endif // KRM130_H diff --git a/simulator/krm130/krm130.pro b/simulator/krm130/krm130.pro new file mode 100644 index 00000000..3eb73478 --- /dev/null +++ b/simulator/krm130/krm130.pro @@ -0,0 +1,36 @@ +EFINES += DEVICE_LIB + +TEMPLATE = lib + +QT -= gui +QT += xml + +TARGET = krm130 + +DESTDIR = ../../../modules + +CONFIG(debug, debug|release) { + + LIBS += -L../../../lib -lCfgReader_d + LIBS += -L../../../lib -lphysics_d + LIBS += -L../../../lib -ldevice_d + LIBS += -L../../../lib -lfilesystem_d + +} else { + + LIBS += -L../../../lib -lCfgReader + LIBS += -L../../../lib -lphysics + LIBS += -L../../../lib -ldevice + LIBS += -L../../../lib -lfilesystem +} + +INCLUDEPATH += ./include +INCLUDEPATH += ../physics/include +INCLUDEPATH += ../solver/include +INCLUDEPATH += ../device/include +INCLUDEPATH += ../../CfgReader/include +INCLUDEPATH += ../../filesystem/include + + +HEADERS += $$files(./include/*.h) +SOURCES += $$files(./src/*.cpp) diff --git a/simulator/krm130/src/krm130.cpp b/simulator/krm130/src/krm130.cpp new file mode 100644 index 00000000..25684579 --- /dev/null +++ b/simulator/krm130/src/krm130.cpp @@ -0,0 +1,311 @@ +#include "krm130.h" + +#include + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +BrakeCrane130::BrakeCrane130(QObject *parent) : BrakeCrane (parent) + , k_leek(0.0) + , k_stab(0.0) + , Vec(1.0) + , A1(1.0) + , k1(1.0) + , k2(1.0) + , k3(1.0) + , k4(1.0) + , T1(0.1) + , T2(0.1) + , K4_power(10.0) + , Qbp(0.0) + , old_input(0) + , old_output(0) + , pulse_II(true) + , pulse_I(true) + , t_old(0) + , dt(0) + , handle_pos(static_cast(POS_II)) + , pos_angle(static_cast(POS_II)) + , pos_delay(0.3) + , min_pos(POS_I) + , max_pos(POS_VI) + , pos_duration(5.0) + , dir(0) + , pos_switch(true) + , tau(0.0) + +{ + std::fill(K.begin(), K.end(), 0.0); + std::fill(pos.begin(), pos.end(), 0.0); + pos[POS_II] = 1.0; + + positions_names << "I" << "II" << "III" << "IV" << "Va" << "V" << "VI"; + + float max_angle = 115.0f; + positions.push_back(0.0f); + positions.push_back(35.0f / max_angle); + positions.push_back(52.0f / max_angle); + positions.push_back(59.0f / max_angle); + positions.push_back(63.0f / max_angle); + positions.push_back(80.0f / max_angle); + positions.push_back(1.0f); + + incTimer = new Timer(pos_delay); + decTimer = new Timer(pos_delay); + + //connect(incTimer, &Timer::process, this, &BrakeCrane395::inc); + //connect(decTimer, &Timer::process, this, &BrakeCrane395::dec); + + connect(incTimer, SIGNAL(process()), this, SLOT(inc()), Qt::DirectConnection); + connect(decTimer, SIGNAL(process()), this, SLOT(dec()), Qt::DirectConnection); +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +BrakeCrane130::~BrakeCrane130() +{ + delete debug_log; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void BrakeCrane130::setPosition(int &position) +{ + position = cut(position, static_cast(POS_I), static_cast(POS_VI)); + + std::fill(pos.begin(), pos.end(), 0.0); + pos[static_cast(position)] = 1.0; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +QString BrakeCrane130::getPositionName() +{ + return positions_names[handle_pos]; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +float BrakeCrane130::getHandlePosition() +{ + return static_cast(handle_pos) / 6.0f; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void BrakeCrane130::init(double pTM, double pFL) +{ + Q_UNUSED(pFL) + + y[0] = pTM; + y[1] = pTM; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void BrakeCrane130::preStep(state_vector_t &Y, double t) +{ + Q_UNUSED(t) + + t_old = t; + + if ( (static_cast(pos[POS_II]) == 1) && pulse_II ) + { + Y[0] = cut(pf(2 * p0 - Y[1]), 0.0, pFL); + pulse_II = false; + } + else + { + pulse_II = true; + } +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void BrakeCrane130::postStep(state_vector_t &Y, double t) +{ + Q_UNUSED(Y) + + dt = t - t_old; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void BrakeCrane130::ode_system(const state_vector_t &Y, + state_vector_t &dYdt, + double t) +{ + double Q_charge = K[1] * (pFL - Y[1]) * pos[POS_I]; + + double u1 = hs_n(Y[1] - p0); + + double Q_train = K[1] * (pFL - Y[1]) * u1 * pos[POS_II]; + + double Q_stab = - k_stab * cut(k1 * Y[1], 0.0, 1.0) * pos[POS_II]; + + double Q_brake = - K[5] * Y[1] * pos[POS_Va] + - K[6] * Y[1] * pos[POS_V] + - K[9] * Y[1] * pos[POS_VI]; + + double Qer = Q_charge + Q_train + Q_stab + Q_brake; + + double s1 = A1 * (Y[0] - Y[1]); + + double K4 = 0; + + //K4 = K[4] * (1.0 + pow(pf(Y[BP_PRESSURE] / p0 - 1.0), K4_power)) * hs_p(Y[0] - Y[1]); + K4 = K[4] * (1.0 + k4 * pf(Y[0] - Y[1])); + + double u2 = cut(k2 * nf(s1), 0.0, 1.0) * (1.0 - pos[POS_VI]); + double u3 = cut(k3 * pf(s1), 0.0, 1.0); + + double Qbp = K[2] * (pFL - Y[0]) * u2 + - K4 * Y[0] * u3 + - K[7] * Y[0] * pos[POS_VI] + + K[8] * (pFL - Y[0]) * pos[POS_I]; + + setBrakePipeFlow(Qbp); + setEqResrvoirFlow(Qer); + + BrakeCrane::ode_system(Y, dYdt, t); +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void BrakeCrane130::load_config(CfgReader &cfg) +{ + QString secName = "Device"; + + for (size_t i = 1; i <= MAX_FLOW_COEFFS; ++i) + { + QString param = QString("K%1").arg(i); + + cfg.getDouble(secName, param, K[i]); + } + + cfg.getDouble(secName, "EqReservoirVolume", Ver); + cfg.getDouble(secName, "LocoBrakePipeVolume", Vbp); + cfg.getDouble(secName, "EqCameraVolume", Vec); + cfg.getDouble(secName, "k_leek", k_leek); + cfg.getDouble(secName, "k_stab", k_stab); + cfg.getDouble(secName, "A1", A1); + cfg.getDouble(secName, "k1", k1); + cfg.getDouble(secName, "k2", k2); + cfg.getDouble(secName, "k3", k3); + cfg.getDouble(secName, "k4", k4); + cfg.getDouble(secName, "T1", T1); + cfg.getDouble(secName, "T2", T2); + cfg.getDouble(secName, "K4_power", K4_power); +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void BrakeCrane130::stepKeysControl(double t, double dt) +{ + Q_UNUSED(t) + + if (getKeyState(KEY_Semicolon)) + { + if (!decTimer->isStarted()) + decTimer->start(); + } + else + { + decTimer->stop(); + } + + if (getKeyState(KEY_Quote)) + { + if (!incTimer->isStarted()) + incTimer->start(); + } + else + { + incTimer->stop(); + } + + if (isAlt()) + { + if (getKeyState(KEY_1)) + { + handle_pos = POS_I; + } + + if (getKeyState(KEY_2)) + { + handle_pos = POS_II; + } + + if (getKeyState(KEY_3)) + { + handle_pos = POS_III; + } + + if (getKeyState(KEY_4)) + { + handle_pos = POS_IV; + } + + if (getKeyState(KEY_5)) + { + handle_pos = POS_Va; + } + + if (getKeyState(KEY_6)) + { + handle_pos = POS_V; + } + + if (getKeyState(KEY_7)) + { + handle_pos = POS_VI; + } + } + + setPosition(handle_pos); + + incTimer->step(t, dt); + decTimer->step(t, dt); +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void BrakeCrane130::inc() +{ + int old_pos = handle_pos; + + handle_pos++; + + handle_pos = cut(handle_pos, min_pos, max_pos); + + if (handle_pos != old_pos) + emit soundPlay("Kran_395_ruk"); +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void BrakeCrane130::dec() +{ + int old_pos = handle_pos; + + handle_pos--; + + handle_pos = cut(handle_pos, min_pos, max_pos); + + if (handle_pos != old_pos) + emit soundPlay("Kran_395_ruk"); +} + +GET_BRAKE_CRANE(BrakeCrane130) diff --git a/simulator/kvt224/include/kvt224.h b/simulator/kvt224/include/kvt224.h new file mode 100644 index 00000000..e2e5ceb4 --- /dev/null +++ b/simulator/kvt224/include/kvt224.h @@ -0,0 +1,74 @@ +#ifndef KVT224_H +#define KVT224_H + +#include "loco-crane.h" + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +enum +{ + MAX_FLOW_COEFFS = 10, + MAX_GIAN_COEFFS = 10, + NUM_STEPS = 5 +}; + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +class LocoCrane224 : public LocoCrane +{ +public: + + LocoCrane224(QObject *parent = Q_NULLPTR); + + ~LocoCrane224(); + + double getHandlePosition() const; + + double getHandleShift() const; + + double getAirDistribPressure() const; + + void init(double pTM, double pFL); + +private: + + double V1; + + double V2; + + double Vpz; + + double delta_p; + + double ps; + + double min_pos; + + double max_pos; + + double pos_duration; + + int dir; + + + std::array step_pressures; + + std::array fixed_pos; + + std::array K; + + std::array k; + + /// Текущая фиксированная позиция + double cur_pos; + + void ode_system(const state_vector_t &Y, state_vector_t &dYdt, double t); + + void load_config(CfgReader &cfg); + + void stepKeysControl(double t, double dt); +}; + +#endif // KVT224_H diff --git a/simulator/kvt224/kvt224.pro b/simulator/kvt224/kvt224.pro new file mode 100644 index 00000000..b2583466 --- /dev/null +++ b/simulator/kvt224/kvt224.pro @@ -0,0 +1,37 @@ +DEFINES += DEVICE_LIB + +TEMPLATE = lib + +QT -= gui +QT += xml + +TARGET = kvt224 + +DESTDIR = ../../../modules + +CONFIG(debug, debug|release) { + + LIBS += -L../../../lib -lCfgReader_d + LIBS += -L../../../lib -lphysics_d + LIBS += -L../../../lib -ldevice_d + LIBS += -L../../../lib -lfilesystem_d + +} else { + + LIBS += -L../../../lib -lCfgReader + LIBS += -L../../../lib -lphysics + LIBS += -L../../../lib -ldevice + LIBS += -L../../../lib -lfilesystem +} + +INCLUDEPATH += ./include +INCLUDEPATH += ../physics/include +INCLUDEPATH += ../solver/include +INCLUDEPATH += ../device/include +INCLUDEPATH += ../../CfgReader/include +INCLUDEPATH += ../../filesystem/include + + +HEADERS += $$files(./include/*.h) +SOURCES += $$files(./src/*.cpp) + diff --git a/simulator/kvt224/src/kvt224.cpp b/simulator/kvt224/src/kvt224.cpp new file mode 100644 index 00000000..bd5546d4 --- /dev/null +++ b/simulator/kvt224/src/kvt224.cpp @@ -0,0 +1,232 @@ +#include "kvt224.h" + +#include + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +LocoCrane224::LocoCrane224(QObject *parent) : LocoCrane(parent) + , V1(1e-4) + , V2(1e-4) + , Vpz(3e-4) + , delta_p(0.05) + , ps(0.1) + , min_pos(-0.05) + , max_pos(1.0) + , pos_duration(1.0) + , dir(0) + , step_pressures({0.0, 0.13, 0.20, 0.30, 0.40}) +{ + std::fill(K.begin(), K.end(), 0.0); + std::fill(k.begin(), k.end(), 0.0); + + pos = cur_pos = 1.0; + + /*DebugLog *log = new DebugLog("kvt254.txt"); + connect(this, &LocoCrane254::DebugPrint, log, &DebugLog::DebugPring);*/ +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +LocoCrane224::~LocoCrane224() +{ + +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +double LocoCrane224::getHandlePosition() const +{ + return pos; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +double LocoCrane224::getHandleShift() const +{ + return pos; +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +double LocoCrane224::getAirDistribPressure() const +{ + return getY(0); +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void LocoCrane224::init(double pTM, double pFL) +{ + Q_UNUSED(pTM) + Q_UNUSED(pFL) +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void LocoCrane224::ode_system(const state_vector_t &Y, + state_vector_t &dYdt, + double t) +{ + Q_UNUSED(t) + + // Давление, задаваемое поворотом рукоятки + double p_handle = K[3] * pf(cur_pos); + + double u1 = hs_p(p_handle - Y[2]); + + double u2 = hs_n(p_handle - Y[2]); + + // Давление, задаваемое уравнительным органом крана + double pz = p_handle * u1 + Y[2] * u2; + + double dp = pz - pBC; + + double u3 = cut(pf(k[1] * dp), 0.0, 1.0); + + double u4 = cut(nf(k[1] * dp), 0.0, 1.0); + + // Поток воздуха в ТЦ + Qbc = K[1] * (pFL - pBC) * u3 - K[2] * pBC * u4; + + // Работа повторительной схемы + + double dp12 = Y[0] - Y[1]; + + double u5 = hs_n(dp12 - ps); + + double u6 = hs_n(pos) + is_release; + + double Qpz = K[7] * (Y[1] - Y[2]); + + double Q12 = K[5] * dp12 * u5; + + double Q1 = K[4] * Qvr; + + double Q2 = Q12 - Qpz - K[6] * Y[1] * u6; + + dYdt[0] = Q1 / V1; // p1 + + dYdt[1] = Q2 / V2; // p2 + + dYdt[2] = Qpz / Vpz; // p_pz +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void LocoCrane224::load_config(CfgReader &cfg) +{ + QString secName = "Device"; + + for (size_t i = 1; i < K.size(); ++i) + { + QString coeff = QString("K%1").arg(i); + cfg.getDouble(secName, coeff, K[i]); + } + + for (size_t i = 1; i < k.size(); ++i) + { + QString coeff = QString("k%1").arg(i); + cfg.getDouble(secName, coeff, k[i]); + } + + cfg.getDouble(secName, "V1", V1); + cfg.getDouble(secName, "V2", V2); + cfg.getDouble(secName, "Vpz", Vpz); + + cfg.getDouble(secName, "delta_p", delta_p); + + cfg.getDouble(secName, "ps", ps); + + QString tmp = ""; + + cfg.getString(secName, "StepPressures", tmp); + + std::istringstream ss(tmp.toStdString()); + + for (size_t i = 0; i < NUM_STEPS; ++i) + { + double step_press = 0.0; + ss >> step_press; + + step_pressures[i] = step_press; + } + + for (size_t i = 0; i < step_pressures.size(); ++i) + { + fixed_pos[i] = static_cast(i) / (NUM_STEPS - 1); + } + + cfg.getDouble(secName, "MinPos", min_pos); + cfg.getDouble(secName, "MaxPos", max_pos); + cfg.getDouble(secName, "PosDuration", pos_duration); +} + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ +void LocoCrane224::stepKeysControl(double t, double dt) +{ + Q_UNUSED(t) + + // Непрерывное движение ручки + if (getKeyState(KEY_Leftbracket)) + dir = -1; + else + { + if (getKeyState(KEY_Rightbracket)) + dir = 1; + else + dir = 0; + } + + pos += dir * pos_duration * dt; + + pos = cut(pos, min_pos, max_pos); + + for (size_t i = 0; i < fixed_pos.size() - 1; ++i) + { + if ( (pos >= fixed_pos[i]) && (pos < fixed_pos[i+1]) ) + cur_pos = fixed_pos[i]; + } + + if (pos > 0.99 * *(fixed_pos.end() - 1)) + cur_pos = *(fixed_pos.end() - 1); + + if (isAlt()) + { + if (getKeyState(KEY_8)) + { + pos = fixed_pos[0]; + } + + if (getKeyState(KEY_9)) + { + pos = fixed_pos[1]; + } + + if (getKeyState(KEY_0)) + { + pos = fixed_pos[2]; + } + + if (getKeyState(KEY_Minus)) + { + pos = fixed_pos[3]; + } + + if (getKeyState(KEY_Equals)) + { + pos = fixed_pos[4]; + } + } +} + +GET_LOCO_CRANE(LocoCrane224) diff --git a/simulator/simulator.pro b/simulator/simulator.pro index f010c899..f21b6994 100644 --- a/simulator/simulator.pro +++ b/simulator/simulator.pro @@ -21,7 +21,9 @@ SUBDIRS += ./simulator SUBDIRS += ./modbus SUBDIRS += ./krm395 +SUBDIRS += ./krm130 SUBDIRS += ./vr242 +SUBDIRS += ./kvt224 SUBDIRS += ./kvt254 SUBDIRS += ./epk150 SUBDIRS += ./km2202