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.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) {
|
function within(x, min, max) {
|
||||||
if (x < min) {
|
if (x < min) {
|
||||||
return 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",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ar-drone": "git://github.com/andrew/node-ar-drone.git#gps",
|
"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": {},
|
"devDependencies": {},
|
||||||
"scripts": {
|
"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