Skip to content

Instantly share code, notes, and snippets.

@bmershon
Last active October 24, 2016 20:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bmershon/0fe5edad0d2d621e0ae8 to your computer and use it in GitHub Desktop.
Save bmershon/0fe5edad0d2d621e0ae8 to your computer and use it in GitHub Desktop.
Orbits

The Forest Fire Sensor Network simulation required the senors to be in motion. What type of motion should be used? I considered the following:

  • Random Brownian Motion.
  • Wandering behavior as described by Craig Reynolds, which I first encountered a couple of years ago while reading Daniel Shiffman's Nature of Code
  • Predictable orbits resulting from sin and cosine functions

I decided to give the orbits approach a try. Dynamic sensor networks are interesting to visualize because the changing coverage of a region seems highly dependent on the underlying motion of the sensors. A predictable orbit for each sensor allows for the possibility that an evader wishing to remain in the "holes" of the coverage blanket could predict where each hole might form.

We see again the question presented in Robert Ghrist's paper:

The evasion problem for this scenario is whether an unknown evader can navigate through holes in the sensor cover without being detected.

<!DOCTYPE html>
<meta charset="utf-8">
<title>Dynamic Sensor Network</title>
<style>
svg {
position: absolute;
top: 0;
left: 0;
}
</style>
<body>
</body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var color = d3.scale.category10();
var width = 960,
height = 500;
var numPoints = 10;
var data = d3.range(numPoints).map(function() {
return {xloc: 0, yloc: 0, a: Math.random(), b: Math.random(),
xOffset: Math.random(), yOffset: Math.random(), theta: Math.random() * Math.PI};
});
var x = d3.scale.linear()
.domain([-1.2, 1.2])
.range([0, height]);
var y = d3.scale.linear()
.domain([-1.2, 1.2])
.range([0, height]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", function(d) { return "translate(" + width/4 + "," + 0 + ")"; })
var circle = svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("stroke", "#000")
.attr("stroke-width", "2px")
.attr("r", 4)
var pathData = calculatePaths(data);
var line = d3.svg.line();
var path = svg.selectAll(".line")
.data(pathData)
.enter().append("path")
.attr("d", function(d) {
return line(d);
})
.attr("fill", "none")
.attr("stroke", "#000")
console.log(calculatePaths(data));
function calculatePaths(data) {
var pointArray = [],
dt = 0.01, i, t;
var dataLength = data.length;
for (i = 0; i < dataLength; i++){
var d = data[i], arrayToAdd = [];
for (t = 0; t < Math.PI * 2; t+= dt) {
// sample from next time step, add position
arrayToAdd.push([x(d.a*Math.cos(t + d.xOffset * Math.PI * 2)), y(d.b * Math.sin(t + d.yOffset * Math.PI * 2))]);
}
pointArray.push(arrayToAdd);
}
return pointArray;
}
d3.timer(function() {
svg.selectAll("polygon").remove();
data.forEach(function(d) {
d.xloc = d.a*Math.cos(d.theta + d.xOffset * Math.PI * 2);
d.yloc = d.b*Math.sin(d.theta + d.yOffset * Math.PI * 2);
d.theta += 0.02;
});
circle
.attr("cx", function(d) { return x(d.xloc); })
.attr("cy", function(d) { return y(d.yloc); })
.attr("fill", function(d, i) {
return color(i)
});
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment