1 Star 0 Fork 0

tectim/engine-sim

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
oscilloscope_cluster.cpp 14.93 KB
一键复制 编辑 原始数据 按行查看 历史
Ange Yaghi 提交于 2022-09-29 09:02 +08:00 . More accurate dyno measurements
#include "../include/oscilloscope_cluster.h"
#include "../include/engine_sim_application.h"
#include <sstream>
OscilloscopeCluster::OscilloscopeCluster() {
m_simulator = nullptr;
m_torqueScope = nullptr;
m_powerScope = nullptr;
m_totalExhaustFlowScope = nullptr;
m_intakeFlowScope = nullptr;
m_exhaustFlowScope = nullptr;
m_exhaustValveLiftScope = nullptr;
m_intakeValveLiftScope = nullptr;
m_audioWaveformScope = nullptr;
m_cylinderPressureScope = nullptr;
m_sparkAdvanceScope = nullptr;
m_cylinderMoleculesScope = nullptr;
m_pvScope = nullptr;
for (int i = 0; i < MaxLayeredScopes; ++i) {
m_currentFocusScopes[i] = nullptr;
}
m_torque = 0;
m_power = 0;
m_updatePeriod = 0.25f;
m_updateTimer = 0.0f;
}
OscilloscopeCluster::~OscilloscopeCluster() {
/* void */
}
void OscilloscopeCluster::initialize(EngineSimApplication *app) {
UiElement::initialize(app);
m_torqueScope = addElement<Oscilloscope>(this);
m_powerScope = addElement<Oscilloscope>(this);
m_exhaustFlowScope = addElement<Oscilloscope>(this);
m_totalExhaustFlowScope = addElement<Oscilloscope>(this);
m_intakeFlowScope = addElement<Oscilloscope>(this);
m_audioWaveformScope = addElement<Oscilloscope>(this);
m_intakeValveLiftScope = addElement<Oscilloscope>(this);
m_exhaustValveLiftScope = addElement<Oscilloscope>(this);
m_cylinderPressureScope = addElement<Oscilloscope>(this);
m_sparkAdvanceScope = addElement<Oscilloscope>(this);
m_cylinderMoleculesScope = addElement<Oscilloscope>(this);
m_pvScope = addElement<Oscilloscope>(this);
// Torque
m_torqueScope->setBufferSize(100);
m_torqueScope->m_xMin = 0.0f;
m_torqueScope->m_yMin = 0.0f;
m_torqueScope->m_yMax = 0.0f;
m_torqueScope->m_lineWidth = 2.0f;
m_torqueScope->m_drawReverse = false;
m_torqueScope->m_dynamicallyResizeX = true;
m_torqueScope->i_color = m_app->getOrange();
// Power
m_powerScope->setBufferSize(100);
m_powerScope->m_xMin = 0.0f;
m_powerScope->m_yMin = 0.0f;
m_powerScope->m_yMax = 0.0f;
m_powerScope->m_lineWidth = 2.0f;
m_powerScope->m_drawReverse = false;
m_powerScope->m_dynamicallyResizeX = true;
m_powerScope->i_color = m_app->getPink();
// Total exhaust flow
m_totalExhaustFlowScope->setBufferSize(1024);
m_totalExhaustFlowScope->m_xMin = 0.0f;
m_totalExhaustFlowScope->m_xMax = constants::pi * 4;
m_totalExhaustFlowScope->m_yMin = -units::flow(10, units::scfm);
m_totalExhaustFlowScope->m_yMax = units::flow(10, units::scfm);
m_totalExhaustFlowScope->m_lineWidth = 2.0f;
m_totalExhaustFlowScope->m_drawReverse = false;
m_totalExhaustFlowScope->i_color = m_app->getOrange();
// Exhaust flow
m_exhaustFlowScope->setBufferSize(1024);
m_exhaustFlowScope->m_xMin = 0.0f;
m_exhaustFlowScope->m_xMax = constants::pi * 4;
m_exhaustFlowScope->m_yMin = -units::flow(10.0, units::scfm);
m_exhaustFlowScope->m_yMax = units::flow(10.0, units::scfm);
m_exhaustFlowScope->m_lineWidth = 2.0f;
m_exhaustFlowScope->m_drawReverse = false;
m_exhaustFlowScope->i_color = m_app->getOrange();
// Intake flow
m_intakeFlowScope->setBufferSize(1024);
m_intakeFlowScope->m_xMin = 0.0f;
m_intakeFlowScope->m_xMax = constants::pi * 4;
m_intakeFlowScope->m_yMin = -units::flow(10.0, units::scfm);
m_intakeFlowScope->m_yMax = units::flow(10.0, units::scfm);
m_intakeFlowScope->m_lineWidth = 2.0f;
m_intakeFlowScope->m_drawReverse = false;
m_intakeFlowScope->i_color = m_app->getBlue();
// Cylinder molcules
m_cylinderMoleculesScope->setBufferSize(1024);
m_cylinderMoleculesScope->m_xMin = 0.0f;
m_cylinderMoleculesScope->m_xMax = constants::pi * 4;
m_cylinderMoleculesScope->m_yMin = -0.05;
m_cylinderMoleculesScope->m_yMax = 0.2;
m_cylinderMoleculesScope->m_lineWidth = 4.0f;
m_cylinderMoleculesScope->m_drawReverse = false;
m_cylinderMoleculesScope->i_color = m_app->getForegroundColor();
// Audio waveform scope
m_audioWaveformScope->setBufferSize(44100 / 50);
m_audioWaveformScope->m_xMin = 0.0f;
m_audioWaveformScope->m_xMax = 44100 / 10;
m_audioWaveformScope->m_yMin = -1.5f;
m_audioWaveformScope->m_yMax = 1.5f;
m_audioWaveformScope->m_lineWidth = 2.0f;
m_audioWaveformScope->m_drawReverse = false;
m_audioWaveformScope->i_color = m_app->getBlue();
// Valve lift scopes
m_exhaustValveLiftScope->setBufferSize(1024);
m_exhaustValveLiftScope->m_xMin = 0.0f;
m_exhaustValveLiftScope->m_xMax = constants::pi * 4;
m_exhaustValveLiftScope->m_yMin = (float)units::distance(-10, units::thou);
m_exhaustValveLiftScope->m_yMax = (float)units::distance(10, units::thou);
m_exhaustValveLiftScope->m_lineWidth = 2.0f;
m_exhaustValveLiftScope->m_drawReverse = false;
m_exhaustValveLiftScope->i_color = m_app->getOrange();
m_intakeValveLiftScope->setBufferSize(1024);
m_intakeValveLiftScope->m_xMin = 0.0f;
m_intakeValveLiftScope->m_xMax = constants::pi * 4;
m_intakeValveLiftScope->m_yMin = (float)units::distance(-10, units::thou);
m_intakeValveLiftScope->m_yMax = (float)units::distance(10, units::thou);
m_intakeValveLiftScope->m_lineWidth = 2.0f;
m_intakeValveLiftScope->m_drawReverse = false;
m_intakeValveLiftScope->i_color = m_app->getBlue();
// Cylinder pressure scope
m_cylinderPressureScope->setBufferSize(1024);
m_cylinderPressureScope->m_xMin = 0.0f;
m_cylinderPressureScope->m_xMax = constants::pi * 4;
m_cylinderPressureScope->m_yMin = -(float)std::sqrt(units::pressure(1, units::psi));
m_cylinderPressureScope->m_yMax = (float)std::sqrt(units::pressure(1, units::psi));
m_cylinderPressureScope->m_lineWidth = 2.0f;
m_cylinderPressureScope->m_drawReverse = false;
m_cylinderPressureScope->i_color = m_app->getOrange();
// Pressure volume scope
m_pvScope->setBufferSize(1024);
m_pvScope->m_xMin = 0.0f;
m_pvScope->m_xMax = units::volume(0.1, units::L);
m_pvScope->m_yMin = -(float)std::sqrt(units::pressure(1, units::psi));
m_pvScope->m_yMax = (float)std::sqrt(units::pressure(1, units::psi));
m_pvScope->m_lineWidth = 2.0f;
m_pvScope->m_drawReverse = true;
m_pvScope->i_color = m_app->getOrange();
m_pvScope->m_dynamicallyResizeX = true;
// Spark advance scope
m_sparkAdvanceScope->setBufferSize(1024);
m_sparkAdvanceScope->m_xMin = 0.0f;
m_sparkAdvanceScope->m_xMax = units::rpm(10000);
m_sparkAdvanceScope->m_yMin = -units::angle(30, units::deg);
m_sparkAdvanceScope->m_yMax = units::angle(60, units::deg);
m_sparkAdvanceScope->m_lineWidth = 2.0f;
m_sparkAdvanceScope->m_drawReverse = true;
m_sparkAdvanceScope->i_color = m_app->getOrange();
m_currentFocusScopes[0] = m_totalExhaustFlowScope;
m_currentFocusScopes[1] = nullptr;
m_torqueUnits = app->getAppSettings()->torqueUnits;
m_powerUnits = app->getAppSettings()->powerUnits;
}
void OscilloscopeCluster::destroy() {
UiElement::destroy();
}
void OscilloscopeCluster::signal(UiElement *element, Event event) {
if (event == Event::Clicked) {
if (element == m_audioWaveformScope) {
m_currentFocusScopes[0] = m_audioWaveformScope;
m_currentFocusScopes[1] = nullptr;
}
else if (element == m_powerScope || element == m_torqueScope) {
m_currentFocusScopes[0] = m_torqueScope;
m_currentFocusScopes[1] = m_powerScope;
m_currentFocusScopes[2] = nullptr;
}
else if (element == m_totalExhaustFlowScope) {
m_currentFocusScopes[0] = m_totalExhaustFlowScope;
m_currentFocusScopes[1] = nullptr;
}
else if (
element == m_intakeValveLiftScope
|| element == m_exhaustValveLiftScope)
{
m_currentFocusScopes[0] = m_intakeValveLiftScope;
m_currentFocusScopes[1] = m_exhaustValveLiftScope;
m_currentFocusScopes[2] = nullptr;
}
else if (element == m_pvScope) {
m_currentFocusScopes[0] = m_pvScope;
m_currentFocusScopes[1] = nullptr;
}
else if (
element == m_intakeFlowScope
|| element == m_exhaustFlowScope
|| element == m_cylinderMoleculesScope)
{
m_currentFocusScopes[0] = m_intakeFlowScope;
m_currentFocusScopes[1] = m_exhaustFlowScope;
m_currentFocusScopes[2] = m_cylinderMoleculesScope;
m_currentFocusScopes[3] = nullptr;
}
else if (element == m_cylinderPressureScope) {
m_currentFocusScopes[0] = m_cylinderPressureScope;
m_currentFocusScopes[1] = nullptr;
}
else if (element == m_sparkAdvanceScope) {
m_currentFocusScopes[0] = m_sparkAdvanceScope;
m_currentFocusScopes[1] = nullptr;
}
}
}
void OscilloscopeCluster::update(float dt) {
const double torque = (m_torqueUnits == "Nm")
? (units::convert(m_simulator->getFilteredDynoTorque(), units::Nm))
: (units::convert(m_simulator->getFilteredDynoTorque(), units::ft_lb));
const double power = (m_powerUnits == "kW")
? (units::convert(m_simulator->getDynoPower(), units::kW))
: (units::convert(m_simulator->getDynoPower(), units::hp));
m_torque = m_torque * 0.95 + 0.05 * torque;
m_power = m_power * 0.95 + 0.05 * power;
Engine *engine = m_simulator->getEngine();
if (engine != nullptr) {
if (m_updateTimer <= 0 && m_simulator->m_dyno.m_enabled) {
m_updateTimer = m_updatePeriod;
m_torqueScope->addDataPoint(engine->getRpm(), m_torque);
m_powerScope->addDataPoint(engine->getRpm(), m_power);
}
m_sparkAdvanceScope->addDataPoint(
-engine->getCrankshaft(0)->m_body.v_theta,
engine->getIgnitionModule()->getTimingAdvance());
}
m_updateTimer -= dt;
UiElement::update(dt);
}
void OscilloscopeCluster::render() {
Grid grid;
grid.h_cells = 3;
grid.v_cells = 4;
const Bounds &hpTorqueBounds = grid.get(m_bounds, 0, 3);
renderScope(m_torqueScope, hpTorqueBounds, "Torque/Power");
renderScope(m_powerScope, hpTorqueBounds, "", true);
const Bounds &valveLiftBounds = grid.get(m_bounds, 2, 2);
renderScope(m_intakeValveLiftScope, valveLiftBounds, "Valve Lift");
renderScope(m_exhaustValveLiftScope, valveLiftBounds, "", true);
const Bounds &flowBounds = grid.get(m_bounds, 2, 3);
renderScope(m_intakeFlowScope, flowBounds, "Flow");
renderScope(m_exhaustFlowScope, flowBounds, "", true);
renderScope(m_cylinderMoleculesScope, flowBounds, "", true);
const Bounds &audioWaveformBounds = grid.get(m_bounds, 0, 2);
renderScope(m_audioWaveformScope, audioWaveformBounds, "Waveform");
const Bounds &cylinderPressureBounds = grid.get(m_bounds, 1, 3);
renderScope(m_pvScope, cylinderPressureBounds, "pressure-volume");
const Bounds &totalExhaustPressureBounds = grid.get(m_bounds, 1, 2);
renderScope(m_totalExhaustFlowScope, totalExhaustPressureBounds, "Total Exhaust Flow");
const Bounds &focusBounds = grid.get(m_bounds, 0, 0, 3, 2);
Bounds focusTitle = focusBounds;
focusTitle.m0.y = focusTitle.m1.y - (24.0f + 15.0f);
Bounds focusBody = focusBounds;
focusBody.m1 = focusBody.m1 - Point(0.0f, 24.0f + 15.0f);
drawFrame(focusTitle, 1.0, m_app->getForegroundColor(), m_app->getBackgroundColor());
drawFrame(focusBody, 1.0, m_app->getForegroundColor(), m_app->getBackgroundColor());
for (int i = 0; i < MaxLayeredScopes; ++i) {
if (m_currentFocusScopes[i] != nullptr) {
m_currentFocusScopes[i]->render(focusBody);
}
else break;
}
UiElement::render();
}
void OscilloscopeCluster::sample() {
Engine *engine = m_simulator->getEngine();
if (engine == nullptr) return;
const double cylinderPressure = engine->getChamber(0)->m_system.pressure()
+ engine->getChamber(0)->m_system.dynamicPressure(-1.0, 0.0);
if (m_simulator->getCurrentIteration() % 2 == 0) {
double cycleAngle = engine->getCrankshaft(0)->getCycleAngle();
if (!engine->isSpinningCw()) {
cycleAngle = 4 * constants::pi - cycleAngle;
}
getTotalExhaustFlowOscilloscope()->addDataPoint(
cycleAngle,
m_simulator->getTotalExhaustFlow() / m_simulator->getTimestep());
getCylinderPressureScope()->addDataPoint(
engine->getCrankshaft(0)->getCycleAngle(constants::pi),
std::sqrt(cylinderPressure));
getExhaustFlowOscilloscope()->addDataPoint(
cycleAngle,
engine->getChamber(0)->getLastTimestepExhaustFlow() / m_simulator->getTimestep());
getIntakeFlowOscilloscope()->addDataPoint(
cycleAngle,
engine->getChamber(0)->getLastTimestepIntakeFlow() / m_simulator->getTimestep());
getCylinderMoleculesScope()->addDataPoint(
cycleAngle,
engine->getChamber(0)->m_system.n());
getExhaustValveLiftOscilloscope()->addDataPoint(
cycleAngle,
engine->getChamber(0)->getCylinderHead()->exhaustValveLift(
engine->getChamber(0)->getPiston()->getCylinderIndex()));
getIntakeValveLiftOscilloscope()->addDataPoint(
cycleAngle,
engine->getChamber(0)->getCylinderHead()->intakeValveLift(
engine->getChamber(0)->getPiston()->getCylinderIndex()));
getPvScope()->addDataPoint(
engine->getChamber(0)->getVolume(),
std::sqrt(engine->getChamber(0)->m_system.pressure()));
}
m_exhaustFlowScope->m_yMin = m_intakeFlowScope->m_yMin =
std::fmin(m_intakeFlowScope->m_yMin, m_exhaustFlowScope->m_yMin);
m_exhaustFlowScope->m_yMax = m_intakeFlowScope->m_yMax =
std::fmax(m_intakeFlowScope->m_yMax, m_exhaustFlowScope->m_yMax);
m_torqueScope->m_yMin = m_powerScope->m_yMin =
std::fmin(m_torqueScope->m_yMin, m_powerScope->m_yMin);
m_torqueScope->m_yMax = m_powerScope->m_yMax =
std::fmax(m_torqueScope->m_yMax, m_powerScope->m_yMax);
m_powerScope->m_xMax = m_torqueScope->m_xMax =
std::fmax(m_powerScope->m_xMax, units::toRpm(engine->getSpeed()));
}
void OscilloscopeCluster::setSimulator(Simulator *simulator) {
m_simulator = simulator;
}
void OscilloscopeCluster::renderScope(
Oscilloscope *osc,
const Bounds &bounds,
const std::string &title,
bool overlay)
{
if (!overlay) {
drawFrame(bounds, 1.0, m_app->getForegroundColor(), m_app->getBackgroundColor());
}
if (osc == m_currentFocusScopes[0]) {
Grid grid;
grid.h_cells = 3;
grid.v_cells = 4;
const Bounds &focusBounds = grid.get(m_bounds, 0, 0, 3, 2);
Bounds focusTitle = focusBounds;
focusTitle.m1 -= Point(0.0f, 24.0f + 15.0f);
Bounds focusBody = focusBounds;
focusTitle.m1 += Point(0.0f, 24.0f + 15.0f);
drawText(title, focusTitle.inset(20.0f), 24.0f, Bounds::tl);
}
osc->m_bounds = bounds;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/tectim/engine-sim.git
git@gitee.com:tectim/engine-sim.git
tectim
engine-sim
engine-sim
master

搜索帮助