|
|
|
@ -7,23 +7,24 @@ namespace Simulator {
|
|
|
|
|
solarPanelEfficiency: number = 0.15; |
|
|
|
|
solarPanelArea: number = 1.0; // in square meters
|
|
|
|
|
|
|
|
|
|
emptyVehicleWeight: number = 80; // kg
|
|
|
|
|
driverWeight: number = 60; // kg
|
|
|
|
|
additionalWeight: number; // additional weight, not counting cyclist and empty vehicle weight, in kg
|
|
|
|
|
|
|
|
|
|
motorConsumption(distance: number, ascendingElevation: number): number { |
|
|
|
|
// empirical measures
|
|
|
|
|
let maxWeight = 200; // in kg
|
|
|
|
|
let maxWeightAdditionalConsumption = 4; // in Wh/km
|
|
|
|
|
let maxTestedElevation = 500; // in meters
|
|
|
|
|
let maxTestedElevationConsumption = 7; // in Wh/m
|
|
|
|
|
let baseConsumption = 14; // in Wh/km
|
|
|
|
|
const g = 9.8; |
|
|
|
|
let totalWeight = this.emptyVehicleWeight + this.driverWeight + this.additionalWeight; |
|
|
|
|
let potentialEnergy = totalWeight * g * ascendingElevation; // Ep = m*g*h (result in Joules)
|
|
|
|
|
potentialEnergy = potentialEnergy / 3600; // convert joules to watt-hour
|
|
|
|
|
|
|
|
|
|
let weightRelatedConsumption = MathUtils.clamp(this.additionalWeight * maxWeightAdditionalConsumption / maxWeight, 0, maxWeightAdditionalConsumption); |
|
|
|
|
// empirical measures
|
|
|
|
|
let baseConsumption = 13; // in Wh/km
|
|
|
|
|
let maxWeight = 300; // in kg
|
|
|
|
|
let additionalConsumptionAtMaxWeight = 5; // in Wh/km (without accounting for ascending elevation, only accelerations and additional friction)
|
|
|
|
|
|
|
|
|
|
// TODO: should not be multiplied by distance
|
|
|
|
|
// TODO: should be multiplied by total vehicle weight
|
|
|
|
|
let elevationRelatedConsumption = MathUtils.clamp(ascendingElevation * maxTestedElevationConsumption / maxTestedElevation, 0, maxTestedElevationConsumption); |
|
|
|
|
let weightRelatedConsumption = MathUtils.clamp(totalWeight * additionalConsumptionAtMaxWeight / maxWeight, 0, additionalConsumptionAtMaxWeight); |
|
|
|
|
|
|
|
|
|
return distance * (baseConsumption + weightRelatedConsumption + elevationRelatedConsumption) |
|
|
|
|
return distance * (baseConsumption + weightRelatedConsumption) + potentialEnergy; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
solarPower(irradiance: number): number { |
|
|
|
@ -55,7 +56,7 @@ namespace Simulator {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
outing.distance = dailyRatio * this.dailyDistance; |
|
|
|
|
outing.ascendingElevation = this.dailyAscendingElevation; |
|
|
|
|
outing.ascendingElevation = dailyRatio * this.dailyAscendingElevation; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -92,7 +93,7 @@ namespace Simulator {
|
|
|
|
|
|
|
|
|
|
planning.getOuting(day % 7, hour, outing); |
|
|
|
|
|
|
|
|
|
let consumption = vehicle.motorConsumption(outing.distance, outing.ascendingElevation); |
|
|
|
|
let consumption = outing.distance > 0 ? vehicle.motorConsumption(outing.distance, outing.ascendingElevation) : 0; |
|
|
|
|
let production = vehicle.solarPower(solarIrradiance[hourIdx]) * 1.0; // produced energy in Wh is equal to power (W) multiplied by time (h)
|
|
|
|
|
|
|
|
|
|
result.totalProducedSolarEnergy += production; |
|
|
|
|