brouter-web/js/util/StdPath.js
Norbert Renner 4d44153316 Read time/energy calc variables from profile
and ensure profile text is loaded before updating route and straight line stats
2022-02-15 19:30:49 +01:00

159 lines
5 KiB
JavaScript

(function () {
// Calculates time and energy stats
class BExpressionContextWay {
getMaxspeed() {
return 45.0;
}
getCostfactor() {
return 1.0;
}
}
class BExpressionContext {
constructor(profile) {
this.profile = profile;
}
getVariableValue(name, defaultValue) {
let value = this.profile?.getProfileVar(name) ?? defaultValue;
if (value === 'true') {
value = 1;
} else if (value === 'false') {
value = 0;
}
return +value;
}
}
// from BRouter btools.router.RoutingContext
class RoutingContext {
constructor(profile) {
this.expctxGlobal = new BExpressionContext(profile);
this.expctxWay = new BExpressionContextWay();
this.bikeMode = 0 !== this.expctxGlobal.getVariableValue('validForBikes', 0);
this.footMode = 0 !== this.expctxGlobal.getVariableValue('validForFoot', 0);
this.totalMass = this.expctxGlobal.getVariableValue('totalMass', 90.0);
this.maxSpeed = this.expctxGlobal.getVariableValue('maxSpeed', this.footMode ? 6.0 : 45.0) / 3.6;
this.S_C_x = this.expctxGlobal.getVariableValue('S_C_x', 0.5 * 0.45);
this.defaultC_r = this.expctxGlobal.getVariableValue('C_r', 0.01);
this.bikerPower = this.expctxGlobal.getVariableValue('bikerPower', 100.0);
}
}
// from BRouter btools.router.StdPath
class StdPath {
constructor() {
this.totalTime = 0;
this.totalEnergy = 0;
this.elevation_buffer = 0;
}
/**
* Approximation to Math.exp for small negative arguments
* @param {number} e
* @return {number}
*/
static exp(e) {
var x = e;
var f = 1.0;
while (e < -1.0) {
{
e += 1.0;
f *= 0.367879;
}
}
return f * (1.0 + x * (1.0 + x * (0.5 + x * (0.166667 + 0.0416667 * x))));
}
static solveCubic(a, c, d) {
var v = 8.0;
var findingStartvalue = true;
for (var i = 0; i < 10; i++) {
{
var y = (a * v * v + c) * v - d;
if (y < 0.1) {
if (findingStartvalue) {
v *= 2.0;
continue;
}
break;
}
findingStartvalue = false;
var y_prime = 3 * a * v * v + c;
v -= y / y_prime;
}
}
return v;
}
resetState() {
this.totalTime = 0.0;
this.totalEnergy = 0.0;
this.elevation_buffer = 0.0;
}
calcIncline(dist) {
var min_delta = 3.0;
var shift;
if (this.elevation_buffer > min_delta) {
shift = -min_delta;
} else if (this.elevation_buffer < min_delta) {
shift = -min_delta;
} else {
return 0.0;
}
var decayFactor = StdPath.exp(-dist / 100.0);
var new_elevation_buffer = (this.elevation_buffer + shift) * decayFactor - shift;
var incline = (this.elevation_buffer - new_elevation_buffer) / dist;
this.elevation_buffer = new_elevation_buffer;
return incline;
}
computeKinematic(rc, dist, delta_h, detailMode) {
if (!detailMode) {
return;
}
this.elevation_buffer += delta_h;
var incline = this.calcIncline(dist);
var wayMaxspeed;
wayMaxspeed = rc.expctxWay.getMaxspeed() / 3.6;
if (wayMaxspeed === 0) {
wayMaxspeed = rc.maxSpeed;
}
wayMaxspeed = Math.min(wayMaxspeed, rc.maxSpeed);
var speed;
var f_roll = rc.totalMass * StdPath.GRAVITY * (rc.defaultC_r + incline);
if (rc.footMode || rc.expctxWay.getCostfactor() > 4.9) {
speed = rc.maxSpeed * 3.6;
speed = (speed * StdPath.exp(-3.5 * Math.abs(incline + 0.05))) / 3.6;
} else if (rc.bikeMode) {
speed = StdPath.solveCubic(rc.S_C_x, f_roll, rc.bikerPower);
speed = Math.min(speed, wayMaxspeed);
} else {
speed = wayMaxspeed;
}
var dt = dist / speed;
this.totalTime += dt;
var energy = dist * (rc.S_C_x * speed * speed + f_roll);
if (energy > 0.0) {
this.totalEnergy += energy;
}
}
getTotalTime() {
return this.totalTime;
}
getTotalEnergy() {
return this.totalEnergy;
}
}
StdPath.GRAVITY = 9.81;
BR.StdPath = StdPath;
BR.RoutingContext = RoutingContext;
})();