A simple interface for visualizing the marginal effects on fuel combustion given a change in vehicle attributes.
Last active
March 16, 2016 02:28
-
-
Save mtaptich/024462262babe91764d1 to your computer and use it in GitHub Desktop.
Bus Fuel Consumption
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment