Migrate 32 engine definitions into validated startup-loaded TOML files and separate configuration and snapshots from scenario assembly. Add camera-based stereo propagation from shared pipe geometry, preserve exhaust character, tune carburetor mixtures and idle, use ignition cuts for carb engines, and support returning to the scenario menu. Validation: full Windows build and all 14 CTest checks passed.
70 lines
3.3 KiB
C++
70 lines
3.3 KiB
C++
#pragma once
|
|
#include "FluidSim/PipeProfile.hpp"
|
|
#include "FluidSim/Ecu.hpp"
|
|
#include "FluidSim/Vehicle.hpp"
|
|
#include <array>
|
|
|
|
namespace fluidsim::port {
|
|
enum class TwoStrokeExhaust { Racing, Straight };
|
|
|
|
// YZ125-sized baseline. Port/chamber/combustion dimensions are explicit design
|
|
// estimates, not a measured Yamaha cylinder or factory exhaust/ignition map.
|
|
struct TwoStrokeConfig {
|
|
EcuConfig ecu=[] {
|
|
EcuConfig e;
|
|
e.idle_control=EcuConfig::IdleControl::FixedOpening;
|
|
e.throttle_time_constant=.0002f;e.throttle_rate=5000;
|
|
e.ignition_map={{0,10},{3000,18},{6000,24},{9000,18},{11000,12},{13000,6},{15000,2},{18000,0}};
|
|
e.idle_rpm=3000;e.idle_max_opening=.3f;e.rev_limit_enabled=false;
|
|
e.overrun_cut_rpm=5000;e.overrun_resume_rpm=3500;
|
|
e.rev_limit_fuel_cut_enabled=false;e.overrun_fuel_cut_enabled=false;e.overrun_ignition_cut_enabled=true;
|
|
return e;
|
|
}();
|
|
VehicleConfig vehicle=[] {
|
|
VehicleConfig v;
|
|
v.primary_reduction=64.f/19;v.final_drive_ratio=49.f/13;
|
|
v.gear_ratios={31.f/13,29.f/15,27.f/17,23.f/17,20.f/17,19.f/18};
|
|
v.mass=170;v.wheel_radius=.3313f;
|
|
return v;
|
|
}();
|
|
float initial_rpm{3000}, starter_torque{8}, maximum_load_torque{10};
|
|
float crankshaft_inertia{.01f};
|
|
TwoStrokeExhaust exhaust{TwoStrokeExhaust::Racing};
|
|
float bore{.054f}, stroke{.0545f}, rod{.110f};
|
|
float trapped_compression{8.2f}; // exhaust-closure volume / clearance volume
|
|
float transfer_duration{130}, exhaust_duration{190};
|
|
float transfer_width{.050f}, exhaust_width{.036f}; // summed effective window widths
|
|
float pilot_jet_scale{.75f}, main_jet_scale{1.6f}, needle_jet_scale{1.f};
|
|
float needle_low_scale{2.72f}, needle_mid_scale{.8f};
|
|
float needle_off_idle_scale{12.f}, needle_transition_scale{9.f}, needle_tip_scale{5.f};
|
|
float needle_quarter_scale{1.4f}, needle_upper_scale{.76f};
|
|
float pilot_transition_scale{1.f}, pilot_tip_scale{1.f};
|
|
float jet_scale{1.f}; // multiplier on effective jet diameters
|
|
float crankcase_clearance{150e-6f};
|
|
float carburetor_diameter{.0381f};
|
|
float idle_spark_gain{.05f}; // spark degrees per RPM error at the fixed carb stop
|
|
float idle_minimum_advance{-10.f};
|
|
float idle_slide_opening{.045f}; // fixed mechanical stop, normalized 0..1 (4.5%)
|
|
float minimum_burn_seconds{.0008f};
|
|
// Empirical mechanical FMEP = A + B*mean_piston_speed + C*speed^2.
|
|
// Generic correlation estimates, not a measured YZ125 coast-down fit.
|
|
float friction_bar{.4f}, friction_bar_per_mps{.09f}, friction_bar_per_mps2{.0009f};
|
|
float exhaust_cell_length{.01f};
|
|
std::array<PipeSection, 6> racing_pipe{{
|
|
{.160f, .036f, .036f}, // header
|
|
{.180f, .036f, .060f}, // shallow first diffuser
|
|
{.190f, .060f, .105f}, // second diffuser
|
|
{.130f, .105f, .105f}, // belly
|
|
{.210f, .105f, .022f}, // convergent / baffle cone
|
|
{.240f, .022f, .022f} // stinger
|
|
}};
|
|
float geometric_compression() const {
|
|
const float theta = (180 + exhaust_duration * .5f) * pi / 180;
|
|
const float radius = stroke * .5f, sine = std::sin(theta);
|
|
const float travel = radius * (1 - std::cos(theta)) + rod -
|
|
std::sqrt(rod*rod - radius*radius*sine*sine);
|
|
return 1 + (trapped_compression - 1) * stroke / travel;
|
|
}
|
|
};
|
|
} // namespace fluidsim::port
|