implement launch spark skip functionality (#6566)

This commit is contained in:
kifir 2024-06-07 14:55:15 +03:00 committed by rusefillc
parent 3e4d1db28b
commit fdc60e4bff
5 changed files with 151 additions and 3 deletions

View File

@ -87,7 +87,15 @@ void EngineState::updateSlowSensors() {
void EngineState::updateSparkSkip() {
#if EFI_LAUNCH_CONTROL
engine->softSparkLimiter.updateTargetSkipRatio(luaSoftSparkSkip, tractionControlSparkSkip);
engine->hardSparkLimiter.updateTargetSkipRatio(luaHardSparkSkip, tractionControlSparkSkip);
engine->hardSparkLimiter.updateTargetSkipRatio(
luaHardSparkSkip,
tractionControlSparkSkip,
/*
* We are applying launch controller spark skip ratio only for hard skip limiter (see
* https://github.com/rusefi/rusefi/issues/6566#issuecomment-2153149902).
*/
engine->launchController.getSparkSkipRatio()
);
#endif // EFI_LAUNCH_CONTROL
}

View File

@ -144,6 +144,8 @@ void LaunchControlBase::update() {
// If conditions are met...
isLaunchCondition = m_launchTimer.hasElapsedSec(engineConfiguration->launchActivateDelay);
}
sparkSkipRatio = calculateSparkSkipRatio(rpm);
}
bool LaunchControlBase::isLaunchRpmRetardCondition() const {
@ -158,6 +160,25 @@ bool LaunchControlBase::isLaunchFuelRpmRetardCondition() const {
return isLaunchRpmRetardCondition() && engineConfiguration->launchFuelCutEnable;
}
float LaunchControlBase::calculateSparkSkipRatio(const int rpm) const {
float result = 0.0f;
if (engineConfiguration->launchControlEnabled && engineConfiguration->launchSparkCutEnable) {
if (isLaunchCondition) {
result = 1.0f;
} else {
const int launchRpm = engineConfiguration->launchRpm;
const int sparkSkipStartRpm = launchRpm - engineConfiguration->launchRpmWindow;
if (sparkSkipStartRpm <= rpm) {
const float initialIgnitionCutRatio = engineConfiguration->initialIgnitionCutPercent / 100.0f;
const int sparkSkipEndRpm = launchRpm - engineConfiguration->launchCorrectionsEndRpm;
const float finalIgnitionCutRatio = engineConfiguration->finalIgnitionCutPercentBeforeLaunch / 100.0f;
result = interpolateClamped(sparkSkipStartRpm, initialIgnitionCutRatio, sparkSkipEndRpm, finalIgnitionCutRatio, rpm);
}
}
}
return result;
}
SoftSparkLimiter::SoftSparkLimiter(const bool p_allowHardCut)
: allowHardCut(p_allowHardCut) {
#if EFI_UNIT_TEST
@ -165,7 +186,11 @@ SoftSparkLimiter::SoftSparkLimiter(const bool p_allowHardCut)
#endif // EFI_UNIT_TEST
}
void SoftSparkLimiter::updateTargetSkipRatio(const float luaSparkSkip, const float tractionControlSparkSkip) {
void SoftSparkLimiter::updateTargetSkipRatio(
const float luaSparkSkip,
const float tractionControlSparkSkip,
const float launchControllerSparkSkipRatio
) {
targetSkipRatio = luaSparkSkip;
if (engineConfiguration->useHardSkipInTraction) {
if (allowHardCut) {
@ -174,6 +199,14 @@ void SoftSparkLimiter::updateTargetSkipRatio(const float luaSparkSkip, const flo
} else if (!allowHardCut) {
targetSkipRatio += tractionControlSparkSkip;
}
if (allowHardCut) {
/*
* We are applying launch controller spark skip ratio only for hard skip limiter (see
* https://github.com/rusefi/rusefi/issues/6566#issuecomment-2153149902).
*/
targetSkipRatio += launchControllerSparkSkipRatio;
}
}
static tinymt32_t tinymt;

View File

@ -35,10 +35,16 @@ public:
bool isLaunchSparkRpmRetardCondition() const;
bool isLaunchFuelRpmRetardCondition() const;
float getSparkSkipRatio() const { return sparkSkipRatio; }
private:
bool isLaunchRpmRetardCondition() const;
float calculateSparkSkipRatio(int rpm) const;
Timer m_launchTimer;
float sparkSkipRatio = 0.0f;
};
/**
@ -50,7 +56,11 @@ public:
/**
* targetSkipRatio of '0' means 'do not skip', would always return false
*/
void updateTargetSkipRatio(float luaSoftSparkSkip, float tractionControlSparkSkip);
void updateTargetSkipRatio(
float luaSoftSparkSkip,
float tractionControlSparkSkip,
float launchControllerSparkSkipRatio = 0.0f
);
[[nodiscard]] float getTargetSkipRatio() const { return targetSkipRatio; }
bool shouldSkip();

View File

@ -0,0 +1,96 @@
//
// Created by kifir on 6/7/24.
//
#include "pch.h"
constexpr int TEST_LAUNCH_RPM = 3850;
constexpr int TEST_LAUNCH_RPM_WINDOW = 1850;
constexpr int TEST_LAUNCH_SPARK_SKIP_END_RPM = 850;
constexpr int TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START = TEST_LAUNCH_RPM - TEST_LAUNCH_RPM_WINDOW;
constexpr int TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END = TEST_LAUNCH_RPM - TEST_LAUNCH_SPARK_SKIP_END_RPM;
constexpr int TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END - TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START;
constexpr int TEST_INITIAL_IGNITION_CUT_PERCENT = 13;
constexpr float TEST_INITIAL_IGNITION_CUT_RATIO = 0.13f;
constexpr int TEST_FINAL_IGNITION_CUT_PERCENT = 42;
constexpr float TEST_FINAL_IGNITION_CUT_RATIO = 0.42f;
static void setUpTestParameters(
const std::optional<bool> launchControlEnabled,
const std::optional<bool> enableIgnitionCut
) {
if (launchControlEnabled.has_value()) {
engineConfiguration->launchControlEnabled = launchControlEnabled.value();
} else {
ASSERT_FALSE(engineConfiguration->launchControlEnabled); // check default value
}
if (enableIgnitionCut.has_value()) {
engineConfiguration->launchSparkCutEnable = enableIgnitionCut.value();
} else {
ASSERT_FALSE(engineConfiguration->launchSparkCutEnable); // check default value
}
engineConfiguration->launchRpm = TEST_LAUNCH_RPM;
engineConfiguration->launchRpmWindow = TEST_LAUNCH_RPM_WINDOW;
engineConfiguration->launchCorrectionsEndRpm = TEST_LAUNCH_SPARK_SKIP_END_RPM;
engineConfiguration->initialIgnitionCutPercent = TEST_INITIAL_IGNITION_CUT_PERCENT;
engineConfiguration->finalIgnitionCutPercentBeforeLaunch = TEST_FINAL_IGNITION_CUT_PERCENT;
engineConfiguration->launchActivationMode = ALWAYS_ACTIVE_LAUNCH; // to satisfy activateSwitchCondition
engineConfiguration->launchSpeedThreshold = 0; // to satisfy speedCondition
Sensor::setMockValue(SensorType::DriverThrottleIntent, 1.7); // to satisfy tpsCondition
}
static void updateRpm(const int rpm, EngineTestHelper& eth) {
Sensor::setMockValue(SensorType::Rpm, rpm);
for (int i = 0; i < 2; i++) {\
/*
* We need to repeat the following code twice because method EngineState::periodicFastCallback updates launch
* controller after updating spark skip - can we fix it safely?
*/
eth.moveTimeForwardSec(1);
// run the ignition math
engine->periodicFastCallback();
}
}
TEST(skipSparkRatio, raisingRpm) {
EngineTestHelper eth(engine_type_e::TEST_ENGINE);
setUpTestParameters({ true }, { true });
updateRpm(TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START - 1, eth);
EXPECT_FALSE(engine->launchController.isLaunchCondition);
EXPECT_EQ(engine->hardSparkLimiter.getTargetSkipRatio(), 0.0f);
updateRpm(TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START, eth);
/* We've entered spark skip RPM window: */
EXPECT_FALSE(engine->launchController.isLaunchCondition);
EXPECT_EQ(engine->hardSparkLimiter.getTargetSkipRatio(), TEST_INITIAL_IGNITION_CUT_RATIO);
updateRpm(TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END, eth);
EXPECT_FALSE(engine->launchController.isLaunchCondition);
EXPECT_EQ(engine->hardSparkLimiter.getTargetSkipRatio(), TEST_FINAL_IGNITION_CUT_RATIO);
updateRpm((TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END - TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START) / 2, eth);
EXPECT_FALSE(engine->launchController.isLaunchCondition);
EXPECT_EQ(
engine->hardSparkLimiter.getTargetSkipRatio(),
(TEST_FINAL_IGNITION_CUT_RATIO - TEST_FINAL_IGNITION_CUT_RATIO) / 2
);
updateRpm(TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END + 1, eth);
/* We've left spark skip RPM window: */
EXPECT_FALSE(engine->launchController.isLaunchCondition);
EXPECT_EQ(engine->hardSparkLimiter.getTargetSkipRatio(), TEST_FINAL_IGNITION_CUT_RATIO);
updateRpm(TEST_LAUNCH_RPM - 1, eth);
EXPECT_FALSE(engine->launchController.isLaunchCondition);
EXPECT_EQ(engine->hardSparkLimiter.getTargetSkipRatio(), TEST_FINAL_IGNITION_CUT_RATIO);
/* We've reached TEST_LAUNCH_RPM: */
updateRpm(TEST_LAUNCH_RPM, eth);
EXPECT_TRUE(engine->launchController.isLaunchCondition);
EXPECT_EQ(engine->hardSparkLimiter.getTargetSkipRatio(), 1.0);
}

View File

@ -48,6 +48,7 @@ TESTS_SRC_CPP = \
tests/launch/test_rpm_condition.cpp \
tests/launch/test_retard_threshold_rpm.cpp \
tests/launch/test_ignition_angle_advance.cpp \
tests/launch/test_spark_skip_ratio.cpp \
tests/lua/test_lua_basic.cpp \
tests/lua/test_lookup.cpp \
tests/lua/test_lua_e38.cpp \