diff --git a/software/js-drone/README.md b/software/js-drone/README.md index 78c9126c0485363bbcf881f3449e6e9fe2d03d85..ccb325564ff6a73e1b8ae5253b740d60a6e3e65a 100644 --- a/software/js-drone/README.md +++ b/software/js-drone/README.md @@ -2,7 +2,7 @@ ## 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 @@ -20,8 +20,10 @@ * 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 ## -Run `quickjs binary location` `desired script location` +Run `quickjs binary location` `scripts location`/main.js diff --git a/software/js-drone/buildout.hash.cfg b/software/js-drone/buildout.hash.cfg index 463d7cb3c5637b4064235840168783124a7c0425..9a159be1d4292544d55843a5a06c66b3ceff2ad8 100644 --- a/software/js-drone/buildout.hash.cfg +++ b/software/js-drone/buildout.hash.cfg @@ -14,28 +14,12 @@ # not need these here). [instance-profile] filename = instance.cfg -md5sum = 9c754abbc80f795229c3e79a8ede534b +md5sum = ae1ccd9272303ee0102cdcec8ddef562 -[cli] -filename = cli.js -md5sum = 33271aeec124301604fdd406f0b339d1 - -[common] -filename = common.js -md5sum = 1a43f5cf3db1256fee985f82d88930a0 - -[demo] -filename = demo.js -md5sum = 31d8511e6d297643e65febe9a3ed2428 - -[manual-flight] -filename = manual-flight.js -md5sum = 175813fc8b2f19f91dae27ad4e14ab03 +[main] +filename = main.js +md5sum = 195c4ba934fb05f46dec18a5a132c450 [pubsub] filename = pubsub.js -md5sum = 1d1a2be301d74a619b63a33c4b4039da - -[subscribe] -filename = subscribe.js -md5sum = 772e84f5584fc66c976778bbd8ae6a65 +md5sum = d8798c3206f129e8715afd3ca23afa1a diff --git a/software/js-drone/cli.js b/software/js-drone/cli.js deleted file mode 100644 index 898597e5c6e48e563847bcad9a33b6ba217ef9bd..0000000000000000000000000000000000000000 --- a/software/js-drone/cli.js +++ /dev/null @@ -1,146 +0,0 @@ -/*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(); diff --git a/software/js-drone/common.js b/software/js-drone/common.js deleted file mode 100644 index c950db840f4822faac3e249b6bd5b926b10dd517..0000000000000000000000000000000000000000 --- a/software/js-drone/common.js +++ /dev/null @@ -1,184 +0,0 @@ -/*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(); - } -} diff --git a/software/js-drone/demo.js b/software/js-drone/demo.js deleted file mode 100644 index ce1b5ea53d4a9fe1241d518ec2a81d7b55b2baa0..0000000000000000000000000000000000000000 --- a/software/js-drone/demo.js +++ /dev/null @@ -1,195 +0,0 @@ -/*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(); diff --git a/software/js-drone/instance-input-schema.json b/software/js-drone/instance-input-schema.json new file mode 100644 index 0000000000000000000000000000000000000000..403be292170f078f9b0ad3f3f3120d1fdb0c6629 --- /dev/null +++ b/software/js-drone/instance-input-schema.json @@ -0,0 +1,56 @@ +{ + "$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 + } + } +} diff --git a/software/js-drone/instance.cfg b/software/js-drone/instance.cfg index 134a144edc4b53a61299eecdb94a28b0cd042b8c..661e1d9ac88ac9538cd500bf17930dff52c048b4 100644 --- a/software/js-drone/instance.cfg +++ b/software/js-drone/instance.cfg @@ -1,9 +1,6 @@ [buildout] parts = - cli - demo - manual-flight - subscribe + main eggs-directory = ${buildout:eggs-directory} develop-eggs-directory = ${buildout:develop-eggs-directory} @@ -28,14 +25,31 @@ cert = $${slap_connection:cert_file} recipe = slapos.recipe.build slapparameter-dict = $${slap-configuration:configuration} init = - options['autopilot-ip'] = options['slapparameter-dict'].get('autopilot_ip', '192.168.27.1') - options['id'] = options['slapparameter-dict'].get('id', '1') - options['is-a-simulation'] = options['slapparameter-dict'].get('is_a_simulation', 'false') - options['leader-id'] = options['slapparameter-dict'].get('leader_id', '1') - options['is-leader'] = 'true' if options['id'] == options['leader-id'] else 'false' - options['multicast-ipv6'] = options['slapparameter-dict'].get('multicast_ip', 'ff15::1111') - options['net-if'] = options['slapparameter-dict'].get('net_if', 'eth0') - options['drone-id-list'] = options['slapparameter-dict'].get('drone_id_list', '') + options['autopilot-ip'] = options['slapparameter-dict'].get('autopilot-ip', '192.168.27.1') + options['id'] = options['slapparameter-dict'].get('id', 1) + options['is-a-simulation'] = options['slapparameter-dict'].get('is-a-simulation', False) + options['leader-id'] = options['slapparameter-dict'].get('leader-id', 1) + options['is-leader'] = options['id'] == options['leader-id'] + options['multicast-ipv6'] = options['slapparameter-dict'].get('multicast-ip', 'ff15::1111') + options['net-if'] = options['slapparameter-dict'].get('net-if', 'eth0') + 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] recipe = slapos.recipe.template:jinja2 @@ -46,41 +60,22 @@ context = raw qjs_wrapper ${qjs-wrapper:location}/lib/libqjswrapper.so $${: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] <= js-dynamic-template extra-context = - key id drone:id key ipv6 drone:multicast-ipv6 key net_if drone:net-if -[subscribe] +[main] <= js-dynamic-template extra-context = + key autopilot_ip drone:autopilot-ip 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 diff --git a/software/js-drone/main.js b/software/js-drone/main.js new file mode 100644 index 0000000000000000000000000000000000000000..cba4c7e36179c2b9be6135b5b0dce2fe8b3b7e25 --- /dev/null +++ b/software/js-drone/main.js @@ -0,0 +1,124 @@ +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(); +}; diff --git a/software/js-drone/manual-flight.js b/software/js-drone/manual-flight.js deleted file mode 100644 index afad0c84e897caaba3563b3f93f547c417ce6fa9..0000000000000000000000000000000000000000 --- a/software/js-drone/manual-flight.js +++ /dev/null @@ -1,113 +0,0 @@ -/*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(); diff --git a/software/js-drone/pubsub.js b/software/js-drone/pubsub.js index c2491732487ede460e9f83dd48b9cb550d2817a4..bfe2022bc2794769e264afee346da806422a9d5d 100644 --- a/software/js-drone/pubsub.js +++ b/software/js-drone/pubsub.js @@ -9,7 +9,7 @@ var parent = Worker.parent; function handle_msg(e) { switch(e.data.action) { 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.onmessage = null; break; diff --git a/software/js-drone/software.cfg b/software/js-drone/software.cfg index c77b4ce3114a00cf9a3fd6e865ad002d2ddd165d..732387fe8cb3b236484166e109f794854e7fe4e4 100644 --- a/software/js-drone/software.cfg +++ b/software/js-drone/software.cfg @@ -6,12 +6,8 @@ extends = parts = instance-profile - common - cli - demo - manual-flight + main pubsub - subscribe slapos-cookbook [download-file-base] @@ -24,20 +20,8 @@ recipe = slapos.recipe.template url = ${:_profile_base_location_}/${:filename} output = ${buildout:directory}/template.cfg -[common] -<= download-file-base - -[cli] -<= download-file-base - -[demo] -<= download-file-base - -[manual-flight] +[main] <= download-file-base [pubsub] <= download-file-base - -[subscribe] -<= download-file-base diff --git a/software/js-drone/software.cfg.json b/software/js-drone/software.cfg.json new file mode 100644 index 0000000000000000000000000000000000000000..12c3331fa27a00e2a4029e1ab94af14e71c50551 --- /dev/null +++ b/software/js-drone/software.cfg.json @@ -0,0 +1,14 @@ +{ + "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 + } + } +} diff --git a/software/js-drone/subscribe.js b/software/js-drone/subscribe.js deleted file mode 100644 index f865224fb35059f5af901e66d026907d0b944b58..0000000000000000000000000000000000000000 --- a/software/js-drone/subscribe.js +++ /dev/null @@ -1,40 +0,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();