suboptimumg.vehicle.powertrain.powertrain#
- class suboptimumg.vehicle.powertrain.powertrain.Motor(vehicle_model)[source]#
Bases:
objectModels motor torque output, efficiency, and power limits.
Notes
The efficiency map, rpm/torque normalization parameters, and the power-limit grids are precomputed once at construction time (when
use_efficiency_lutis set) so that the runtime hot path only needs a singlenp.interplookup instead of a bisection loop. Callbuild_power_limit_tableagain if motor parameters are mutated at runtime.- Parameters:
vehicle_model (VehicleModel)
- build_power_limit_table(n_rpm=200)[source]#
Precompute the DC-power-limited max motor torque at each rpm.
- Parameters:
n_rpm (int) – Number of RPM points to precompute between 0 and max_rpm.
- Return type:
None
Notes
At a given rpm, the binding DC constraint is
tau * omega / eta_elec(rpm, tau) <= pow_lim, which is implicit in tau because eta_elec depends on tau via the LUT. This inverts the constraint once by bisecting tau in [0, tau_curve(rpm)] at each rpm in a fixed grid, then looks the result up with np.interp at runtime.At rpm=0 there is no power binding (omega=0 implies P_DC=0 for any tau), so the static torque curve dominates. Where the static curve already fits under pow_lim, no inversion is needed (this also provides a cheap early-out when full torque is already under the power limit at a given rpm). The bisection itself relies on P_DC(tau) being non-decreasing in tau, because eta_elec is bounded (eval_efficiency_map clips to [0.66, 0.99]), so the tau term dominates as tau approaches 0.
Rebuild this table if pow_lim, moc_efficiency, or the LUT itself changes after construction.
- calculate_max_ground_force_and_motor_power(v, ratio)[source]#
Calculates force and power output by the motor.
- Parameters:
v (float) – Velocity of the vehicle (m/s)
ratio (float) – Gear ratio
- Returns:
ground_force (float) – Force at the ground (N)
motor_power (float) – Motor shaft power output (W)
- Return type:
tuple[float, float]
Notes
The torque the motor can deliver is constrained by two things: the static torque curve tau_curve(rpm), and the DC-bus power limit pow_lim, via
tau * omega / eta_elec(rpm, tau) <= pow_lim, which is circular in tau because eta_elec depends on tau. When use_efficiency_lut is True this is resolved by an inverse lookup built once at init in build_power_limit_table.Only chain/diff efficiencies sit between shaft and wheel, so the wheel torque uses mechanical_efficiency (not the full chain). The inverter and motor losses are upstream of the shaft and affect battery draw, not wheel torque.
- electrical_efficiency(rpm, torque)[source]#
Loss factor between DC bus and motor shaft.
- Parameters:
rpm (float) – Motor RPM (used if LUT is enabled)
torque (float) – Motor torque (used if LUT is enabled)
- Returns:
Motor efficiency * MOC efficiency
- Return type:
float
Notes
Covers the inverter (moc_efficiency) and the motor itself. When an efficiency LUT is in use and both rpm and torque are supplied, the motor’s contribution is pulled from the (rpm, torque) map; otherwise the scalar motor_efficiency is used.
- eval_efficiency_map(rpm, torque)[source]#
Evaluate the 2D efficiency map at a given (rpm, torque) point.
- Parameters:
rpm (float) – Motor RPM
torque (float) – Motor torque
- Returns:
Motor efficiency (0.66 to 0.99)
- Return type:
float
Notes
Inputs outside the fitted rpm/torque range are clamped to the nearest in-range value before evaluating the polynomial, and the result is scaled down by an exponential penalty based on how far outside the range the original inputs were.
- fit_efficiency_data(points, degv, degt)[source]#
Fit a 2D polynomial z = f(x, y) to data points [[x, y, z], …].
- Parameters:
points (list of lists) – Each inner list is [rpm, torque, efficiency] for a data point.
degv (int) – Degree of the polynomial in the rpm (x) direction.
degt (int) – Degree of the polynomial in the torque (y) direction.
- Returns:
Coefficient matrix C[i,j] for x^i y^j.
- Return type:
NDArray[np.float64]
Notes
If the efficiency surface has an especially unusual shape, a higher fit degree may be needed. Keep degrees even, and as low as possible, to limit evaluation complexity.
- get_torque_at_rpm(motor_rpm)[source]#
Get motor torque at a given RPM using piecewise function.
The torque curve has three regions: 1. Flat region (0 to fw_rpm): constant max torque 2. Linear decay (fw_rpm to max_rpm): torque decreases linearly 3. Zero region (above max_rpm): no torque
- Parameters:
motor_rpm (float) – Motor RPM
- Returns:
Motor torque at the given RPM (Nm)
- Return type:
float
- mechanical_efficiency()[source]#
Loss factor between motor shaft and wheel.
- Returns:
Combined chain and differential efficiency (0.0 to 1.0)
- Return type:
float
Notes
Only the components that physically sit downstream of the shaft act here: the chain/belt and the diff. The inverter and motor losses are electrical and do not reduce wheel torque; they show up as extra DC current draw and are accounted for in electrical_efficiency.
- powertrain_efficiency(rpm, torque)[source]#
Full DC-bus-to-ground efficiency, used by callers converting between battery power and wheel power (or vice versa).
- Parameters:
rpm (float) – Motor RPM (used if efficiency_method is ‘indiv’)
torque (float) – Motor torque (used if efficiency_method is ‘indiv’)
- Returns:
Overall powertrain efficiency (0.0 to 1.0)
- Return type:
float
Notes
Equals electrical_efficiency * mechanical_efficiency when in ‘indiv’ mode. In ‘sys’ mode the lumped system_efficiency parameter is used directly. Diff efficiency is currently fixed at 100% (TODO).
- class suboptimumg.vehicle.powertrain.powertrain.Powertrain(vehicle_model)[source]#
Bases:
objectModels the full powertrain, composed of a motor.
- Parameters:
vehicle_model (VehicleModel)