A simple interface for visualizing the marginal effects on fuel combustion given a change in vehicle attributes.
forked from mtaptich's block: Bus Fuel Consumption
A simple interface for visualizing the marginal effects on fuel combustion given a change in vehicle attributes.
forked from mtaptich's block: Bus Fuel Consumption
<html lang="en"> | |
<head> | |
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script> | |
<style type="text/css"> | |
body { | |
width: 1024px; | |
margin-top: 0; | |
margin: auto; | |
font-family: "Lato", "PT Serif", serif; | |
color: #222222; | |
padding: 0; | |
font-weight: 300; | |
line-height: 33px; | |
-webkit-font-smoothing: antialiased; | |
} | |
.container{ | |
width: 960; | |
} | |
#interface{ | |
left: 0px; | |
position: fixed; | |
width: 720px; | |
float: left; | |
} | |
.side{ | |
position: fixed; | |
left: 735px; | |
width: 200px; | |
top: 40px; | |
text-align: center; | |
} | |
#force_text{ | |
color: #e74c3c; | |
} | |
.line{ | |
fill: none; | |
stroke: #f1c40f; | |
stroke-width: 8px; | |
opacity: 0.9; | |
} | |
.box{ | |
fill:#ecf0f1; | |
stroke: #2c3e50; | |
stroke-dasharray: 2px,2px; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: none; | |
shape-rendering: crispEdges; | |
} | |
.axis text, .label{ | |
font-size: 20px; | |
} | |
.tick line{ | |
opacity: 0.2; | |
stroke: black; | |
} | |
h2{ | |
margin: 0; | |
} | |
</style> | |
<body> | |
<div class="container"> | |
<div id="interface"> </div> | |
<div class="side"> | |
<h2>Bus Controls</h2> | |
<label for="nVel"> | |
Velocity (km/h) = <span id="nvel-value">96</span> | |
<input style="width: 200px;" type="range" min="0" max="150" id="nVel" value="96"> | |
</label> | |
<label for="nMass"> | |
Mass (kg) = <span id="nmass-value">10,000</span> | |
<input style="width: 200px;" type="range" min="9000" max="15500" id="nMass" value="10000" step='80' > | |
</label> | |
<label for="nAcc"> | |
Acceleration (m/s<sup>2</sup>) = <span id="nacc-value">0.1</span> | |
<input style="width: 200px;" type="range" min="0" max="2" id="nAcc" value="0.1" step='0.1'> | |
</label> | |
<label for="nGrade"> | |
Grade (%) = <span id="ngrade-value">0.1</span> | |
<input style="width: 200px;" type="range" min="0" max="6" id="nGrade" value="0.1" step='0.1'> | |
</label> | |
<label for="nArea"> | |
Frontal Area (m<sup>2</sup>) = <span id="narea-value">7</span> | |
<input style="width: 200px;" type="range" min="5" max="10" id="nArea" value="7.2" step='0.5'> | |
</label> | |
<p>Res. Force: <span id='force_text'></span> N</p> | |
</div> | |
</div> | |
<script> | |
//Initialize Parameters | |
var margin = {top: 40, right: 10, bottom: 20, left: 80}, | |
width = 720 - margin.left - margin.right, | |
height = 640 - margin.top - margin.bottom, | |
bbox = {h: height , w: width, mt: 0}, | |
formatNumber = d3.format(",d"); | |
var vel = 96/3.6, mass = 10000, acceleration = 0, grade = 0, n = 30, BSFC = 200, A =7.2; | |
var data = []; | |
for (var i = 0; i < n; i++) data[i] = 1.88; | |
var x = d3.scale.linear() | |
.domain([0, n - 1]) | |
.range([0, width]); | |
var y = d3.scale.linear() | |
.domain([0, 30]) | |
.range([height, 0]).nice(); | |
var line = d3.svg.line() | |
.x(function(d, i) { return x(i); }) | |
.y(function(d, i) { return y(d); }) | |
.interpolate("monotone"); | |
var svg = d3.select("#interface").append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
svg.append("rect") | |
.attr("width", bbox.w) | |
.attr("height", bbox.h) | |
.attr('y', bbox.mt) | |
.attr('class', 'box'); | |
svg.append("defs").append("clipPath") | |
.attr("id", "clip") | |
.append("rect") | |
.attr("width", width) | |
.attr("height", height); | |
svg.append("g") | |
.attr("class", "y axis") | |
.call(d3.svg.axis().scale(y).orient("left").innerTickSize(-width).outerTickSize(10).tickPadding(10)); | |
var path = svg.append("g") | |
.attr("clip-path", "url(#clip)") | |
.append("path") | |
.data([data]) | |
.attr("class", "line") | |
.attr("d", line); | |
svg.append("text") | |
.attr("class", "label") | |
.attr("text-anchor", "end") | |
.attr("x", -2) | |
.attr("y", -70) | |
.attr("dy", ".90em") | |
.attr("transform", "rotate(-90)") | |
.text("Bus Fuel Usage, (g fuel / sec)"); | |
fuel(); | |
function fuel() { | |
var Cr = 0.005; // Coeffcient of rolling resistance | |
var Cd = 0.06; //drag coefficient | |
var epsi = 0.95; //transmission efficiency | |
var rho_air = 1.1839; //kg/m^3 | |
var sinetheta = grade/100;//to radians | |
v1 = mass*acceleration; | |
v2 = mass* 9.81 *sinetheta; | |
v3 = mass*9.81*Cr; | |
//Simple Engine Model | |
Fres = (v1 + v2 + v3 + 0.5 * Cd * A * rho_air * (vel)*(vel))/1000 // kilonewton | |
Pacc = 15; //kwh/h | |
P = Fres*vel/epsi + Pacc; //kw | |
fuel_output = P * BSFC/3600; | |
// push a new data point onto the back | |
data.push(fuel_output); | |
d3.select("#force_text").text(formatNumber(Math.round(Fres*1000/100)*100)); | |
// redraw the line, and slide it to the left | |
path | |
.attr("d", line) | |
.attr("transform", null) | |
.transition() | |
.duration(500) | |
.ease("linear") | |
.attr("transform", "translate(" + x(-1) + ")") | |
.each("end", fuel); | |
// pop the old data point off the front | |
data.shift(); | |
} | |
// Velocity | |
d3.select("#nVel").on("input", function() { | |
vel = +this.value/3.6 | |
d3.select('#nvel-value').text(+this.value); | |
}); | |
d3.select("#nMass").on("input", function() { | |
mass = +this.value | |
d3.select('#nmass-value').text(formatNumber(+this.value)); | |
}); | |
d3.select("#nAcc").on("input", function() { | |
acceleration = +this.value | |
d3.select('#nacc-value').text(+this.value); | |
}); | |
d3.select("#nGrade").on("input", function() { | |
grade = +this.value | |
d3.select('#ngrade-value').text(+this.value); | |
}); | |
d3.select("#nArea").on("input", function() { | |
A = +this.value | |
d3.select('#narea-value').text(+this.value); | |
}); | |
d3.select(self.frameElement).style("height", (640) + "px"); | |
d3.select(self.frameElement).style("width", (960) + "px"); | |
</script> | |
</body> | |
</html> |