Commit b013e21e authored by Léo-Paul Géneau's avatar Léo-Paul Géneau 👾

software/js-drone: use a flight script parameter

Use a script passed by the user for the flight instead of a predefined one.
parent 2f8b9e1f
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
## Presentation ## ## Presentation ##
* Deploy 4 different scripts (`cli.js`, `demo.js`, `manual-flight.js` and `subscribe.js`) on a drone to fly it * Deploy `main.js` script on a drone to fly it
* Compile all required libraries to run flight scripts * Compile all required libraries to run flight scripts
...@@ -20,8 +20,10 @@ ...@@ -20,8 +20,10 @@
* net-if: Network interface used for multicast traffic * net-if: Network interface used for multicast traffic
* drone-id-list: Comma seperated list of the drone IDs of the swarm (recommanded to add the current drone ID) * drone-id-list: List of the drone IDs of the swarm (recommended to add the current drone ID)
* flight-script: User script to execute to fly drone swarm
## How it works ## ## How it works ##
Run `quickjs binary location` `desired script location` Run `quickjs binary location` `scripts location`/main.js
...@@ -14,28 +14,12 @@ ...@@ -14,28 +14,12 @@
# not need these here). # not need these here).
[instance-profile] [instance-profile]
filename = instance.cfg filename = instance.cfg
md5sum = 9c754abbc80f795229c3e79a8ede534b md5sum = ae1ccd9272303ee0102cdcec8ddef562
[cli] [main]
filename = cli.js filename = main.js
md5sum = 33271aeec124301604fdd406f0b339d1 md5sum = 195c4ba934fb05f46dec18a5a132c450
[common]
filename = common.js
md5sum = 1a43f5cf3db1256fee985f82d88930a0
[demo]
filename = demo.js
md5sum = 31d8511e6d297643e65febe9a3ed2428
[manual-flight]
filename = manual-flight.js
md5sum = 175813fc8b2f19f91dae27ad4e14ab03
[pubsub] [pubsub]
filename = pubsub.js filename = pubsub.js
md5sum = 1d1a2be301d74a619b63a33c4b4039da md5sum = d8798c3206f129e8715afd3ca23afa1a
[subscribe]
filename = subscribe.js
md5sum = 772e84f5584fc66c976778bbd8ae6a65
/*jslint indent2 */
/*global console, std */
import {
loiter,
setAirspeed,
setAltitude,
setTargetLatLong,
reboot
} from "{{ qjs_wrapper }}"; //jslint-quiet
import {
connect,
displayDronePositions,
land,
quit,
startPubsub,
takeOff
} from "{{ common }}"; //jslint-quiet
/*jslint-disable*/
import * as std from "std";
/*jslint-enable*/
var running = false;
const wrongParameters = displayMessage.bind(null, "Wrong parameters");
function checkNumber(value, toExecute) {
return (
Number.isNaN(value)
? wrongParameters
: toExecute.bind(null, value)
);
}
function displayMessage(message) {
console.log(message);
return 0;
}
function exit() {
running = false;
quit();
return 0;
}
function getInput() {
let undefined_cmd;
let altitude;
let cmd;
let latitude;
let longitude;
let s;
let speed;
const help = `
connect
takeoff
land
goto(point)
gotoCoord(latitude, longitude)
altitude(altitude)
speed(speed)
positions
reboot
exit
help
`;
const f = std.fdopen(std.in, "r");
running = true;
while (running) {
std.printf("> ");
s = f.getline();
undefined_cmd = false;
switch (s) {
case "altitude":
std.printf("Altitude: ");
altitude = parseFloat(f.getline());
cmd = checkNumber(altitude, setAltitude);
break;
case "connect":
cmd = connect;
startPubsub();
break;
case "exit":
cmd = exit;
break;
case "gotoCoord":
std.printf("Latitude: ");
latitude = parseFloat(f.getline());
std.printf("Longitude: ");
longitude = parseFloat(f.getline());
cmd = checkNumber(longitude, checkNumber(latitude, setTargetLatLong));
break;
case "help":
cmd = displayMessage.bind(null, help);
break;
case "land":
cmd = land;
break;
case "loiter":
cmd = loiter;
break;
case "positions":
cmd = displayDronePositions;
break;
case "reboot":
cmd = reboot;
break;
case "speed":
std.printf("Speed: ");
speed = parseFloat(f.getline());
cmd = checkNumber(speed, setAirspeed);
break;
case "takeoff":
cmd = takeOff.bind(null, 60);
break;
default:
undefined_cmd = true;
cmd = displayMessage.bind(null, " Undefined command");
}
let ret = cmd();
if (ret) {
console.log(" [ERROR] function:\n", cmd, "\nreturn value:", ret);
}
else if (s !== "help" && !undefined_cmd) {
console.log(" Command successful");
}
};
f.close();
}
getInput();
/*jslint-disable*/
{% set comma_separated_drone_id_list = ', '.join(drone_id_list.split()) -%}
/*jslint-enable*/
import {
arm,
doParachute,
getAltitude,
getLatitude,
getLongitude,
getYaw,
initPubsub,
setAltitude,
setTargetLatLong,
start,
stop,
stopPubsub,
takeOffAndWait,
Drone
} from "{{ qjs_wrapper }}"; //jslint-quiet
import {exit} from "std";
import {sleep, Worker} from "os";
const IP = "{{ autopilot_ip }}";
const PORT = "7909";
export const IS_LEADER = {{ is_leader }};
export const LEADER_ID = {{ leader_id }};
export const SIMULATION = {{ is_a_simulation }};
export const EPSILON = 105;
const EPSILON_YAW = 6;
const EPSILON_ALTITUDE = 5;
const TARGET_YAW = 0;
export const ALTITUDE_DIFF = 30;
const URL = "udp://" + IP + ":" + PORT;
const LOG_FILE = "{{ log_dir }}/mavsdk-log";
const droneIdList = [{{ comma_separated_drone_id_list }}];
const droneDict = {};
var pubsubRunning = false;
var pubsubWorker;
export function connect() {
console.log("Will connect to", URL);
exit_on_fail(start(URL, LOG_FILE, 60), "Failed to connect to " + URL);
}
export function distance(lat1, lon1, lat2, lon2) {
const R = 6371e3; // meters
const la1 = lat1 * Math.PI/180; // la, lo in radians
const la2 = lat2 * Math.PI/180;
const lo1 = lon1 * Math.PI/180;
const lo2 = lon2 * Math.PI/180;
//haversine formula
const sinLat = Math.sin((la2 - la1)/2);
const sinLon = Math.sin((lo2 - lo1)/2);
const h = sinLat*sinLat + Math.cos(la1)*Math.cos(la2)*sinLon*sinLon
return 2*R*Math.asin(Math.sqrt(h));
}
export function displayDronePositions() {
if(!pubsubRunning)
console.log("You must start pubsub first !");
else {
for (const [id, drone] of Object.entries(droneDict)) {
console.log(id, drone.latitude, drone.longitude, drone.altitudeAbs, drone.altitudeRel);
}
}
return 0;
}
function exit_on_fail(ret, msg) {
if(ret) {
console.log(msg);
quit();
exit(-1);
}
}
export function quit() {
stop();
if(pubsubRunning) {
stopPubsub();
}
}
export function goToAltitude(target_altitude, wait, go) {
if(go) {
exit_on_fail(
setAltitude(target_altitude),
`Failed to go to altitude ${target_altitude} m`
);
}
if(wait) {
waitForAltitude(target_altitude);
}
}
export function land() {
var yaw;
while(true) {
yaw = getYaw();
console.log(`[DEMO] Waiting for yaw... (${yaw} , ${TARGET_YAW})`);
if(Math.abs(yaw - TARGET_YAW) < EPSILON_YAW) {
break;
}
sleep(250);
}
console.log("[DEMO] Deploying parachute...");
exit_on_fail(doParachute(2), "Failed to deploy parachute");
}
export function setLatLong(latitude, longitude, target_altitude) {
var cur_latitude;
var cur_longitude;
var d;
if(target_altitude !== 0) {
setAltitude(target_altitude, false, true);
}
console.log(`Going to (${latitude}, ${longitude}) from
(${getLatitude()}, ${getLongitude()})`);
exit_on_fail(
setTargetLatLong(latitude, longitude),
`Failed to go to (${latitude}, ${longitude})`
);
sleep(500);
while(true) {
cur_latitude = getLatitude();
cur_longitude = getLongitude();
d = distance(cur_latitude, cur_longitude, latitude, longitude);
console.log(`Waiting for drone to get to destination (${d} m),
(${cur_latitude} , ${cur_longitude}), (${latitude}, ${longitude})`);
if(d < EPSILON) {
sleep(6000);
return;
}
sleep(1000);
}
}
export function startPubsub() {
pubsubWorker = new Worker("{{ pubsub_script }}");
pubsubWorker.onmessage = function(e) {
if (!e.data.publishing)
pubsubWorker.onmessage = null;
}
initPubsub(droneIdList.length);
for (let i = 0; i < droneIdList.length; i++) {
let id = droneIdList[i]
droneDict[id] = new Drone(id);
droneDict[id].init(i);
}
pubsubWorker.postMessage({ action: "run", publish: true });
pubsubRunning = true;
return droneDict;
}
export function takeOff(altitude) {
exit_on_fail(arm(), "Failed to arm");
takeOffAndWait();
goToAltitude(altitude, true, true);
}
function waitForAltitude(target_altitude) {
var altitude = getAltitude();
while(Math.abs(altitude - target_altitude) > EPSILON_ALTITUDE) {
console.log(
`[DEMO] Waiting for altitude... (${altitude} , ${target_altitude})`);
sleep(1000);
altitude = getAltitude();
}
}
/*jslint indent2 */
/*global console */
import {
getAltitude,
getAltitudeRel,
getInitialAltitude,
getLatitude,
getLongitude,
landed,
loiter,
setCheckpoint,
setTargetCoordinates
} from "{{ qjs_wrapper }}"; //jslint-quiet
import {sleep} from "os";
import {
connect,
distance,
goToAltitude,
land,
quit,
setLatLong,
startPubsub,
takeOff,
ALTITUDE_DIFF,
IS_LEADER,
LEADER_ID,
SIMULATION
} from "{{ common }}"; //jslint-quiet
const FLIGH_ALTITUDE = 100;
const PARACHUTE_ALTITUDE = 35;
const checkpointList = [
{
"latitude": 45.64492790560583,
"longitude": 14.25334942966329,
"altitude": 585.1806861589965
},
{
"latitude": 45.64316335436476,
"longitude": 14.26332880184475,
"altitude": 589.8802607573035
},
{
"latitude": 45.64911917196595,
"longitude": 14.26214792790128,
"altitude": 608.6648153348965
},
{
"latitude": 45.64122685351364,
"longitude": 14.26590493128597,
"altitude": 606.1448368129072
},
{
"latitude": 45.64543355564817,
"longitude": 14.27242391207985,
"altitude": 630.0829598206344
},
{
"latitude": 45.6372792927328,
"longitude": 14.27533492411138,
"altitude": 616.1839898415284
},
{
"latitude": 45.64061299543953,
"longitude": 14.26161958465814,
"altitude": 598.0603137354178
},
{
"latitude": 45.64032340702919,
"longitude": 14.2682896662383,
"altitude": 607.1243119862851
}
];
const landingPoint = [
{
"latitude": 45.6398451,
"longitude": 14.2699217
}
];
let INITIAL_ALTITUDE;
let START_ALTITUDE;
var nextCheckpoint = 0;
var distanceToLandingPoint = 100;
var leaderAltitudeAbs;
var leaderAltitudeRel;
var leaderLatitude;
var leaderLongitude;
function followLeader(leaderId, initialAltitude, altitudeDiff) {
goToAltitude(START_ALTITUDE + ALTITUDE_DIFF, false, true);
while(droneDict[leaderId].altitudeAbs == 0) {
console.log("[DEMO] Waiting for leader to send its altitude");
sleep(1000);
}
while(droneDict[leaderId].altitudeAbs < initialAltitude) {
console.log(`[DEMO] Waiting for leader to reach altitude ${initialAltitude} (currently ${droneDict[leaderId].altitudeAbs})`);
sleep(1000);
}
console.log("[DEMO] Switching to following mode...\n");
do {
leaderAltitudeAbs = droneDict[leaderId].altitudeAbs;
leaderAltitudeRel = droneDict[leaderId].altitudeRel;
leaderLatitude = droneDict[leaderId].latitude;
leaderLongitude = droneDict[leaderId].longitude;
setTargetCoordinates(
leaderLatitude,
leaderLongitude,
leaderAltitudeAbs + altitudeDiff,
0
);
sleep(500);
} while(leaderAltitudeRel > PARACHUTE_ALTITUDE);
console.log("[DEMO] Stop following...\n");
nextCheckpoint = droneDict[leaderId].lastCheckpoint + 1;
}
function waitForAltitude(altitude) {
var curAltitude;
do {
sleep(1000);
curAltitude = getAltitude();
console.log(
`[DEMO] Waiting for altitude... (${curAltitude} , ${altitude})`);
}
while(curAltitude < altitude);
}
function waitForLanding() {
while(!landed()) {
sleep(1000);
}
}
console.log("[DEMO] Connecting...\n");
connect();
const droneDict = startPubsub();
INITIAL_ALTITUDE = getInitialAltitude();
START_ALTITUDE = INITIAL_ALTITUDE + FLIGH_ALTITUDE;
if(SIMULATION) {
takeOff(START_ALTITUDE + 1);
}
waitForAltitude(START_ALTITUDE);
console.log("[DEMO] Setting loiter mode...\n");
loiter();
sleep(3000);
if(!IS_LEADER) {
followLeader(LEADER_ID, START_ALTITUDE, ALTITUDE_DIFF);
}
for (let i = nextCheckpoint; i < checkpointList.length; i++) {
console.log(`[DEMO] Going to Checkpoint ${i}\n`);
setLatLong(checkpointList[i].latitude, checkpointList[i].longitude, checkpointList[i].altitude + FLIGH_ALTITUDE);
console.log(`[DEMO] Reached Checkpoint ${i}\n`);
setCheckpoint(i);
sleep(30000);
}
console.log("[DEMO] Setting altitude...\n");
goToAltitude(getAltitude() - getAltitudeRel() + PARACHUTE_ALTITUDE, true, true);
if(!IS_LEADER) {
setLatLong(
checkpointList[checkpointList.length - 1].latitude,
checkpointList[checkpointList.length - 1].longitude,
0
);
}
while(distanceToLandingPoint > 20) {
console.log(`[DEMO] Waiting to reache landing point (current distance is ${distanceToLandingPoint})`);
distanceToLandingPoint = distance(getLatitude(), getLongitude(), landingPoint.latitude, landingPoint.longitude);
}
console.log("[DEMO] Landing...\n");
land();
waitForLanding();
quit();
{
"$schema": "http://json-schema.org/draft-06/schema",
"type": "object",
"description": "Parameters to instantiate JS drone",
"additionalProperties": false,
"properties": {
"autopilot-ip": {
"title": "IP address of the drone's autopilot",
"description": "IP used to create a connection with the autopilot.",
"type": "string",
"default": "192.168.27.1"
},
"id": {
"title": "Drone ID",
"description": "Unique identifier of the drone.",
"type": "integer",
"default": 1
},
"is-a-simulation": {
"title": "Set the flight as a simulation",
"description": "The option used to determine if the flight is real or if it is a simulation. This affects the context of the flight (e.g. if the take off is manual or automatic).",
"type": "boolean",
"default": false
},
"leader-id": {
"title": "Leader ID",
"description": "Unique identifier of the drone chosen to be the leader.",
"type": "integer",
"default": 1
},
"multicast-ipv6": {
"title": "IP of the multicast group",
"description": "IP address used to communicate with the other drones.",
"type": "string",
"default": "ff15::1111"
},
"net-if": {
"title": "Network interface",
"description": "Interface used for multicast traffic.",
"type": "string",
"default": "eth0"
},
"drone-id-list": {
"title": "List of drones IDs",
"description": "List of identifiers of drones.",
"type": "array",
"default": []
},
"flight-script": {
"title": "Script of the flight",
"description": "Script which will be executed for the flight",
"type": "string",
"textarea": true
}
}
}
[buildout] [buildout]
parts = parts =
cli main
demo
manual-flight
subscribe
eggs-directory = ${buildout:eggs-directory} eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory} develop-eggs-directory = ${buildout:develop-eggs-directory}
...@@ -28,14 +25,31 @@ cert = $${slap_connection:cert_file} ...@@ -28,14 +25,31 @@ cert = $${slap_connection:cert_file}
recipe = slapos.recipe.build recipe = slapos.recipe.build
slapparameter-dict = $${slap-configuration:configuration} slapparameter-dict = $${slap-configuration:configuration}
init = init =
options['autopilot-ip'] = options['slapparameter-dict'].get('autopilot_ip', '192.168.27.1') options['autopilot-ip'] = options['slapparameter-dict'].get('autopilot-ip', '192.168.27.1')
options['id'] = options['slapparameter-dict'].get('id', '1') options['id'] = options['slapparameter-dict'].get('id', 1)
options['is-a-simulation'] = options['slapparameter-dict'].get('is_a_simulation', 'false') options['is-a-simulation'] = options['slapparameter-dict'].get('is-a-simulation', False)
options['leader-id'] = options['slapparameter-dict'].get('leader_id', '1') options['leader-id'] = options['slapparameter-dict'].get('leader-id', 1)
options['is-leader'] = 'true' if options['id'] == options['leader-id'] else 'false' options['is-leader'] = options['id'] == options['leader-id']
options['multicast-ipv6'] = options['slapparameter-dict'].get('multicast_ip', 'ff15::1111') options['multicast-ipv6'] = options['slapparameter-dict'].get('multicast-ip', 'ff15::1111')
options['net-if'] = options['slapparameter-dict'].get('net_if', 'eth0') options['net-if'] = options['slapparameter-dict'].get('net-if', 'eth0')
options['drone-id-list'] = options['slapparameter-dict'].get('drone_id_list', '') options['drone-id-list'] = options['slapparameter-dict'].get('drone-id-list', [])
options['is-publisher'] = 'flight-script' in options['slapparameter-dict']
subscription_script = '''
me.onStart = function() {
const f = std.fdopen(std.in, "r");
console.log("Use q to quit");
};
me.onUpdate= function() {
while(f.getline() != "q") {
continue;
}
f.close();
};
'''
options['flight-script'] = options['slapparameter-dict'].get('flight-script', subscription_script)
[js-dynamic-template] [js-dynamic-template]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
...@@ -46,41 +60,22 @@ context = ...@@ -46,41 +60,22 @@ context =
raw qjs_wrapper ${qjs-wrapper:location}/lib/libqjswrapper.so raw qjs_wrapper ${qjs-wrapper:location}/lib/libqjswrapper.so
$${:extra-context} $${:extra-context}
[common]
<= js-dynamic-template
extra-context =
key autopilot_ip drone:autopilot-ip
key drone_id_list drone:drone-id-list
key is_a_simulation drone:is-a-simulation
key is_leader drone:is-leader
key leader_id drone:leader-id
key log_dir directory:log
key pubsub_script pubsub:rendered
[cli]
<= js-dynamic-template
extra-context =
key common common:rendered
[demo]
<= js-dynamic-template
extra-context =
key common common:rendered
[manual-flight]
<= js-dynamic-template
extra-context =
key common common:rendered
[pubsub] [pubsub]
<= js-dynamic-template <= js-dynamic-template
extra-context = extra-context =
key id drone:id
key ipv6 drone:multicast-ipv6 key ipv6 drone:multicast-ipv6
key net_if drone:net-if key net_if drone:net-if
[subscribe] [main]
<= js-dynamic-template <= js-dynamic-template
extra-context = extra-context =
key autopilot_ip drone:autopilot-ip
key drone_id_list drone:drone-id-list key drone_id_list drone:drone-id-list
key flight_script drone:flight-script
key id drone:id
key is_a_simulation drone:is-a-simulation
key is_leader drone:is-leader
key is_publisher drone:is-publisher
key leader_id drone:leader-id
key log_dir directory:log
key pubsub_script pubsub:rendered key pubsub_script pubsub:rendered
import {
arm,
doParachute,
getAltitude,
getAltitudeRel,
getInitialAltitude,
getLatitude,
getLongitude,
getYaw,
initPubsub,
landed,
loiter,
reboot,
setAirspeed,
setAltitude,
setCheckpoint,
setTargetCoordinates,
start,
stop,
stopPubsub,
takeOffAndWait,
Drone
} from "{{ qjs_wrapper }}";
import {sleep, Worker} from "os";
import * as std from "std";
const IP = "{{ autopilot_ip }}";
const URL = "udp://" + IP + ":7909";
const LOG_FILE = "{{ log_dir }}/mavsdk-log";
const IS_LEADER = {{ 'true' if is_leader else 'false' }};
const LEADER_ID = {{ leader_id }};
const IS_PUBLISHER = {{ 'true' if is_publisher else 'false' }}
const SIMULATION = {{ 'true' if is_a_simulation else 'false' }};
const droneIdList = {{ drone_id_list }};
const droneDict = {};
const pubsubScript = "{{ pubsub_script }}";
var pubsubWorker;
var pubsubRunning = false;
const me = {
'id': "{{ id }}",
'getCurrentPosition': function() {
return {
'x': getLatitude(),
'y': getLongitude(),
'z': getAltitudeRel()
};
},
'onStart': function() {},
'onUpdate': function() {},
'setAirspeed': setAirspeed,
'setTargetCoordinates': setTargetCoordinates
}
function connect() {
console.log("Will connect to", URL);
exit_on_fail(start(URL, LOG_FILE, 60), "Failed to connect to " + URL);
}
function exit_on_fail(ret, msg) {
if(ret) {
console.log(msg);
quit();
std.exit(-1);
}
}
function quit() {
stop();
if(pubsubRunning) {
stopPubsub();
}
}
function takeOff() {
exit_on_fail(arm(), "Failed to arm");
takeOffAndWait();
}
function waitForLanding() {
while(!landed()) {
sleep(1000);
}
}
if(IS_PUBLISHER) {
console.log("Connecting to aupilot\n");
connect();
}
pubsubWorker = new Worker(pubsubScript);
pubsubWorker.onmessage = function(e) {
if (!e.data.publishing)
pubsubWorker.onmessage = null;
}
initPubsub(droneIdList.length);
for (let i = 0; i < droneIdList.length; i++) {
let id = droneIdList[i]
droneDict[id] = new Drone(id);
droneDict[id].init(i);
}
pubsubWorker.postMessage({ action: "run", id: me.id, publish: IS_PUBLISHER });
pubsubRunning = true;
{{ flight_script }}
if(IS_PUBLISHER && SIMULATION) {
takeOff();
}
me.onStart()
me.onUpdate();
if(IS_PUBLISHER) {
waitForLanding();
quit();
} else {
stopPubsub();
};
/*jslint indent2 */
/*global console */
import {
getAltitude,
getInitialAltitude,
landed,
loiter,
setTargetCoordinates
} from "{{ qjs_wrapper }}"; //jslint-quiet
import {sleep} from "os";
import {
connect,
goToAltitude,
quit,
startPubsub,
takeOff,
ALTITUDE_DIFF,
IS_LEADER,
LEADER_ID,
SIMULATION
} from "{{ common }}"; //jslint-quiet
const FLIGH_ALTITUDE = 100;
const PARACHUTE_ALTITUDE = 35;
let INITIAL_ALTITUDE;
let START_ALTITUDE;
var leaderAltitudeAbs;
var leaderAltitudeRel;
var leaderLatitude;
var leaderLongitude;
function followLeader(leaderId, initialAltitude, altitudeDiff) {
goToAltitude(START_ALTITUDE + ALTITUDE_DIFF, false, true);
while(droneDict[leaderId].altitudeAbs == 0) {
console.log("[DEMO] Waiting for leader to send its altitude");
sleep(1000);
}
while(droneDict[leaderId].altitudeAbs < initialAltitude) {
console.log(`[DEMO] Waiting for leader to reach altitude ${initialAltitude} (currently ${droneDict[leaderId].altitudeAbs})`);
sleep(1000);
}
console.log("[DEMO] Switching to following mode...\n");
do {
leaderAltitudeAbs = droneDict[leaderId].altitudeAbs;
leaderAltitudeRel = droneDict[leaderId].altitudeRel;
leaderLatitude = droneDict[leaderId].latitude;
leaderLongitude = droneDict[leaderId].longitude;
setTargetCoordinates(
leaderLatitude,
leaderLongitude,
leaderAltitudeAbs + altitudeDiff,
0
);
sleep(500);
} while(leaderAltitudeRel > PARACHUTE_ALTITUDE);
console.log("[DEMO] Stop following...\n");
}
function waitForAltitude(altitude) {
var curAltitude;
do {
sleep(1000);
curAltitude = getAltitude();
console.log(
`[DEMO] Waiting for altitude... (${curAltitude} , ${altitude})`);
}
while(curAltitude < altitude);
}
function waitForLanding() {
while(!landed()) {
sleep(1000);
}
}
const droneDict = startPubsub();
console.log("[DEMO] Connecting...\n");
connect();
while(getInitialAltitude() == 0) {
console.log("[DEMO] Waiting for first telemetry\n");
sleep(1000);
}
INITIAL_ALTITUDE = getInitialAltitude();
START_ALTITUDE = INITIAL_ALTITUDE + FLIGH_ALTITUDE;
if(SIMULATION) {
takeOff(START_ALTITUDE + 1);
}
waitForAltitude(START_ALTITUDE);
console.log("[DEMO] Setting loiter mode...\n");
loiter();
sleep(3000);
if(!IS_LEADER) {
followLeader(LEADER_ID, START_ALTITUDE, ALTITUDE_DIFF);
}
console.log("[DEMO] Loitering until manual intructions are given\n")
waitForLanding();
quit();
...@@ -9,7 +9,7 @@ var parent = Worker.parent; ...@@ -9,7 +9,7 @@ var parent = Worker.parent;
function handle_msg(e) { function handle_msg(e) {
switch(e.data.action) { switch(e.data.action) {
case "run": case "run":
runPubsub(IPV6, PORT, "{{ net_if }}", {{ id }}, e.data.publish); runPubsub(IPV6, PORT, "{{ net_if }}", e.data.id, e.data.publish);
parent.postMessage({running: false}); parent.postMessage({running: false});
parent.onmessage = null; parent.onmessage = null;
break; break;
......
...@@ -6,12 +6,8 @@ extends = ...@@ -6,12 +6,8 @@ extends =
parts = parts =
instance-profile instance-profile
common main
cli
demo
manual-flight
pubsub pubsub
subscribe
slapos-cookbook slapos-cookbook
[download-file-base] [download-file-base]
...@@ -24,20 +20,8 @@ recipe = slapos.recipe.template ...@@ -24,20 +20,8 @@ recipe = slapos.recipe.template
url = ${:_profile_base_location_}/${:filename} url = ${:_profile_base_location_}/${:filename}
output = ${buildout:directory}/template.cfg output = ${buildout:directory}/template.cfg
[common] [main]
<= download-file-base
[cli]
<= download-file-base
[demo]
<= download-file-base
[manual-flight]
<= download-file-base <= download-file-base
[pubsub] [pubsub]
<= download-file-base <= download-file-base
[subscribe]
<= download-file-base
{
"name": "JS Drone",
"description": "JS Drone",
"serialisation": "xml",
"software-type": {
"default": {
"title": "Default",
"software-type": "default",
"description": "Default",
"request": "instance-input-schema.json",
"index": 0
}
}
}
/*jslint-disable*/
{% set comma_separated_drone_id_list = ', '.join(drone_id_list.split()) -%}
/*jslint-enable*/
import {
initPubsub,
stopPubsub,
Drone
} from "{{ qjs_wrapper }}"; //jslint-quiet
import {Worker} from "os";
/*jslint-disable*/
import * as std from "std";
/*jslint-enable*/
const droneIdList = [{{ comma_separated_drone_id_list }}];
const droneDict = {};
var pubsubWorker = new Worker("{{ pubsub_script }}");
pubsubWorker.onmessage = function(e) {
if (!e.data.publishing)
pubsubWorker.onmessage = null;
}
initPubsub(droneIdList.length);
for (let i = 0; i < droneIdList.length; i++) {
let id = droneIdList[i]
droneDict[id] = new Drone(id);
droneDict[id].init(i);
}
pubsubWorker.postMessage({ action: "run", publish: false });
const f = std.fdopen(std.in, "r");
console.log("Use q to quit");
while (f.getline() != "q") {
continue;
}
stopPubsub();
f.close();
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment