Skip to content

Instantly share code, notes, and snippets.

@k4kfh
Last active November 28, 2015 05:49
Show Gist options
  • Save k4kfh/615aba5fd882777596dc to your computer and use it in GitHub Desktop.
Save k4kfh/615aba5fd882777596dc to your computer and use it in GitHub Desktop.
ZephyrCab prototype Example
prototype: {
"builder": "EMD", //This is displayed to the client and can be anything
"name": "F7-A", //This is also displayed to the client and can be anything
"type": "locomotive", //This must be "locomotive"
"weight": 250000, //Weight of the locomotive in lbs
"maxHP": 1500, //Horsepower of the locomotive
"notchRPM": [300, 362, 425, 487, 550, 613, 675, 738, 800], //This is an array of RPMs for the notch values. Start with idle, end with RUN8, for a total of 9 array items.
"notchMaxSpeeds": [null, 7.5, 15, 22.5, 30, 37.5, 45, 52.5, 60], //This is an array of max speeds for the notch values. Set the first item to null. This is so we can look things up by just feeding the notch into it, but the max speed for IDLE is obviously zero.
"engineRunning": 0, //This is NOT A BOOLEAN! This is a binary value (0 is off, 1 is on). You should set this to 0, sim.js will redefine it as needed.
"fuel": {
usage: [3.5, 6.5, 14.5, 23.4, 33.3, 45.7, 59.6, 75.3, 93.1], //This is an array in of fuel consumption in Gal/Hr.
capacity: 1200, //Total fuel tank capacity in gallons
},
air: {
reservoir: {
main: {}, //As of right now, we don't have any properties for this, but we plan to in the future.
},
compressor: {
limits: {
lower: 130, //This is the point at which the compressor will turn back on and fill up the air reservoir (psi)
upper: 140, //This is the point at which the compressor will turn off (psi)
},
flowrate: 0.28, //This is cfm/rpm, derived from "255cfm @ 900rpm for an SD45" according to Mr. Al Krug
needsEngine: true, //This variable tells if the compressor requires the engine to be running or not. If your compressor is directly driven by the prime mover this should be true.
}
},
"calc": {
/*
This is an object containing several functions that I am leaving open to developers.
Among these are tractive effort and a few other things that could be calculated in a number of different ways.
There's no one-size-fits-all method, so I am putting this in the hands of devs. As long as your function accepts the same arguments as this standard, and returns the same things, how it works is up to you.
*/
"te": function (speed, trainPosition) { //This function calculates tractive effort given speed and trainPosition. You can use trainPosition to access other prototype object attributes.
/*
This example uses an equation from a Virginia Tech paper.
It is important to note that the value from this function will be used, unaltered, in the physics engine. You cannot forget to take into account the reverser. This is easy; all you have to do is multiply your calculated value by the global variable: reverser . If we're in neutral, this will yield 0. In forward, it will do nothing. In reverse, it will make your number negative. Simple, but very important.
*/
//First we need to convert the speed to KM/HR.
var efficiency = 0.72;
var horsepower = train.all[trainPosition].prototype.realtime.horsepower * notch.state;
var speedSI = speed * 1.60934;
/*
Now we must actually use the formula from the Virginia Tech paper. It states:
T = 2650((np/v))
T is tractive effort in Newtons.
n is the efficiency coefficient (unitless)
p is the output horsepower
v is the speed in km/hr
*/
var teNewtons = 2650 * ((efficiency * horsepower) / (speedSI))
//Now that we have the tractive effort in Newtons, we must convert it to pounds.
var teLbs = 0.224809 * teNewtons * reverser;
//This is a measure of protection since the equation creates a curve that moves upwards too sharply
if (speed < 8.9) {
teLbs = 56500 * (notch.state / 8) * reverser;
}
return teLbs;
}
},
"realtime": { //The physics engine stores real-time information in this object's children.
speed: 0, //This is defined as 0 to start; sim.js will redefine as needed.
horsepower: 0, //This represents the OUTPUT HORSEPOWER, not the maximum. Set it to 0, sim.js will redefine as needed.
"grade": 0, //IMPORTANT : This can be set to any grade percentage, but it should be as a percent not as a decimal. 1 for a 1% grade, NOT 0.01!
fuel: {
status: 1200, //Set this to the max fuel value (in gallons). This represents the current fuel level, in gallons, so if you don't set it to the max you won't be starting off full.
notifiedOfEmptyTank: false, //This is a system variable that sim.js uses. Please define it as false.
},
air: {
compressor: {
calc: function (trainPosition) {
/*
This function should calculate and set the flow rate in CFM. You can find out any prototype property since we gave it the trainPosition. You should NOT multiply this calculation by running or engineRunning; sim.js will do that!
In an F7, the compressor is driven directly by the prime mover, so this calculation will look at RPM and go from there. If you had an engine with an electric compressor, that would be different.
Additionally, if you had an engine with an electric compressor, you would need to set .prototype.air.needsEngine to false.
*/
var rpm = train.all[trainPosition].prototype.realtime.rpm
var cfm = rpm * 0.283; //This is a figure that I got from "255cu ft/min @ 900rpm" from Al Krug.
return cfm;
},
flowrate: 0, //Set this to 0
running: 0, //This works a lot like prototype.engineRunning
},
reservoir: {
//Realtime data about the main reservoir is stored here
main: {
pressure: 0,
}
}
},
},
"gauges": {
/*
These objects contain every parameter for generating all the dashboard gauges.
ZephyrCab uses this gauge library: https://github.com/Mikhus/canv-gauge
Please see the documentation here for information on these parameters. The only parameter that will be overriden is renderTo.
https://github.com/Mikhus/canv-gauge/wiki/Gauge-API
*/
"speedometer": {
"title": "Speed",
"minValue": 0,
"maxValue": 120,
"majorTicks": ['0', '20', '40', '60', '80', '80', '100', '120'],
"minorTicks": 10,
"strokeTicks": true,
"units": "MPH",
"valueFormat": {
int: 3,
dec: 0
},
"glow": false,
"animation": {
delay: 0,
duration: 500,
fn: "quad",
},
"colors": {
plate: '#fff',
majorTicks: '#444',
minorTicks: '#666',
title: '#888',
units: '#888',
numbers: '#444',
needle: {
start: 'rgba(240, 128, 128, 1)',
end: 'rgba(255, 160, 122, .9)'
}
},
highlights: [],
},
"rpm": {
"title": "",
"minValue": 0,
"maxValue": 900,
"majorTicks": ['0', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
"minorTicks": 10,
"strokeTicks": true,
"units": "RPM",
"valueFormat": {
int: 3,
dec: 0
},
"glow": false,
"animation": {
delay: 0,
duration: 1200,
fn: "cycle",
},
"colors": {
plate: '#fff',
majorTicks: '#444',
minorTicks: '#666',
title: '#888',
units: '#888',
numbers: '#444',
needle: {
start: 'rgba(240, 128, 128, 1)',
end: 'rgba(255, 160, 122, .9)'
}
},
highlights: [],
},
"fuel": {
"title": "Fuel",
"minValue": 0,
"maxValue": 1200,
"majorTicks": ['0', '100', '200', '300', '400', '500', '600', '700', '800', '900', '1000', '1100', '1200'],
"minorTicks": 10,
"strokeTicks": true,
"units": "Gal.",
"valueFormat": {
int: 4,
dec: 0
},
"glow": false,
"animation": {
delay: 0,
duration: 500,
fn: "quad",
},
"colors": {
plate: '#fff',
majorTicks: '#444',
minorTicks: '#666',
title: '#888',
units: '#888',
numbers: '#444',
needle: {
start: 'rgba(240, 128, 128, 1)',
end: 'rgba(255, 160, 122, .9)'
}
},
highlights: [],
},
},
//This object contains a variety of coefficients for a variety of different things. Right now we only store rolling resistance here, but when adhesion is finished all that info will be stored here, along with any other coefficients we need.
"coefficientOf": {
rollingResistance: 0.0015,
},
}
prototype: {
"builder": "EMD", //This is displayed to the client and can be anything
"name": "F7-A", //This is also displayed to the client and can be anything
"type": "locomotive", //This must be "locomotive"
"weight": 250000, //Weight of the locomotive in lbs
"maxHP": 1500, //Horsepower of the locomotive
"notchRPM": [300, 362, 425, 487, 550, 613, 675, 738, 800], //This is an array of RPMs for the notch values. Start with idle, end with RUN8, for a total of 9 array items.
"notchMaxSpeeds": [null, 7.5, 15, 22.5, 30, 37.5, 45, 52.5, 60], //This is an array of max speeds for the notch values. Set the first item to null. This is so we can look things up by just feeding the notch into it, but the max speed for IDLE is obviously zero.
"engineRunning": 0, //This is NOT A BOOLEAN! This is a binary value (0 is off, 1 is on). You should set this to 0, sim.js will redefine it as needed.
"fuel": {
usage: [3.5, 6.5, 14.5, 23.4, 33.3, 45.7, 59.6, 75.3, 93.1], //This is an array in of fuel consumption in Gal/Hr.
capacity: 1200, //Total fuel tank capacity in gallons
},
"calc": {
/*
This is an object containing several functions that I am leaving open to developers.
Among these are tractive effort and a few other things that could be calculated in a number of different ways.
There's no one-size-fits-all method, so I am putting this in the hands of devs. As long as your function accepts the same arguments as this standard, and returns the same things, how it works is up to you.
*/
"te": function(speed, trainPosition) { //This function calculates tractive effort given speed and trainPosition. You can use trainPosition to access other prototype object attributes.
/*
This example uses an equation from a Virginia Tech paper.
It is important to note that the value from this function will be used, unaltered, in the physics engine. You cannot forget to take into account the reverser. This is easy; all you have to do is multiply your calculated value by the global variable: reverser . If we're in neutral, this will yield 0. In forward, it will do nothing. In reverse, it will make your number negative. Simple, but very important.
*/
//First we need to convert the speed to KM/HR.
var efficiency = 0.72;
var horsepower = train.all[trainPosition].prototype.realtime.horsepower * notch.state;
var speedSI = speed * 1.60934;
/*
Now we must actually use the formula from the Virginia Tech paper. It states:
T = 2650((np/v))
T is tractive effort in Newtons.
n is the efficiency coefficient (unitless)
p is the output horsepower
v is the speed in km/hr
*/
var teNewtons = 2650 * ((efficiency * horsepower) / (speedSI))
//Now that we have the tractive effort in Newtons, we must convert it to pounds.
var teLbs = 0.224809 * teNewtons * reverser
//This is a measure of protection since the equation creates a curve that moves upwards too sharply
if (speed < 8.9) {
teLbs = 56500 * (notch.state / 8) * reverser;
}
return teLbs;
}
},
"realtime": { //The physics engine stores real-time information in this object's children.
speed: 0, //This is defined as 0 to start; sim.js will redefine as needed.
horsepower: 0, //This represents the OUTPUT HORSEPOWER, not the maximum. Set it to 0, sim.js will redefine as needed.
"grade": 0, //IMPORTANT : This can be set to any grade percentage, but it should be as a percent not as a decimal. 1 for a 1% grade, NOT 0.01!
fuel: {
status: 1200, //Set this to the max fuel value (in gallons). This represents the current fuel level, in gallons, so if you don't set it to the max you won't be starting off full.
notifiedOfEmptyTank: false, //This is a system variable that sim.js uses. Please define it as false.
},
},
"gauges": {
/*
These objects contain every parameter for generating all the dashboard gauges.
ZephyrCab uses this gauge library: https://github.com/Mikhus/canv-gauge
Please see the documentation here for information on these parameters. The only parameter that will be overriden is renderTo.
https://github.com/Mikhus/canv-gauge/wiki/Gauge-API
*/
"speedometer": {
"title": "Speed",
"minValue": 0,
"maxValue": 120,
"majorTicks": ['0', '20', '40', '60', '80', '80', '100', '120'],
"minorTicks": 10,
"strokeTicks": true,
"units": "MPH",
"valueFormat": {
int: 3,
dec: 0
},
"glow": false,
"animation": {
delay: 0,
duration: 500,
fn: "quad",
},
"colors": {
plate: '#fff',
majorTicks: '#444',
minorTicks: '#666',
title: '#888',
units: '#888',
numbers: '#444',
needle: {
start: 'rgba(240, 128, 128, 1)',
end: 'rgba(255, 160, 122, .9)'
}
},
highlights: [],
},
"rpm": {
"title": "",
"minValue": 0,
"maxValue": 900,
"majorTicks": ['0', '100', '200', '300', '400', '500', '600', '700', '800', '900'],
"minorTicks": 10,
"strokeTicks": true,
"units": "RPM",
"valueFormat": {
int: 3,
dec: 0
},
"glow": false,
"animation": {
delay: 0,
duration: 1200,
fn: "cycle",
},
"colors": {
plate: '#fff',
majorTicks: '#444',
minorTicks: '#666',
title: '#888',
units: '#888',
numbers: '#444',
needle: {
start: 'rgba(240, 128, 128, 1)',
end: 'rgba(255, 160, 122, .9)'
}
},
highlights: [],
},
"fuel": {
"title": "Fuel",
"minValue": 0,
"maxValue": 1200,
"majorTicks": ['0', '100', '200', '300', '400', '500', '600', '700', '800', '900', '1000', '1100', '1200'],
"minorTicks": 10,
"strokeTicks": true,
"units": "Gal.",
"valueFormat": {
int: 4,
dec: 0
},
"glow": false,
"animation": {
delay: 0,
duration: 500,
fn: "quad",
},
"colors": {
plate: '#fff',
majorTicks: '#444',
minorTicks: '#666',
title: '#888',
units: '#888',
numbers: '#444',
needle: {
start: 'rgba(240, 128, 128, 1)',
end: 'rgba(255, 160, 122, .9)'
}
},
highlights: [],
},
},
//This object contains a variety of coefficients for a variety of different things. Right now we only store rolling resistance here, but when adhesion is finished all that info will be stored here, along with any other coefficients we need.
"coefficientOf": {
rollingResistance: 0.0015,
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment