65 lines
2.5 KiB
C++
65 lines
2.5 KiB
C++
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <cstddef>
|
|
#include <vector>
|
|
|
|
namespace fluidsim::port {
|
|
|
|
struct DynoPoint {
|
|
float power_kw{};
|
|
float torque_nm{};
|
|
};
|
|
|
|
// Shared rolling peak curve from the C# Scenario base class. Each bin stores
|
|
// the greatest observed power and torque independently, with missing bins
|
|
// interpolated when the engine crosses an RPM range too quickly to sample it.
|
|
class DynoCurve {
|
|
public:
|
|
static constexpr float rpm_bin_size = 50.0f;
|
|
|
|
void reset() {
|
|
bins_.clear();
|
|
last_bin_ = invalid_bin;
|
|
}
|
|
|
|
void update(float rpm, float power_kw, float torque_nm) {
|
|
if (!std::isfinite(rpm) || rpm <= 0.0f || !std::isfinite(power_kw) || !std::isfinite(torque_nm))
|
|
return;
|
|
const auto bin = static_cast<std::size_t>(rpm / rpm_bin_size);
|
|
if (bin >= bins_.max_size()) return;
|
|
while (bins_.size() <= bin) bins_.push_back({});
|
|
|
|
if (last_bin_ != invalid_bin && bin > last_bin_ + 1) {
|
|
const float last_power = bins_[last_bin_].power_kw > 0.0f ? bins_[last_bin_].power_kw : 0.0f;
|
|
const float last_torque = bins_[last_bin_].torque_nm > 0.0f ? bins_[last_bin_].torque_nm : 0.0f;
|
|
for (std::size_t missing = last_bin_ + 1; missing < bin; ++missing) {
|
|
const float t = static_cast<float>(missing - last_bin_) /
|
|
static_cast<float>(bin - last_bin_);
|
|
const float interpolated_power = last_power + (power_kw - last_power) * t;
|
|
const float interpolated_torque = last_torque + (torque_nm - last_torque) * t;
|
|
auto& point = bins_[missing];
|
|
if (interpolated_power > point.power_kw || point.power_kw <= 0.0f)
|
|
point.power_kw = interpolated_power;
|
|
if (interpolated_torque > point.torque_nm || point.torque_nm <= 0.0f)
|
|
point.torque_nm = interpolated_torque;
|
|
}
|
|
}
|
|
|
|
auto& current = bins_[bin];
|
|
if (power_kw > current.power_kw || current.power_kw <= 0.0f) current.power_kw = power_kw;
|
|
if (torque_nm > current.torque_nm || current.torque_nm <= 0.0f) current.torque_nm = torque_nm;
|
|
last_bin_ = bin;
|
|
}
|
|
|
|
const std::vector<DynoPoint>& bins() const { return bins_; }
|
|
|
|
private:
|
|
static constexpr std::size_t invalid_bin = static_cast<std::size_t>(-1);
|
|
std::vector<DynoPoint> bins_;
|
|
std::size_t last_bin_{invalid_bin};
|
|
};
|
|
|
|
} // namespace fluidsim::port
|