Added map server
Esse commit está contido em:
+162
@@ -0,0 +1,162 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<style type="text/css" media="screen">
|
||||
button.active{
|
||||
background:red;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/leaflet.css" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="phone-position">
|
||||
Phone:
|
||||
<span class='lat'></span>,
|
||||
<span class='lon'></span>
|
||||
(+/-<span class='accuracy'></span>m)
|
||||
</div>
|
||||
<div id="drone-position">
|
||||
Drone:
|
||||
<span class='lat'></span>,
|
||||
<span class='lon'></span>
|
||||
<p>Distance:
|
||||
<span class='distance'></span>
|
||||
</p>
|
||||
</div>
|
||||
<button id='takeoff'>Takeoff</button>
|
||||
<button id='land'>Land</button>
|
||||
<button id='move'>Move</button>
|
||||
<button id='stop'>stop</button>
|
||||
<div id="map" style="width: 1000px; height: 600px"></div>
|
||||
|
||||
|
||||
<script src="http://maps.google.com/maps/api/js?v=3.2&sensor=false"></script>
|
||||
<script src="leaflet.js"></script>
|
||||
<script src="leaflet-google.js"></script>
|
||||
|
||||
<script src="jquery.js"></script>
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script>
|
||||
var socket = io.connect('/');
|
||||
var lat, lon, map, laptop, drone, phone, phonePath;
|
||||
var stop = true;
|
||||
|
||||
var phoneIcon = L.icon({
|
||||
iconUrl: 'images/iphone.png'
|
||||
});
|
||||
|
||||
var laptopIcon = L.icon({
|
||||
iconUrl: 'images/laptop.png'
|
||||
});
|
||||
|
||||
var droneIcon = L.icon({
|
||||
iconUrl: 'images/copter.png'
|
||||
});
|
||||
|
||||
|
||||
function initMap(lat, lon){
|
||||
map = L.map('map').setView([lat, lon], 20);
|
||||
|
||||
var googleLayer = new L.Google('SATELLITE');
|
||||
map.addLayer(googleLayer);
|
||||
|
||||
laptop = L.marker([lat, lon], {icon: laptopIcon}).addTo(map)
|
||||
}
|
||||
|
||||
function onPositionError(err){
|
||||
console.log(err)
|
||||
}
|
||||
|
||||
$(function(){
|
||||
$('#takeoff').click(function(){
|
||||
socket.emit('takeoff')
|
||||
})
|
||||
$('#land').click(function(){
|
||||
socket.emit('land')
|
||||
})
|
||||
$('#move').click(function(){
|
||||
stop = false;
|
||||
})
|
||||
$('#stop').click(function(){
|
||||
stop = true;
|
||||
})
|
||||
})
|
||||
|
||||
socket.on('connect', function(){
|
||||
|
||||
|
||||
console.log('connected')
|
||||
|
||||
socket.on('position', function(data){
|
||||
if(data.lat != undefined){
|
||||
if (drone == null){
|
||||
drone = L.marker([data.lat, data.lon], {icon: droneIcon}).addTo(map)
|
||||
}
|
||||
drone.setLatLng([data.lat, data.lon])
|
||||
$('#drone-position .lat').text(data.lat)
|
||||
$('#drone-position .lon').text(data.lon)
|
||||
$('#drone-position .distance').text(data.distance)
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('phone', function(data){
|
||||
if(data.lat != undefined){
|
||||
if (laptop == null){
|
||||
initMap(data.lat, data.lon)
|
||||
}
|
||||
if (phone == null){
|
||||
phone = L.marker([data.lat, data.lon], {icon: phoneIcon}).addTo(map)
|
||||
phonePath = L.polyline([[data.lat, data.lon]], {color: 'red'}).addTo(map);
|
||||
} else {
|
||||
phone.setLatLng([data.lat, data.lon])
|
||||
phonePath.addLatLng([data.lat, data.lon])
|
||||
}
|
||||
$('#phone-position .lat').text(data.lat)
|
||||
$('#phone-position .lon').text(data.lon)
|
||||
$('#phone-position .accuracy').text(data.accuracy)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
// L.marker([51.5, -0.09]).addTo(map)
|
||||
//
|
||||
// .bindPopup("<b>Hello world!</b><br />I am a popup.").openPopup();
|
||||
//
|
||||
// L.circle([51.508, -0.11], 500, {
|
||||
//
|
||||
// color: 'red',
|
||||
//
|
||||
// fillColor: '#f03',
|
||||
//
|
||||
// fillOpacity: 0.5
|
||||
//
|
||||
// }).addTo(map).bindPopup("I am a circle.");
|
||||
//
|
||||
// L.polygon([
|
||||
//
|
||||
// [51.509, -0.08],
|
||||
//
|
||||
// [51.503, -0.06],
|
||||
//
|
||||
// [51.51, -0.047]
|
||||
//
|
||||
// ]).addTo(map).bindPopup("I am a polygon.");
|
||||
|
||||
// L.MultiPolyline([[51.509, -0.08],[51.503, -0.06],[51.51, -0.047]]).addTo(map)
|
||||
//
|
||||
// var popup = L.popup();
|
||||
//
|
||||
// function onMapClick(e) {
|
||||
// popup
|
||||
// .setLatLng(e.latlng)
|
||||
// .setContent("You clicked the map at " + e.latlng.toString())
|
||||
// .openOn(map);
|
||||
// }
|
||||
// map.on('click', onMapClick);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+68
-49
@@ -7,55 +7,6 @@ var client = arDrone.createClient();
|
||||
|
||||
client.config('general:navdata_demo', 'FALSE');
|
||||
|
||||
client.takeoff()
|
||||
|
||||
var targetLat, targetLon, targetYaw, cyaw;
|
||||
|
||||
setTimeout(function(){
|
||||
// end of garden: 51.392059 -2.3224394
|
||||
targetLat = 51.392059
|
||||
targetLon = -2.3224394
|
||||
}, 6000)
|
||||
|
||||
var handleNavData = function(data){
|
||||
if ( data.demo == null) return;
|
||||
|
||||
var currentLat = data.gps.latitude
|
||||
var currentLon = data.gps.longitude
|
||||
console.log('lat/lon:', currentLat, currentLon);
|
||||
|
||||
var currentYaw = data.demo.rotation.yaw;
|
||||
|
||||
if (targetLat == null || targetLon == null || currentYaw == null || currentLat == null || currentLon == null) return;
|
||||
|
||||
var bearing = vincenty.distVincenty(currentLat, currentLon, targetLat, targetLon)
|
||||
|
||||
if(bearing.distance > 1){
|
||||
console.log('distance', bearing.distance)
|
||||
console.log('bearing:', bearing.initialBearing)
|
||||
targetYaw = bearing.initialBearing
|
||||
|
||||
console.log('currentYaw:', currentYaw);
|
||||
var eyaw = targetYaw - currentYaw;
|
||||
console.log('eyaw:', eyaw);
|
||||
|
||||
var uyaw = yawPID.getCommand(eyaw);
|
||||
console.log('uyaw:', uyaw);
|
||||
|
||||
var cyaw = within(uyaw, -1, 1);
|
||||
console.log('cyaw:', cyaw);
|
||||
|
||||
client.clockwise(cyaw)
|
||||
client.front(0.05)
|
||||
} else {
|
||||
targetYaw = null
|
||||
client.stop()
|
||||
console.log('Reached ', targetLat, targetLon)
|
||||
}
|
||||
}
|
||||
|
||||
client.on('navdata', handleNavData);
|
||||
|
||||
function within(x, min, max) {
|
||||
if (x < min) {
|
||||
return min;
|
||||
@@ -66,3 +17,71 @@ function within(x, min, max) {
|
||||
}
|
||||
}
|
||||
|
||||
// client.takeoff()
|
||||
|
||||
function gpsNavigator(client){
|
||||
this.targetLat = null;
|
||||
this.targetLon = null;
|
||||
this.targetYaw = null;
|
||||
this.callback = null;
|
||||
|
||||
this.client = client;
|
||||
|
||||
this.waypoint = function(lat, lon, cb){
|
||||
this.targetLat = lat
|
||||
this.targetLon = lon
|
||||
this.callback = cb
|
||||
}
|
||||
|
||||
this.handleNavData = function(data){
|
||||
if (data.demo == null) return;
|
||||
|
||||
var currentLat = data.gps.latitude
|
||||
var currentLon = data.gps.longitude
|
||||
console.log('lat/lon:', currentLat, currentLon);
|
||||
|
||||
var currentYaw = data.demo.rotation.yaw;
|
||||
|
||||
if (targetLat == null || targetLon == null || currentYaw == null || currentLat == null || currentLon == null) return;
|
||||
|
||||
var bearing = vincenty.distVincenty(currentLat, currentLon, targetLat, targetLon)
|
||||
|
||||
if(bearing.distance > 0.5){
|
||||
console.log('distance', bearing.distance)
|
||||
console.log('bearing:', bearing.initialBearing)
|
||||
this.targetYaw = bearing.initialBearing
|
||||
|
||||
console.log('currentYaw:', currentYaw);
|
||||
var eyaw = targetYaw - currentYaw;
|
||||
console.log('eyaw:', eyaw);
|
||||
|
||||
var uyaw = yawPID.getCommand(eyaw);
|
||||
console.log('uyaw:', uyaw);
|
||||
|
||||
var cyaw = within(uyaw, -1, 1);
|
||||
console.log('cyaw:', cyaw);
|
||||
|
||||
this.client.clockwise(cyaw)
|
||||
this.client.front(0.2)
|
||||
} else {
|
||||
this.targetYaw = null
|
||||
this.targetLat = null;
|
||||
this.targetLon = null;
|
||||
this.client.stop()
|
||||
this.callback()
|
||||
console.log('Reached ', targetLat, targetLon)
|
||||
}
|
||||
}
|
||||
this.client.on('navdata', this.handleNavData);
|
||||
}
|
||||
|
||||
var gps = new gpsNavigator(client)
|
||||
|
||||
gps.waypoint(51.392059, -2.3224394, function(){
|
||||
console.log('done!')
|
||||
})
|
||||
|
||||
|
||||
|
||||
client.on('navdata', handleNavData);
|
||||
|
||||
|
||||
+3
-1
@@ -5,7 +5,9 @@
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"ar-drone": "git://github.com/andrew/node-ar-drone.git#gps",
|
||||
"node-vincenty": "0.0.6"
|
||||
"node-vincenty": "0.0.6",
|
||||
"socket.io": "~0.9.16",
|
||||
"express": "~3.4.0"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"scripts": {
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<style type="text/css" media="screen">
|
||||
button.active{
|
||||
background:red;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/leaflet.css" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="phone-position">
|
||||
Phone:
|
||||
<span class='lat'></span>,
|
||||
<span class='lon'></span><br/>
|
||||
+/- <span class='accuracy'></span>m
|
||||
</div>
|
||||
<div id="drone-position">
|
||||
Drone:
|
||||
<span class='lat'></span>,
|
||||
<span class='lon'></span>
|
||||
<p>Distance:
|
||||
<span class='distance'></span>
|
||||
</p>
|
||||
</div>
|
||||
<button id='takeoff'>Takeoff</button>
|
||||
<button id='land'>Land</button>
|
||||
<button id='move'>Move</button>
|
||||
<button id='stop'>stop</button>
|
||||
<div id="map" style="width: 600px; height: 400px"></div>
|
||||
|
||||
|
||||
|
||||
<script src="leaflet.js"></script>
|
||||
|
||||
<script src="jquery.js"></script>
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script>
|
||||
var socket = io.connect('/');
|
||||
var lat, lon, map, watch;
|
||||
var stop = true;
|
||||
|
||||
var options = {
|
||||
enableHighAccuracy: true,
|
||||
timeout: 5000,
|
||||
maximumAge: 0
|
||||
};
|
||||
|
||||
function onPositionError(err){
|
||||
console.log(err)
|
||||
}
|
||||
|
||||
function onPositionUpdate(position)
|
||||
{
|
||||
lat = position.coords.latitude;
|
||||
lon = position.coords.longitude;
|
||||
accuracy = position.coords.accuracy;
|
||||
$('#phone-position .lat').text(lat)
|
||||
$('#phone-position .lon').text(lon)
|
||||
$('#phone-position .accuracy').text(accuracy)
|
||||
socket.emit('phone', {lat: lat, lon: lon, accuracy: accuracy})
|
||||
}
|
||||
|
||||
$(function(){
|
||||
|
||||
id = navigator.geolocation.watchPosition(onPositionUpdate, onPositionError, options);
|
||||
|
||||
$('#takeoff').click(function(){
|
||||
socket.emit('takeoff')
|
||||
})
|
||||
$('#land').click(function(){
|
||||
socket.emit('land')
|
||||
})
|
||||
$('#move').click(function(){
|
||||
stop = false;
|
||||
})
|
||||
$('#stop').click(function(){
|
||||
stop = true;
|
||||
})
|
||||
})
|
||||
|
||||
socket.on('connect', function(){
|
||||
|
||||
|
||||
console.log('connected')
|
||||
|
||||
socket.on('position', function(data){
|
||||
// console.log(data)
|
||||
$('#drone-position .lat').text(data.lat)
|
||||
$('#drone-position .lon').text(data.lon)
|
||||
$('#drone-position .distance').text(data.distance)
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 6.7 KiB |
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 4.9 KiB |
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 3.7 KiB |
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 1.7 KiB |
Arquivo binário não exibido.
|
Depois Largura: | Altura: | Tamanho: 797 B |
externo
+6
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* L.TileLayer is used for standard xyz-numbered tile layers.
|
||||
*/
|
||||
L.Google = L.Class.extend({
|
||||
includes: L.Mixin.Events,
|
||||
|
||||
options: {
|
||||
minZoom: 0,
|
||||
maxZoom: 22,
|
||||
tileSize: 256,
|
||||
subdomains: 'abc',
|
||||
errorTileUrl: '',
|
||||
attribution: '',
|
||||
opacity: 1,
|
||||
continuousWorld: false,
|
||||
noWrap: false,
|
||||
},
|
||||
|
||||
// Possible types: SATELLITE, ROADMAP, HYBRID
|
||||
initialize: function(type, options) {
|
||||
L.Util.setOptions(this, options);
|
||||
|
||||
this._type = google.maps.MapTypeId[type || 'SATELLITE'];
|
||||
},
|
||||
|
||||
onAdd: function(map, insertAtTheBottom) {
|
||||
this._map = map;
|
||||
this._insertAtTheBottom = insertAtTheBottom;
|
||||
|
||||
// create a container div for tiles
|
||||
this._initContainer();
|
||||
this._initMapObject();
|
||||
|
||||
// set up events
|
||||
map.on('viewreset', this._resetCallback, this);
|
||||
|
||||
this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this);
|
||||
map.on('move', this._update, this);
|
||||
//map.on('moveend', this._update, this);
|
||||
|
||||
this._reset();
|
||||
this._update();
|
||||
},
|
||||
|
||||
onRemove: function(map) {
|
||||
this._map._container.removeChild(this._container);
|
||||
//this._container = null;
|
||||
|
||||
this._map.off('viewreset', this._resetCallback, this);
|
||||
|
||||
this._map.off('move', this._update, this);
|
||||
//this._map.off('moveend', this._update, this);
|
||||
},
|
||||
|
||||
getAttribution: function() {
|
||||
return this.options.attribution;
|
||||
},
|
||||
|
||||
setOpacity: function(opacity) {
|
||||
this.options.opacity = opacity;
|
||||
if (opacity < 1) {
|
||||
L.DomUtil.setOpacity(this._container, opacity);
|
||||
}
|
||||
},
|
||||
|
||||
_initContainer: function() {
|
||||
var tilePane = this._map._container
|
||||
first = tilePane.firstChild;
|
||||
|
||||
if (!this._container) {
|
||||
this._container = L.DomUtil.create('div', 'leaflet-google-layer leaflet-top leaflet-left');
|
||||
this._container.id = "_GMapContainer";
|
||||
}
|
||||
|
||||
if (true) {
|
||||
tilePane.insertBefore(this._container, first);
|
||||
|
||||
this.setOpacity(this.options.opacity);
|
||||
var size = this._map.getSize();
|
||||
this._container.style.width = size.x + 'px';
|
||||
this._container.style.height = size.y + 'px';
|
||||
this._container.style.zIndex = 0;
|
||||
}
|
||||
},
|
||||
|
||||
_initMapObject: function() {
|
||||
this._google_center = new google.maps.LatLng(0, 0);
|
||||
var map = new google.maps.Map(this._container, {
|
||||
center: this._google_center,
|
||||
zoom: 0,
|
||||
mapTypeId: this._type,
|
||||
disableDefaultUI: true,
|
||||
keyboardShortcuts: false,
|
||||
draggable: false,
|
||||
disableDoubleClickZoom: true,
|
||||
scrollwheel: false,
|
||||
streetViewControl: false
|
||||
});
|
||||
|
||||
var _this = this;
|
||||
this._reposition = google.maps.event.addListenerOnce(map, "center_changed",
|
||||
function() { _this.onReposition(); });
|
||||
|
||||
map.backgroundColor = '#ff0000';
|
||||
this._google = map;
|
||||
},
|
||||
|
||||
_resetCallback: function(e) {
|
||||
this._reset(e.hard);
|
||||
},
|
||||
|
||||
_reset: function(clearOldContainer) {
|
||||
this._initContainer();
|
||||
},
|
||||
|
||||
_update: function() {
|
||||
this._resize();
|
||||
|
||||
var bounds = this._map.getBounds();
|
||||
var ne = bounds.getNorthEast();
|
||||
var sw = bounds.getSouthWest();
|
||||
var google_bounds = new google.maps.LatLngBounds(
|
||||
new google.maps.LatLng(sw.lat, sw.lng),
|
||||
new google.maps.LatLng(ne.lat, ne.lng)
|
||||
);
|
||||
var center = this._map.getCenter();
|
||||
var _center = new google.maps.LatLng(center.lat, center.lng);
|
||||
|
||||
this._google.setCenter(_center);
|
||||
this._google.setZoom(this._map.getZoom());
|
||||
//this._google.fitBounds(google_bounds);
|
||||
},
|
||||
|
||||
_resize: function() {
|
||||
var size = this._map.getSize();
|
||||
if (this._container.style.width == size.x &&
|
||||
this._container.style.height == size.y)
|
||||
return;
|
||||
this._container.style.width = size.x + 'px';
|
||||
this._container.style.height = size.y + 'px';
|
||||
google.maps.event.trigger(this._google, "resize");
|
||||
},
|
||||
|
||||
onReposition: function() {
|
||||
//google.maps.event.trigger(this._google, "resize");
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,467 @@
|
||||
/* required styles */
|
||||
|
||||
.leaflet-map-pane,
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-tile-pane,
|
||||
.leaflet-tile-container,
|
||||
.leaflet-overlay-pane,
|
||||
.leaflet-shadow-pane,
|
||||
.leaflet-marker-pane,
|
||||
.leaflet-popup-pane,
|
||||
.leaflet-overlay-pane svg,
|
||||
.leaflet-zoom-box,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-layer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-container {
|
||||
overflow: hidden;
|
||||
-ms-touch-action: none;
|
||||
}
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
display: block;
|
||||
}
|
||||
/* map is broken in FF if you have max-width: 100% on tiles */
|
||||
.leaflet-container img {
|
||||
max-width: none !important;
|
||||
}
|
||||
/* stupid Android 2 doesn't understand "max-width: none" properly */
|
||||
.leaflet-container img.leaflet-image-layer {
|
||||
max-width: 15000px !important;
|
||||
}
|
||||
.leaflet-tile {
|
||||
filter: inherit;
|
||||
visibility: hidden;
|
||||
}
|
||||
.leaflet-tile-loaded {
|
||||
visibility: inherit;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
|
||||
.leaflet-overlay-pane svg {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.leaflet-tile-pane { z-index: 2; }
|
||||
.leaflet-objects-pane { z-index: 3; }
|
||||
.leaflet-overlay-pane { z-index: 4; }
|
||||
.leaflet-shadow-pane { z-index: 5; }
|
||||
.leaflet-marker-pane { z-index: 6; }
|
||||
.leaflet-popup-pane { z-index: 7; }
|
||||
|
||||
|
||||
/* control positioning */
|
||||
|
||||
.leaflet-control {
|
||||
position: relative;
|
||||
z-index: 7;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-top,
|
||||
.leaflet-bottom {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leaflet-top {
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-right {
|
||||
right: 0;
|
||||
}
|
||||
.leaflet-bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
.leaflet-left {
|
||||
left: 0;
|
||||
}
|
||||
.leaflet-control {
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
float: right;
|
||||
}
|
||||
.leaflet-top .leaflet-control {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.leaflet-left .leaflet-control {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* zoom and fade animations */
|
||||
|
||||
.leaflet-fade-anim .leaflet-tile,
|
||||
.leaflet-fade-anim .leaflet-popup {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
-o-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
.leaflet-fade-anim .leaflet-tile-loaded,
|
||||
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-animated {
|
||||
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
-o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
}
|
||||
.leaflet-zoom-anim .leaflet-tile,
|
||||
.leaflet-pan-anim .leaflet-tile,
|
||||
.leaflet-touching .leaflet-zoom-animated {
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
-o-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-hide {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
|
||||
/* cursors */
|
||||
|
||||
.leaflet-clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
.leaflet-container {
|
||||
cursor: -webkit-grab;
|
||||
cursor: -moz-grab;
|
||||
}
|
||||
.leaflet-popup-pane,
|
||||
.leaflet-control {
|
||||
cursor: auto;
|
||||
}
|
||||
.leaflet-dragging,
|
||||
.leaflet-dragging .leaflet-clickable,
|
||||
.leaflet-dragging .leaflet-container {
|
||||
cursor: move;
|
||||
cursor: -webkit-grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
}
|
||||
|
||||
|
||||
/* visual tweaks */
|
||||
|
||||
.leaflet-container {
|
||||
background: #ddd;
|
||||
outline: 0;
|
||||
}
|
||||
.leaflet-container a {
|
||||
color: #0078A8;
|
||||
}
|
||||
.leaflet-container a.leaflet-active {
|
||||
outline: 2px solid orange;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
border: 2px dotted #05f;
|
||||
background: white;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
|
||||
/* general typography */
|
||||
.leaflet-container {
|
||||
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
|
||||
/* general toolbar styles */
|
||||
|
||||
.leaflet-bar {
|
||||
box-shadow: 0 1px 7px rgba(0,0,0,0.65);
|
||||
-webkit-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a, .leaflet-bar a:hover {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #ccc;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
.leaflet-bar a,
|
||||
.leaflet-control-layers-toggle {
|
||||
background-position: 50% 50%;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
}
|
||||
.leaflet-bar a:hover {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
.leaflet-bar a:first-child {
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a:last-child {
|
||||
-webkit-border-bottom-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
-webkit-border-bottom-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom: none;
|
||||
}
|
||||
.leaflet-bar a.leaflet-disabled {
|
||||
cursor: default;
|
||||
background-color: #f4f4f4;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-bar {
|
||||
-webkit-border-radius: 10px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:first-child {
|
||||
-webkit-border-top-left-radius: 7px;
|
||||
border-top-left-radius: 7px;
|
||||
-webkit-border-top-right-radius: 7px;
|
||||
border-top-right-radius: 7px;
|
||||
}
|
||||
.leaflet-touch .leaflet-bar a:last-child {
|
||||
-webkit-border-bottom-left-radius: 7px;
|
||||
border-bottom-left-radius: 7px;
|
||||
-webkit-border-bottom-right-radius: 7px;
|
||||
border-bottom-right-radius: 7px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
|
||||
/* zoom control */
|
||||
|
||||
.leaflet-control-zoom-in {
|
||||
font: bold 18px 'Lucida Console', Monaco, monospace;
|
||||
}
|
||||
.leaflet-control-zoom-out {
|
||||
font: bold 22px 'Lucida Console', Monaco, monospace;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-zoom-in {
|
||||
font-size: 22px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-zoom-out {
|
||||
font-size: 28px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
|
||||
/* layers control */
|
||||
|
||||
.leaflet-control-layers {
|
||||
box-shadow: 0 1px 7px rgba(0,0,0,0.4);
|
||||
background: #f8f8f9;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers.png);
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
.leaflet-retina .leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers-2x.png);
|
||||
background-size: 26px 26px;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers-toggle {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
.leaflet-control-layers .leaflet-control-layers-list,
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
|
||||
display: none;
|
||||
}
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-list {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
.leaflet-control-layers-expanded {
|
||||
padding: 6px 10px 6px 6px;
|
||||
color: #333;
|
||||
background: #fff;
|
||||
}
|
||||
.leaflet-control-layers-selector {
|
||||
margin-top: 2px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
.leaflet-control-layers label {
|
||||
display: block;
|
||||
}
|
||||
.leaflet-control-layers-separator {
|
||||
height: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 5px -10px 5px -6px;
|
||||
}
|
||||
|
||||
|
||||
/* attribution and scale controls */
|
||||
|
||||
.leaflet-container .leaflet-control-attribution {
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
box-shadow: 0 0 5px #bbb;
|
||||
margin: 0;
|
||||
}
|
||||
.leaflet-control-attribution,
|
||||
.leaflet-control-scale-line {
|
||||
padding: 0 5px;
|
||||
color: #333;
|
||||
}
|
||||
.leaflet-container .leaflet-control-attribution,
|
||||
.leaflet-container .leaflet-control-scale {
|
||||
font-size: 11px;
|
||||
}
|
||||
.leaflet-left .leaflet-control-scale {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control-scale {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.leaflet-control-scale-line {
|
||||
border: 2px solid #777;
|
||||
border-top: none;
|
||||
color: black;
|
||||
line-height: 1.1;
|
||||
padding: 2px 5px 1px;
|
||||
font-size: 11px;
|
||||
text-shadow: 1px 1px 1px #fff;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
box-shadow: 0 -1px 5px rgba(0, 0, 0, 0.2);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child) {
|
||||
border-top: 2px solid #777;
|
||||
border-bottom: none;
|
||||
margin-top: -2px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
|
||||
border-bottom: 2px solid #777;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-attribution,
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
box-shadow: none;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
border: 4px solid rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
|
||||
/* popup */
|
||||
|
||||
.leaflet-popup {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
}
|
||||
.leaflet-popup-content-wrapper {
|
||||
padding: 1px;
|
||||
text-align: left;
|
||||
-webkit-border-radius: 12px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.leaflet-popup-content {
|
||||
margin: 13px 19px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.leaflet-popup-content p {
|
||||
margin: 18px 0;
|
||||
}
|
||||
.leaflet-popup-tip-container {
|
||||
margin: 0 auto;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.leaflet-popup-tip {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
padding: 1px;
|
||||
|
||||
margin: -10px auto 0;
|
||||
|
||||
-webkit-transform: rotate(45deg);
|
||||
-moz-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
-o-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
|
||||
background: white;
|
||||
|
||||
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 4px 4px 0 0;
|
||||
text-align: center;
|
||||
width: 18px;
|
||||
height: 14px;
|
||||
font: 16px/14px Tahoma, Verdana, sans-serif;
|
||||
color: #c3c3c3;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
background: transparent;
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button:hover {
|
||||
color: #999;
|
||||
}
|
||||
.leaflet-popup-scrolled {
|
||||
overflow: auto;
|
||||
border-bottom: 1px solid #ddd;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
|
||||
/* div icon */
|
||||
|
||||
.leaflet-div-icon {
|
||||
background: #fff;
|
||||
border: 1px solid #666;
|
||||
}
|
||||
.leaflet-editing-icon {
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+113
@@ -0,0 +1,113 @@
|
||||
var express = require('express')
|
||||
, app = express()
|
||||
, server = require('http').createServer(app)
|
||||
, io = require('socket.io').listen(server);
|
||||
|
||||
app.use(express.static(__dirname + '/public'));
|
||||
app.use(app.router);
|
||||
|
||||
app.get('/', function(req, res) {
|
||||
res.sendfile(__dirname + '/index.html');
|
||||
});
|
||||
|
||||
app.get('/phone', function(req, res) {
|
||||
res.sendfile(__dirname + '/phone.html');
|
||||
});
|
||||
|
||||
server.listen(8080);
|
||||
|
||||
io.sockets.on('connection', function(socket) {
|
||||
console.log('connection')
|
||||
|
||||
socket.on('takeoff', function(data){
|
||||
console.log('takeoff', data)
|
||||
client.takeoff()
|
||||
})
|
||||
|
||||
socket.on('land', function(data){
|
||||
console.log('land', data)
|
||||
client.land()
|
||||
})
|
||||
|
||||
socket.on('phone', function(data){
|
||||
console.log('phone', data)
|
||||
targetLat = data.lat
|
||||
targetLon = data.lon
|
||||
phoneAccuracy = data.accuracy
|
||||
})
|
||||
|
||||
socket.on('stop', function(data){
|
||||
console.log('stop', data)
|
||||
targetYaw = null
|
||||
targetLat = null
|
||||
targetLon = null
|
||||
client.stop()
|
||||
})
|
||||
|
||||
setInterval(function(){
|
||||
io.sockets.emit('position', {lat: currentLat, lon: currentLon, distance: currentDistance})
|
||||
io.sockets.emit('drone', {lat: currentLat, lon: currentLon, yaw: currentYaw})
|
||||
io.sockets.emit('phone', {lat: targetLat, lon: targetLon, accuracy: phoneAccuracy})
|
||||
},1000)
|
||||
|
||||
});
|
||||
|
||||
var arDrone = require('ar-drone');
|
||||
var PID = require('./PID');
|
||||
var vincenty = require('node-vincenty');
|
||||
|
||||
var yawPID = new PID(1.0, 0, 0.30);
|
||||
var client = arDrone.createClient();
|
||||
|
||||
client.config('general:navdata_demo', 'FALSE');
|
||||
|
||||
var targetLat, targetLon, targetYaw, cyaw, currentLat, currentLon,currentDistance, currentYaw, phoneAccuracy;
|
||||
|
||||
var handleNavData = function(data){
|
||||
if ( data.demo == null || data.gps == null) return;
|
||||
|
||||
currentLat = data.gps.latitude
|
||||
currentLon = data.gps.longitude
|
||||
|
||||
currentYaw = data.demo.rotation.yaw;
|
||||
|
||||
if (targetLat == null || targetLon == null || currentYaw == null || currentLat == null || currentLon == null) return;
|
||||
|
||||
var bearing = vincenty.distVincenty(currentLat, currentLon, targetLat, targetLon)
|
||||
|
||||
if(bearing.distance > 1){
|
||||
currentDistance = bearing.distance
|
||||
console.log('distance', bearing.distance)
|
||||
console.log('bearing:', bearing.initialBearing)
|
||||
targetYaw = bearing.initialBearing
|
||||
|
||||
console.log('currentYaw:', currentYaw);
|
||||
var eyaw = targetYaw - currentYaw;
|
||||
console.log('eyaw:', eyaw);
|
||||
|
||||
var uyaw = yawPID.getCommand(eyaw);
|
||||
console.log('uyaw:', uyaw);
|
||||
|
||||
var cyaw = within(uyaw, -1, 1);
|
||||
console.log('cyaw:', cyaw);
|
||||
|
||||
client.clockwise(cyaw)
|
||||
client.front(0.05)
|
||||
} else {
|
||||
targetYaw = null
|
||||
client.stop()
|
||||
console.log('Reached ', targetLat, targetLon)
|
||||
}
|
||||
}
|
||||
|
||||
client.on('navdata', handleNavData);
|
||||
|
||||
function within(x, min, max) {
|
||||
if (x < min) {
|
||||
return min;
|
||||
} else if (x > max) {
|
||||
return max;
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
Referência em uma Nova Issue
Bloquear um usuário