Commit d8b91190 authored by Roque's avatar Roque

Implement drone API and physics improvements

See merge request nexedi/erp5!1711
parents 70d11122 73f73897
/*global console*/
/*jslint nomen: true, indent: 2, maxlen: 80, white: true */
/************************** DRONE A AILE FIXE API ****************************/
var DroneAaileFixeAPI = /** @class */ (function () {
"use strict";
// var TAKEOFF_RADIUS = 60,
var LOITER_LIMIT = 30,
LOITER_RADIUS_FACTOR = 0.60,
LOITER_SPEED_FACTOR = 1.5;
//** CONSTRUCTOR
function DroneAaileFixeAPI(gameManager, drone_info, flight_parameters, id) {
this._gameManager = gameManager;
this._mapManager = this._gameManager._mapManager;
this._map_dict = this._mapManager.getMapInfo();
this._flight_parameters = flight_parameters;
this._id = id;
this._drone_info = drone_info;
this._loiter_radius = 0;
this._last_loiter_point_reached = -1;
//this._start_altitude = 0;
//this._last_altitude_point_reached = -1;
this._loiter_mode = false;
this._drone_dict_list = [];
}
/*
** Function called on start phase of the drone, just before onStart AI script
*/
DroneAaileFixeAPI.prototype.internal_start = function () {
return;
};
/*
** Function called on every drone update, right after onUpdate AI script
*/
DroneAaileFixeAPI.prototype.internal_update = function (drone) {
if (this._loiter_mode) {
this.loiter(drone);
}
/*if (this._start_altitude > 0) { //TODO move start_altitude here
this.reachAltitude(drone);
}*/
var _this = this, drone_position = drone.getCurrentPosition(), drone_info;
if (drone_position) {
drone_info = {
'altitudeRel' : drone_position.z,
'altitudeAbs' : this._mapManager.getMapInfo().start_AMSL +
drone_position.z,
'latitude' : drone_position.x,
'longitude' : drone_position.y
};
this._drone_dict_list[this._id] = drone_info;
//broadcast drone info using internal msg
this._gameManager._droneList.forEach(function (drone) {
if (drone.id !== _this._id) {
drone.internal_getMsg(drone_info, _this._id);
}
});
}
};
DroneAaileFixeAPI.prototype.internal_getMsg = function (msg, id) {
this._drone_dict_list[id] = msg;
};
DroneAaileFixeAPI.prototype.set_loiter_mode = function (radius) {
this._loiter_mode = true;
if (radius && radius > LOITER_LIMIT) {
this._loiter_radius = radius * LOITER_RADIUS_FACTOR;
this._loiter_center = this._last_target;
this._loiter_coordinates = [];
this._last_loiter_point_reached = -1;
var x1, y1, angle;
//for (var angle = 0; angle <360; angle+=8){ //counter-clockwise
for (angle = 360; angle > 0; angle-=8){ //clockwise
x1 = this._loiter_radius *
Math.cos(angle * (Math.PI / 180)) + this._loiter_center.x;
y1 = this._loiter_radius *
Math.sin(angle * (Math.PI / 180)) + this._loiter_center.y;
this._loiter_coordinates.push(
this.getCurrentPosition(x1, y1, this._loiter_center.z));
}
}
};
DroneAaileFixeAPI.prototype.internal_setTargetCoordinates =
function (drone, x, y, z, loiter) {
//this._start_altitude = 0;
//convert real geo-coordinates to virtual x-y coordinates
var coordinates = this.processCoordinates(x, y, z);
if (!loiter) {
this._loiter_mode = false;
drone._maxSpeed = this.getMaxSpeed();
//save last target point to use as next loiter center
this._last_target = coordinates;
}
this.internal_setVirtualPlaneTargetCoordinates(drone,
coordinates.x,
coordinates.y,
coordinates.z);
};
/*
** This expects x,y plane coordinates (not geo latitude-longitud)
*/
DroneAaileFixeAPI.prototype.internal_setVirtualPlaneTargetCoordinates =
function (drone, x, y, z) {
x -= drone._controlMesh.position.x;
y -= drone._controlMesh.position.z;
z -= drone._controlMesh.position.y;
drone.setDirection(x, y, z);
drone.setAcceleration(drone._maxAcceleration);
return;
};
DroneAaileFixeAPI.prototype.sendMsg = function (msg, to) {
var _this = this,
droneList = _this._gameManager._droneList;
_this._gameManager.delay(function () {
if (to < 0) {
// Send to all drones
droneList.forEach(function (drone) {
if (drone.infosMesh) {
try {
drone.onGetMsg(msg);
}
catch (error) {
console.warn('Drone crashed on sendMsg due to error:', error);
drone._internal_crash();
}
}
});
}
else {
// Send to specific drone
if (droneList[to].infosMesh) {
try {
droneList[to].onGetMsg(msg);
}
catch (error) {
console.warn('Drone crashed on sendMsg due to error:', error);
droneList[to]._internal_crash();
}
}
}
}, _this._flight_parameters.latency.communication);
};
DroneAaileFixeAPI.prototype.log = function (msg) {
console.log("API say : " + msg);
};
DroneAaileFixeAPI.prototype.getGameParameter = function (name) {
if (["gameTime", "map"].includes(name)) {
return this._gameManager.gameParameter[name];
}
};
/*
** Converts geo latitude-longitud coordinates (º) to x,y plane coordinates (m)
*/
DroneAaileFixeAPI.prototype.processCoordinates = function (lat, lon, z) {
if(isNaN(lat) || isNaN(lon) || isNaN(z)){
throw new Error('Target coordinates must be numbers');
}
var x = this._mapManager.longitudToX(lon, this._map_dict.width),
y = this._mapManager.latitudeToY(lat, this._map_dict.depth),
position = this._mapManager.normalize(x, y, this._map_dict),
processed_coordinates;
if (z > this._map_dict.start_AMSL) {
z -= this._map_dict.start_AMSL;
}
processed_coordinates = {
x: position[0],
y: position[1],
z: z
};
//this._last_altitude_point_reached = -1;
//this.takeoff_path = [];
return processed_coordinates;
};
DroneAaileFixeAPI.prototype.getCurrentPosition = function (x, y, z) {
return this._mapManager.convertToGeoCoordinates(x, y, z, this._map_dict);
};
DroneAaileFixeAPI.prototype.loiter = function (drone) {
if (this._loiter_radius > LOITER_LIMIT) {
var drone_pos = drone.getCurrentPosition(),
min = 9999, min_i, i, d, next_point;
//shift loiter circle to nearest point
if (this._last_loiter_point_reached === -1) {
if (!this.shifted) {
drone._maxSpeed = drone._maxSpeed * LOITER_SPEED_FACTOR;
for (i = 0; i < this._loiter_coordinates.length; i+=1){
d = this._mapManager.latLonDistance([drone_pos.x, drone_pos.y],
[this._loiter_coordinates[i].x,
this._loiter_coordinates[i].y]);
if (d < min) {
min = d;
min_i = i;
}
}
this._loiter_coordinates = this._loiter_coordinates.concat(
this._loiter_coordinates.splice(0,min_i));
this.shifted = true;
}
} else {
this.shifted = false;
}
//stop
if (this._last_loiter_point_reached ===
this._loiter_coordinates.length - 1) {
if (drone._maxSpeed !== this.getMaxSpeed()) {
drone._maxSpeed = this.getMaxSpeed();
}
drone.setDirection(0, 0, 0);
return;
}
//loiter
next_point =
this._loiter_coordinates[this._last_loiter_point_reached + 1];
this.internal_setTargetCoordinates(
drone, next_point.x, next_point.y, next_point.z, true);
if (this._mapManager.latLonDistance([drone_pos.x, drone_pos.y],
[next_point.x, next_point.y]) < 1) {
this._last_loiter_point_reached += 1;
if (this._last_loiter_point_reached ===
this._loiter_coordinates.length - 1) {
return;
}
next_point = this._loiter_coordinates[
this._last_loiter_point_reached + 1];
this.internal_setTargetCoordinates(
drone, next_point.x, next_point.y, next_point.z, true);
}
}
};
DroneAaileFixeAPI.prototype.getDroneAI = function () {
return null;
};
DroneAaileFixeAPI.prototype.setAltitude = function (altitude, drone) {
/*if (this._start_altitude === 0) {
this._start_altitude = 1;
}
this.takeoff_path = [];
if (skip_loiter) {*/
var drone_pos = drone.getCurrentPosition();
this.internal_setVirtualPlaneTargetCoordinates(drone,
drone_pos.x,
drone_pos.y,
altitude);
return;
/*}
var x1, y1,
LOOPS = 1,
CIRCLE_ANGLE = 8,
current_point = 0,
total_points = 360/CIRCLE_ANGLE*LOOPS,
initial_altitude = drone.getAltitudeAbs(),
center = {
x: drone.position.x,
y: drone.position.y,
z: drone.position.z
};
for (var l = 0; l <= LOOPS; l+=1){
for (var angle = 360; angle > 0; angle-=CIRCLE_ANGLE){ //clockwise sense
current_point++;
x1 = TAKEOFF_RADIUS * Math.cos(angle * (Math.PI / 180)) + center.x;
y1 = TAKEOFF_RADIUS * Math.sin(angle * (Math.PI / 180)) + center.y;
if (current_point < total_points/3) {
var FACTOR = 0.5;
x1 = center.x*FACTOR + x1*(1-FACTOR);
y1 = center.y*FACTOR + y1*(1-FACTOR);
}
this.takeoff_path.push({x: x1, y: y1, z: initial_altitude +
current_point * (altitude-initial_altitude)/total_points});
}
}*/
};
/*DroneAaileFixeAPI.prototype.reachAltitude = function (drone) {
function distance(p1, p2) {
return Math.sqrt(Math.pow(p1[0] - p2[0], 2) +
Math.pow(p1[1] - p2[1], 2));
}
//stop
if (this._last_altitude_point_reached === this.takeoff_path.length - 1) {
this._last_altitude_point_reached = -1;
this.takeoff_path = [];
this._start_altitude = 0;
drone.setDirection(0, 0, 0);
return;
}
//loiter
var drone_pos = {
x: drone.position.x,
y: drone.position.y,
z: drone.position.z
};
var next_point = this.takeoff_path[this._last_altitude_point_reached + 1];
this.internal_setVirtualPlaneTargetCoordinates(
next_point.x, next_point.y, next_point.z);
if (distance([drone_pos.x, drone_pos.y],
[next_point.x, next_point.y]) < 1) {
this._last_altitude_point_reached += 1;
if (this._last_altitude_point_reached === this.takeoff_path.length - 1) {
return;
}
next_point = this.takeoff_path[this._last_altitude_point_reached + 1];
this.internal_setVirtualPlaneTargetCoordinates(
next_point.x, next_point.y, next_point.z);
}
};*/
DroneAaileFixeAPI.prototype.getMaxSpeed = function () {
return this._flight_parameters.drone.maxSpeed;
};
DroneAaileFixeAPI.prototype.triggerParachute = function (drone) {
var drone_pos = drone.getCurrentPosition();
this.internal_setTargetCoordinates(drone, drone_pos.x, drone_pos.y, 5);
};
DroneAaileFixeAPI.prototype.landed = function (drone) {
var drone_pos = drone.getCurrentPosition();
return Math.floor(drone_pos.z) < 10;
};
DroneAaileFixeAPI.prototype.exit = function () {
return;
};
DroneAaileFixeAPI.prototype.getInitialAltitude = function () {
return 0;
};
DroneAaileFixeAPI.prototype.getAltitudeAbs = function (altitude) {
return altitude;
};
DroneAaileFixeAPI.prototype.getMinHeight = function () {
return 0;
};
DroneAaileFixeAPI.prototype.getMaxHeight = function () {
return 800;
};
DroneAaileFixeAPI.prototype.getFlightParameters = function () {
return this._flight_parameters;
};
return DroneAaileFixeAPI;
}());
\ No newline at end of file
/*global console*/ /*global BABYLON, console*/
/*jslint nomen: true, indent: 2, maxlen: 80, white: true */ /*jslint nomen: true, indent: 2, maxlen: 80, white: true */
/**************************** DRONE LOG FOLLOWER ******************************/ /**************************** DRONE LOG FOLLOWER ******************************/
var DroneLogAPI = /** @class */ (function () { var DroneLogAPI = /** @class */ (function () {
"use strict"; "use strict";
var TOP_SPEED = 250; //so fast that it virtually "teleports" to target
//** CONSTRUCTOR //** CONSTRUCTOR
function DroneLogAPI(gameManager, drone_info, flight_parameters, id) { function DroneLogAPI(gameManager, drone_info, flight_parameters, id) {
this._gameManager = gameManager; this._gameManager = gameManager;
...@@ -15,7 +16,13 @@ var DroneLogAPI = /** @class */ (function () { ...@@ -15,7 +16,13 @@ var DroneLogAPI = /** @class */ (function () {
/* /*
** Function called at start phase of the drone, just before onStart AI script ** Function called at start phase of the drone, just before onStart AI script
*/ */
DroneLogAPI.prototype.internal_start = function () { DroneLogAPI.prototype.internal_start = function (drone) {
drone._minAcceleration = -1;
drone._maxAcceleration = 1;
drone._minSpeed = TOP_SPEED;
drone._maxSpeed = TOP_SPEED;
drone._acceleration = 10;
drone._speed = TOP_SPEED;
function getLogEntries(log) { function getLogEntries(log) {
var i, line_list = log.split('\n'), log_entry_list = [], log_entry, var i, line_list = log.split('\n'), log_entry_list = [], log_entry,
log_header_found; log_header_found;
...@@ -69,22 +76,43 @@ var DroneLogAPI = /** @class */ (function () { ...@@ -69,22 +76,43 @@ var DroneLogAPI = /** @class */ (function () {
this._flight_parameters.converted_log_point_list = converted_log_point_list; this._flight_parameters.converted_log_point_list = converted_log_point_list;
}; };
/* /*
** Function called on every drone update, right before onUpdate AI script
*/
DroneLogAPI.prototype.internal_update = function (context, delta_time) {
var updateSpeed;
context._speed += context._acceleration * delta_time / 1000;
if (context._speed > context._maxSpeed) {
context._speed = context._maxSpeed;
}
if (context._speed < -context._maxSpeed) {
context._speed = -context._maxSpeed;
}
updateSpeed = context._speed * delta_time / 1000;
if (context._direction.x !== 0 ||
context._direction.y !== 0 ||
context._direction.z !== 0) {
context._controlMesh.position.addInPlace(new BABYLON.Vector3(
context._direction.x * updateSpeed,
context._direction.y * updateSpeed,
context._direction.z * updateSpeed));
}
context._controlMesh.computeWorldMatrix(true);
context._mesh.computeWorldMatrix(true);
};
/*
** Function called on every drone update, right after onUpdate AI script ** Function called on every drone update, right after onUpdate AI script
*/ */
DroneLogAPI.prototype.internal_update = function () { DroneLogAPI.prototype.internal_post_update = function (drone) {
return; return;
}; };
DroneLogAPI.prototype.internal_setTargetCoordinates = DroneLogAPI.prototype.internal_setTargetCoordinates =
function (drone, x, y, z) { function (drone, coordinates) {
var coordinates = this.processCoordinates(x, y, z);
coordinates.x -= drone._controlMesh.position.x; coordinates.x -= drone._controlMesh.position.x;
coordinates.y -= drone._controlMesh.position.z; coordinates.y -= drone._controlMesh.position.z;
coordinates.z -= drone._controlMesh.position.y; coordinates.z -= drone._controlMesh.position.y;
drone.setDirection(coordinates.x, coordinates.y, coordinates.z); drone.setDirection(coordinates.x, coordinates.y, coordinates.z);
drone.setAcceleration(drone._maxAcceleration);
return; return;
}; };
DroneLogAPI.prototype.sendMsg = function (msg, to) { DroneLogAPI.prototype.sendMsg = function (msg, to) {
return; return;
}; };
...@@ -96,6 +124,16 @@ var DroneLogAPI = /** @class */ (function () { ...@@ -96,6 +124,16 @@ var DroneLogAPI = /** @class */ (function () {
return this._gameManager.gameParameter[name]; return this._gameManager.gameParameter[name];
} }
}; };
DroneLogAPI.prototype.setStartingPosition = function (drone, x, y, z) {
if (!drone._canPlay) {
if (z <= 0.05) {
z = 0.05;
}
drone._controlMesh.position = new BABYLON.Vector3(x, z, y);
}
drone._controlMesh.computeWorldMatrix(true);
drone._mesh.computeWorldMatrix(true);
};
DroneLogAPI.prototype.processCoordinates = function (x, y, z) { DroneLogAPI.prototype.processCoordinates = function (x, y, z) {
if(isNaN(x) || isNaN(y) || isNaN(z)){ if(isNaN(x) || isNaN(y) || isNaN(z)){
throw new Error('Target coordinates must be numbers'); throw new Error('Target coordinates must be numbers');
...@@ -126,12 +164,11 @@ var DroneLogAPI = /** @class */ (function () { ...@@ -126,12 +164,11 @@ var DroneLogAPI = /** @class */ (function () {
'me.setTargetCoordinates(me.checkpoint_list[0][0], ' + 'me.setTargetCoordinates(me.checkpoint_list[0][0], ' +
'me.checkpoint_list[0][1], me.checkpoint_list[0][2]);' + 'me.checkpoint_list[0][1], me.checkpoint_list[0][2]);' +
'me.last_checkpoint_reached = -1;' + 'me.last_checkpoint_reached = -1;' +
'me.setAcceleration(10);' +
'};' + '};' +
'me.onUpdate = function(timestamp) {' + 'me.onUpdate = function(timestamp) {' +
'var next_checkpoint = me.checkpoint_list' + 'var next_checkpoint = me.checkpoint_list' +
'[me.last_checkpoint_reached+1];' + '[me.last_checkpoint_reached+1];' +
'if (distance([me.position.x, me.position.y], next_checkpoint) < 12) {' + 'if (distance([me.position.x, me.position.y], next_checkpoint) < 10) {' +
'me.going = false;' + 'me.going = false;' +
'var log_elapsed = next_checkpoint[3] - me.initTimestamp,' + 'var log_elapsed = next_checkpoint[3] - me.initTimestamp,' +
'time_elapsed = new Date() - me.startTime;' + 'time_elapsed = new Date() - me.startTime;' +
...@@ -165,30 +202,6 @@ var DroneLogAPI = /** @class */ (function () { ...@@ -165,30 +202,6 @@ var DroneLogAPI = /** @class */ (function () {
z: z z: z
}; };
}; };
DroneLogAPI.prototype.set_loiter_mode = function (radius, drone) {
return;
};
DroneLogAPI.prototype.setAltitude = function (altitude, drone) {
return;
};
DroneLogAPI.prototype.getMaxSpeed = function () {
return 3000;
};
DroneLogAPI.prototype.getInitialAltitude = function () {
return 0;
};
DroneLogAPI.prototype.getAltitudeAbs = function () {
return 0;
};
DroneLogAPI.prototype.getMinHeight = function () {
return 0;
};
DroneLogAPI.prototype.getMaxHeight = function () {
return 220;
};
DroneLogAPI.prototype.triggerParachute = function (drone) {
return;
};
DroneLogAPI.prototype.getFlightParameters = function () { DroneLogAPI.prototype.getFlightParameters = function () {
return this._flight_parameters; return this._flight_parameters;
}; };
......
...@@ -244,7 +244,7 @@ ...@@ -244,7 +244,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>1004.33468.24270.48913</string> </value> <value> <string>1006.4961.7659.53043</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -262,7 +262,7 @@ ...@@ -262,7 +262,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1669196851.18</float> <float>1675263473.08</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*global BABYLON, console*/
/*jslint nomen: true, indent: 2, maxlen: 80, todo: true */
/************************** FIXED WING DRONE API ****************************/
var FixedWingDroneAPI = /** @class */ (function () {
"use strict";
// var TAKEOFF_RADIUS = 60,
var DEFAULT_SPEED = 16,
EARTH_GRAVITY = 9.81,
LOITER_LIMIT = 30,
LOITER_RADIUS_FACTOR = 0.60,
LOITER_SPEED_FACTOR = 1.5,
MAX_ACCELERATION = 6,
MAX_DECELERATION = 1,
MIN_SPEED = 12,
MAX_SPEED = 26,
MAX_ROLL = 35,
MIN_PITCH = -20,
MAX_PITCH = 25,
MAX_CLIMB_RATE = 8,
MAX_SINK_RATE = 3;
//** CONSTRUCTOR
function FixedWingDroneAPI(gameManager, drone_info, flight_parameters, id) {
this._gameManager = gameManager;
this._mapManager = this._gameManager._mapManager;
this._map_dict = this._mapManager.getMapInfo();
this._flight_parameters = flight_parameters;
this._id = id;
this._drone_info = drone_info;
this._loiter_radius = 0;
this._last_loiter_point_reached = -1;
//this._start_altitude = 0;
//this._last_altitude_point_reached = -1;
this._loiter_mode = false;
this._drone_dict_list = [];
}
/*
** Function called on start phase of the drone, just before onStart AI script
*/
FixedWingDroneAPI.prototype.internal_start = function (drone) {
drone._maxDeceleration = this.getMaxDeceleration();
drone._maxAcceleration = this.getMaxAcceleration();
drone._minSpeed = this.getMinSpeed();
drone._maxSpeed = this.getMaxSpeed();
if (drone._minSpeed > drone._maxSpeed) {
throw new Error('min speed cannot be superior to max speed');
}
drone._speed = drone._targetSpeed = this.getInitialSpeed();
if (drone._speed < drone._minSpeed || drone._speed > drone._maxSpeed) {
throw new Error('Drone speed must be between min speed and max speed');
}
drone._minPitchAngle = this.getMinPitchAngle();
drone._maxPitchAngle = this.getMaxPitchAngle();
if (drone._minPitchAngle > drone._maxPitchAngle) {
throw new Error('min pitch angle cannot be superior to max pitch angle');
}
drone._maxRollAngle = this.getMaxRollAngle();
drone._maxSinkRate = this.getMaxSinkRate();
if (drone._maxSinkRate > drone._maxSpeed) {
throw new Error('max sink rate cannot be superior to max speed');
}
drone._maxClimbRate = this.getMaxClimbRate();
if (drone._maxClimbRate > drone._maxSpeed) {
throw new Error('max climb rate cannot be superior to max speed');
}
drone._maxOrientation = this.getMaxOrientation();
return;
};
/*
** Function called on every drone update, right before onUpdate AI script
*/
FixedWingDroneAPI.prototype.internal_update = function (context, delta_time) {
var diff, newrot, orientationValue, rotStep, updateSpeed;
//TODO rotation
if (context._rotationTarget) {
rotStep = BABYLON.Vector3.Zero();
diff = context._rotationTarget.subtract(context._controlMesh.rotation);
rotStep.x = (diff.x >= 1) ? 1 : diff.x;
rotStep.y = (diff.y >= 1) ? 1 : diff.y;
rotStep.z = (diff.z >= 1) ? 1 : diff.z;
if (rotStep === BABYLON.Vector3.Zero()) {
context._rotationTarget = null;
return;
}
newrot = new BABYLON.Vector3(context._controlMesh.rotation.x +
(rotStep.x * context._rotationSpeed),
context._controlMesh.rotation.y +
(rotStep.y * context._rotationSpeed),
context._controlMesh.rotation.z +
(rotStep.z * context._rotationSpeed)
);
context._controlMesh.rotation = newrot;
}
this._updateSpeed(context, delta_time);
this._updateDirection(context, delta_time);
updateSpeed = context._speed * delta_time / 1000;
if (context._direction.x !== 0 ||
context._direction.y !== 0 ||
context._direction.z !== 0) {
context._controlMesh.position.addInPlace(new BABYLON.Vector3(
context._direction.x * updateSpeed,
context._direction.y * updateSpeed,
context._direction.z * updateSpeed
));
}
//TODO rotation
orientationValue = context._maxOrientation *
(context._speed / context._maxSpeed);
context._mesh.rotation =
new BABYLON.Vector3(orientationValue * context._direction.z, 0,
-orientationValue * context._direction.x);
context._controlMesh.computeWorldMatrix(true);
context._mesh.computeWorldMatrix(true);
};
/*
** Function called on every drone update, right after onUpdate AI script
*/
FixedWingDroneAPI.prototype.internal_post_update = function (drone) {
var _this = this, drone_position = drone.getCurrentPosition(), drone_info;
if (_this._loiter_mode) {
_this.loiter(drone);
}
/*if (_this._start_altitude > 0) { //TODO move start_altitude here
_this.reachAltitude(drone);
}*/
if (drone_position) {
drone_info = {
'altitudeRel' : drone_position.z,
'altitudeAbs' : _this._mapManager.getMapInfo().start_AMSL +
drone_position.z,
'latitude' : drone_position.x,
'longitude' : drone_position.y
};
_this._drone_dict_list[_this._id] = drone_info;
//broadcast drone info using internal msg
_this._gameManager._droneList.forEach(function (drone) {
if (drone.id !== _this._id) {
drone.internal_getMsg(drone_info, _this._id);
}
});
}
};
FixedWingDroneAPI.prototype._updateSpeed = function (drone, delta_time) {
var speed = drone.getSpeed(), speedDiff, speedUpdate;
if (speed !== this._targetSpeed) {
speedDiff = this._targetSpeed - speed;
speedUpdate = drone._acceleration * delta_time / 1000;
if (Math.abs(speedDiff) < Math.abs(speedUpdate)) {
drone._speed = this._targetSpeed;
drone._acceleration = 0;
} else {
drone._speed += speedUpdate;
}
}
};
FixedWingDroneAPI.prototype._updateDirection = function (drone, delta_time) {
var horizontalCoeff, newX, newY, newZ;
[newX, newZ] = this._getNewYaw(drone, delta_time);
newY = this._getNewAltitude(drone);
horizontalCoeff = Math.sqrt(
(
Math.pow(drone.getSpeed(), 2) - Math.pow(newY, 2)
) / (
Math.pow(newX, 2) + Math.pow(newZ, 2)
)
);
newX *= horizontalCoeff;
newZ *= horizontalCoeff;
// swap y and z axis so z axis represents altitude
drone.setDirection(newX, newZ, newY);
};
FixedWingDroneAPI.prototype._getNewYaw = function (drone, delta_time) {
// swap y and z axis so z axis represents altitude
var bearing = this._computeBearing(
drone.position.x,
drone.position.y,
drone._targetCoordinates.x,
drone._targetCoordinates.y
),
yaw = drone.getYaw(),
yawDiff = this._computeYawDiff(yaw, bearing),
yawUpdate = this.getYawVelocity(drone) * delta_time / 1000;
if (yawUpdate >= Math.abs(yawDiff)) {
yawUpdate = yawDiff;
} else if (yawDiff < 0) {
yawUpdate *= -1;
}
yaw += yawUpdate;
// trigonometric circle is east oriented, yaw angle is clockwise
yaw = this._toRad(-yaw + 90);
return [Math.cos(yaw), Math.sin(yaw)];
};
FixedWingDroneAPI.prototype._getNewAltitude = function (drone) {
// swap y and z axis so z axis represents altitude
var altitudeDiff = drone._targetCoordinates.z - drone.position.z,
verticalSpeed;
if (altitudeDiff >= 0) {
verticalSpeed = this._computeVerticalSpeed(
altitudeDiff,
this.getMaxClimbRate(),
drone.getSpeed(),
this.getMaxPitchAngle()
);
} else {
verticalSpeed = -this._computeVerticalSpeed(
Math.abs(altitudeDiff),
this.getMaxSinkRate(),
drone.getSpeed(),
-this.getMinPitchAngle()
);
}
return verticalSpeed;
};
FixedWingDroneAPI.prototype.setRotation = function (drone, x, y, z) {
//TODO rotation
drone._rotationTarget = new BABYLON.Vector3(x, z, y);
};
FixedWingDroneAPI.prototype.setRotationBy = function (drone, x, y, z) {
//TODO rotation
drone._rotationTarget = new BABYLON.Vector3(drone.rotation.x + x,
drone.rotation.y + z,
drone.rotation.z + y);
};
FixedWingDroneAPI.prototype.setAltitude = function (drone, altitude) {
drone._targetCoordinates.z = altitude;
};
FixedWingDroneAPI.prototype.setSpeed = function (drone, speed) {
this._targetSpeed = Math.max(
Math.min(speed, this.getMaxSpeed()),
this.getMinSpeed()
);
drone._acceleration = (this._targetSpeed > drone.getSpeed())
? this.getMaxAcceleration() : -this.getMaxDeceleration();
};
FixedWingDroneAPI.prototype.setStartingPosition = function (drone, x, y, z) {
if (!drone._canPlay) {
if (z <= 0.05) {
z = 0.05;
}
drone._controlMesh.position = new BABYLON.Vector3(x, z, y);
}
drone._controlMesh.computeWorldMatrix(true);
drone._mesh.computeWorldMatrix(true);
};
FixedWingDroneAPI.prototype.internal_getMsg = function (msg, id) {
this._drone_dict_list[id] = msg;
};
FixedWingDroneAPI.prototype.set_loiter_mode = function (radius) {
this._loiter_mode = true;
if (radius && radius > LOITER_LIMIT) {
this._loiter_radius = radius * LOITER_RADIUS_FACTOR;
this._loiter_center = this._last_target;
this._loiter_coordinates = [];
this._last_loiter_point_reached = -1;
var x1, y1, angle;
//for (var angle = 0; angle <360; angle+=8){ //counter-clockwise
for (angle = 360; angle > 0; angle -= 8) { //clockwise
x1 = this._loiter_radius *
Math.cos(this._toRad(angle)) + this._loiter_center.x;
y1 = this._loiter_radius *
Math.sin(this._toRad(angle)) + this._loiter_center.y;
this._loiter_coordinates.push(
this.getCurrentPosition(x1, y1, this._loiter_center.z)
);
}
}
};
FixedWingDroneAPI.prototype.internal_setTargetCoordinates =
function (drone, coordinates, loiter) {
if (!loiter) {
this._loiter_mode = false;
//save last target point to use as next loiter center
this._last_target = coordinates;
}
};
FixedWingDroneAPI.prototype.sendMsg = function (msg, to) {
var _this = this,
droneList = _this._gameManager._droneList;
_this._gameManager.delay(function () {
if (to < 0) {
// Send to all drones
droneList.forEach(function (drone) {
if (drone.infosMesh) {
try {
drone.onGetMsg(msg);
} catch (error) {
console.warn('Drone crashed on sendMsg due to error:', error);
drone._internal_crash();
}
}
});
} else {
// Send to specific drone
if (droneList[to].infosMesh) {
try {
droneList[to].onGetMsg(msg);
} catch (error) {
console.warn('Drone crashed on sendMsg due to error:', error);
droneList[to]._internal_crash();
}
}
}
}, _this._flight_parameters.latency.communication);
};
FixedWingDroneAPI.prototype.log = function (msg) {
console.log("API say : " + msg);
};
FixedWingDroneAPI.prototype.getGameParameter = function (name) {
if (["gameTime", "map"].includes(name)) {
return this._gameManager.gameParameter[name];
}
};
/*
** Converts geo latitude-longitud coordinates (º) to x,y plane coordinates (m)
*/
FixedWingDroneAPI.prototype.processCoordinates = function (lat, lon, z) {
if (isNaN(lat) || isNaN(lon) || isNaN(z)) {
throw new Error('Target coordinates must be numbers');
}
var x = this._mapManager.longitudToX(lon, this._map_dict.width),
y = this._mapManager.latitudeToY(lat, this._map_dict.depth),
position = this._mapManager.normalize(x, y, this._map_dict),
processed_coordinates;
if (z > this._map_dict.start_AMSL) {
z -= this._map_dict.start_AMSL;
}
processed_coordinates = {
x: position[0],
y: position[1],
z: z
};
//this._last_altitude_point_reached = -1;
//this.takeoff_path = [];
return processed_coordinates;
};
FixedWingDroneAPI.prototype.getCurrentPosition = function (x, y, z) {
return this._mapManager.convertToGeoCoordinates(x, y, z, this._map_dict);
};
FixedWingDroneAPI.prototype.loiter = function (drone) {
if (this._loiter_radius > LOITER_LIMIT) {
var drone_pos = drone.getCurrentPosition(),
min = 9999,
min_i,
i,
d,
next_point;
//shift loiter circle to nearest point
if (this._last_loiter_point_reached === -1) {
if (!this.shifted) {
drone._maxSpeed = drone._maxSpeed * LOITER_SPEED_FACTOR;
for (i = 0; i < this._loiter_coordinates.length; i += 1) {
d = this._mapManager.latLonDistance([drone_pos.x, drone_pos.y],
[this._loiter_coordinates[i].x,
this._loiter_coordinates[i].y]);
if (d < min) {
min = d;
min_i = i;
}
}
this._loiter_coordinates = this._loiter_coordinates.concat(
this._loiter_coordinates.splice(0, min_i)
);
this.shifted = true;
}
} else {
this.shifted = false;
}
//stop
if (this._last_loiter_point_reached ===
this._loiter_coordinates.length - 1) {
if (drone._maxSpeed !== this.getMaxSpeed()) {
drone._maxSpeed = this.getMaxSpeed();
}
drone.setDirection(0, 0, 0);
return;
}
//loiter
next_point =
this._loiter_coordinates[this._last_loiter_point_reached + 1];
this.internal_setTargetCoordinates(drone, next_point, true);
if (this._mapManager.latLonDistance([drone_pos.x, drone_pos.y],
[next_point.x, next_point.y]) < 1) {
this._last_loiter_point_reached += 1;
if (this._last_loiter_point_reached ===
this._loiter_coordinates.length - 1) {
return;
}
next_point = this._loiter_coordinates[
this._last_loiter_point_reached + 1
];
this.internal_setTargetCoordinates(drone, next_point, true);
}
}
};
FixedWingDroneAPI.prototype.getDroneAI = function () {
return null;
};
FixedWingDroneAPI.prototype.getMinSpeed = function () {
return this._flight_parameters.drone.minSpeed || MIN_SPEED;
};
FixedWingDroneAPI.prototype.getMaxSpeed = function () {
return this._flight_parameters.drone.maxSpeed || MAX_SPEED;
};
FixedWingDroneAPI.prototype.getInitialSpeed = function () {
return this._flight_parameters.drone.speed || DEFAULT_SPEED;
};
FixedWingDroneAPI.prototype.getMaxDeceleration = function () {
return this._flight_parameters.drone.maxDeceleration || MAX_DECELERATION;
};
FixedWingDroneAPI.prototype.getMaxAcceleration = function () {
return this._flight_parameters.drone.maxAcceleration || MAX_ACCELERATION;
};
FixedWingDroneAPI.prototype.getMinPitchAngle = function () {
return this._flight_parameters.drone.minPitchAngle || MIN_PITCH;
};
FixedWingDroneAPI.prototype.getMaxPitchAngle = function () {
return this._flight_parameters.drone.maxPitchAngle || MAX_PITCH;
};
FixedWingDroneAPI.prototype.getMaxRollAngle = function () {
return this._flight_parameters.drone.maxRoll || MAX_ROLL;
};
FixedWingDroneAPI.prototype.getMaxSinkRate = function () {
return this._flight_parameters.drone.maxSinkRate || MAX_SINK_RATE;
};
FixedWingDroneAPI.prototype.getMaxClimbRate = function () {
return this._flight_parameters.drone.maxClimbRate || MAX_CLIMB_RATE;
};
FixedWingDroneAPI.prototype.getMaxOrientation = function () {
//TODO should be a game parameter (but how to force value to PI quarters?)
return Math.PI / 4;
};
FixedWingDroneAPI.prototype.getYawVelocity = function (drone) {
return 360 * EARTH_GRAVITY
* Math.tan(this._toRad(this.getMaxRollAngle()))
/ (2 * Math.PI * drone.getSpeed());
};
FixedWingDroneAPI.prototype.getYaw = function (drone) {
var direction = drone.worldDirection;
return this._computeBearing(0, 0, direction.x, direction.z);
};
FixedWingDroneAPI.prototype._computeBearing = function (x1, z1, x2, z2) {
return this._toDeg(Math.atan2(x2 - x1, z2 - z1));
};
FixedWingDroneAPI.prototype._computeYawDiff = function (yaw1, yaw2) {
var diff = yaw2 - yaw1;
diff += (diff > 180) ? -360 : (diff < -180) ? 360 : 0;
return diff;
};
FixedWingDroneAPI.prototype._computeVerticalSpeed =
function (altitude_diff, max_climb_rate, speed, max_pitch) {
var maxVerticalSpeed = Math.min(altitude_diff, Math.min(max_climb_rate, speed));
return (this._toDeg(Math.asin(maxVerticalSpeed / speed)) > max_pitch)
? speed * Math.sin(this._toRad(max_pitch))
: maxVerticalSpeed;
};
FixedWingDroneAPI.prototype._toRad = function (angle) {
return angle * Math.PI / 180;
};
FixedWingDroneAPI.prototype._toDeg = function (angle) {
return angle * 180 / Math.PI;
};
FixedWingDroneAPI.prototype.getClimbRate = function (drone) {
return drone.worldDirection.y * drone.getSpeed();
};
FixedWingDroneAPI.prototype.triggerParachute = function (drone) {
var drone_pos = drone.getCurrentPosition();
drone.setTargetCoordinates(drone_pos.x, drone_pos.y, 5);
};
FixedWingDroneAPI.prototype.landed = function (drone) {
var drone_pos = drone.getCurrentPosition();
return Math.floor(drone_pos.z) < 10;
};
FixedWingDroneAPI.prototype.exit = function () {
return;
};
FixedWingDroneAPI.prototype.getInitialAltitude = function () {
return 0;
};
FixedWingDroneAPI.prototype.getAltitudeAbs = function (altitude) {
return altitude;
};
FixedWingDroneAPI.prototype.getMinHeight = function () {
return 0;
};
FixedWingDroneAPI.prototype.getMaxHeight = function () {
return 800;
};
FixedWingDroneAPI.prototype.getFlightParameters = function () {
return this._flight_parameters;
};
return FixedWingDroneAPI;
}());
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
</item> </item>
<item> <item>
<key> <string>default_reference</string> </key> <key> <string>default_reference</string> </key>
<value> <string>gadget_erp5_page_drone_simulator_droneaaailefixe.js</string> </value> <value> <string>gadget_erp5_page_drone_simulator_fixedwingdrone.js</string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>drone_simulator_droneaaailefixe_js</string> </value> <value> <string>drone_simulator_fixedwingdrone_js</string> </value>
</item> </item>
<item> <item>
<key> <string>language</string> </key> <key> <string>language</string> </key>
...@@ -105,7 +105,7 @@ ...@@ -105,7 +105,7 @@
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <string>Drone A Aile Fixe (API)</string> </value> <value> <string>Fixed Wing Drone (API)</string> </value>
</item> </item>
<item> <item>
<key> <string>version</string> </key> <key> <string>version</string> </key>
...@@ -144,12 +144,6 @@ ...@@ -144,12 +144,6 @@
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value> </value>
</item> </item>
<item>
<key> <string>processing_status_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
</dictionary> </dictionary>
</value> </value>
</item> </item>
...@@ -195,7 +189,7 @@ ...@@ -195,7 +189,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1664807682.76</float> <float>1674834555.79</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
...@@ -244,7 +238,7 @@ ...@@ -244,7 +238,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>1004.62583.63891.22220</string> </value> <value> <string>1006.17822.27350.61713</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -262,70 +256,7 @@ ...@@ -262,70 +256,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1670856495.99</float> <float>1676035583.95</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_processing_state</string> </key>
<value> <string>empty</string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>0.0.0.0</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1664807031.69</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
/*global BABYLON, RSVP, console, DroneAaileFixeAPI, DroneLogAPI, document*/ /*global BABYLON, RSVP, console, FixedWingDroneAPI, DroneLogAPI, document*/
/*jslint nomen: true, indent: 2, maxlen: 80, white: true, todo: true, /*jslint nomen: true, indent: 2, maxlen: 80, todo: true,
unparam: true */ unparam: true */
var GAMEPARAMETERS = {}; var GAMEPARAMETERS = {};
...@@ -14,12 +14,20 @@ var DroneManager = /** @class */ (function () { ...@@ -14,12 +14,20 @@ var DroneManager = /** @class */ (function () {
this._controlMesh = null; this._controlMesh = null;
this._canPlay = false; this._canPlay = false;
this._canCommunicate = false; this._canCommunicate = false;
this._maxDeceleration = 0;
this._maxAcceleration = 0; this._maxAcceleration = 0;
this._minSpeed = 0;
this._maxSpeed = 0; this._maxSpeed = 0;
this._minPitchAngle = 0;
this._maxPitchAngle = 0;
this._maxRollAngle = 0;
this._maxSinkRate = 0;
this._maxClimbRate = 0;
this._maxOrientation = 0;
this._speed = 0; this._speed = 0;
this._acceleration = 0; this._acceleration = 0;
this._direction = BABYLON.Vector3.Zero(); this._direction = new BABYLON.Vector3(0, 0, 1); // North
this._maxOrientation = Math.PI / 4; this._rotationSpeed = 0.4;
this._scene = scene; this._scene = scene;
this._canUpdate = true; this._canUpdate = true;
this._id = id; this._id = id;
...@@ -27,7 +35,10 @@ var DroneManager = /** @class */ (function () { ...@@ -27,7 +35,10 @@ var DroneManager = /** @class */ (function () {
this._API = API; // var API created on AI evel this._API = API; // var API created on AI evel
// Create the control mesh // Create the control mesh
this._controlMesh = BABYLON.Mesh.CreateBox( this._controlMesh = BABYLON.Mesh.CreateBox(
"droneControl_" + id, 0.01, this._scene); "droneControl_" + id,
0.01,
this._scene
);
this._controlMesh.isVisible = false; this._controlMesh.isVisible = false;
this._controlMesh.computeWorldMatrix(true); this._controlMesh.computeWorldMatrix(true);
// Create the mesh from the drone prefab // Create the mesh from the drone prefab
...@@ -47,6 +58,7 @@ var DroneManager = /** @class */ (function () { ...@@ -47,6 +58,7 @@ var DroneManager = /** @class */ (function () {
} }
} }
DroneManager.prototype._swapAxe = function (vector) { DroneManager.prototype._swapAxe = function (vector) {
// swap y and z axis so z axis represents altitude
return new BABYLON.Vector3(vector.x, vector.z, vector.y); return new BABYLON.Vector3(vector.x, vector.z, vector.y);
}; };
Object.defineProperty(DroneManager.prototype, "leader_id", { Object.defineProperty(DroneManager.prototype, "leader_id", {
...@@ -79,6 +91,7 @@ var DroneManager = /** @class */ (function () { ...@@ -79,6 +91,7 @@ var DroneManager = /** @class */ (function () {
enumerable: true, enumerable: true,
configurable: true configurable: true
}); });
// swap y and z axis so z axis represents altitude
Object.defineProperty(DroneManager.prototype, "position", { Object.defineProperty(DroneManager.prototype, "position", {
get: function () { get: function () {
if (this._controlMesh !== null) { if (this._controlMesh !== null) {
...@@ -94,6 +107,7 @@ var DroneManager = /** @class */ (function () { ...@@ -94,6 +107,7 @@ var DroneManager = /** @class */ (function () {
enumerable: true, enumerable: true,
configurable: true configurable: true
}); });
// swap y and z axis so z axis represents altitude
Object.defineProperty(DroneManager.prototype, "direction", { Object.defineProperty(DroneManager.prototype, "direction", {
get: function () { return this._swapAxe(this._direction); }, get: function () { return this._swapAxe(this._direction); },
enumerable: true, enumerable: true,
...@@ -102,23 +116,25 @@ var DroneManager = /** @class */ (function () { ...@@ -102,23 +116,25 @@ var DroneManager = /** @class */ (function () {
Object.defineProperty(DroneManager.prototype, "worldDirection", { Object.defineProperty(DroneManager.prototype, "worldDirection", {
get: function () { get: function () {
return new BABYLON.Vector3( return new BABYLON.Vector3(
this._direction.x, this._direction.y, this._direction.z); this._direction.x,
this._direction.y,
this._direction.z
);
}, },
enumerable: true, enumerable: true,
configurable: true configurable: true
}); });
DroneManager.prototype.internal_start = function () { DroneManager.prototype.internal_start = function (initial_position) {
this._maxAcceleration = GAMEPARAMETERS.drone.maxAcceleration; this._API.internal_start(this);
this._maxSpeed = this._API.getMaxSpeed(); this._canPlay = true;
this._API.internal_start(); this._canCommunicate = true;
this._canPlay = true; this._targetCoordinates = initial_position;
this._canCommunicate = true; try {
try { return this.onStart();
return this.onStart(); } catch (error) {
} catch (error) { console.warn('Drone crashed on start due to error:', error);
console.warn('Drone crashed on start due to error:', error); this._internal_crash(error);
this._internal_crash(error); }
}
}; };
/** /**
* Set a target point to move * Set a target point to move
...@@ -127,29 +143,17 @@ var DroneManager = /** @class */ (function () { ...@@ -127,29 +143,17 @@ var DroneManager = /** @class */ (function () {
if (!this._canPlay) { if (!this._canPlay) {
return; return;
} }
return this._API.internal_setTargetCoordinates(this, x, y, z); //convert real geo-coordinates to virtual x-y coordinates
this._targetCoordinates = this._API.processCoordinates(x, y, z);
return this._API.internal_setTargetCoordinates(
this,
this._targetCoordinates
);
}; };
DroneManager.prototype.internal_update = function (delta_time) { DroneManager.prototype.internal_update = function (delta_time) {
var context = this, updateSpeed; var context = this;
if (this._controlMesh) { if (this._controlMesh) {
context._speed += context._acceleration * delta_time / 1000; context._API.internal_update(context, delta_time);
if (context._speed > context._maxSpeed) {
context._speed = context._maxSpeed;
}
if (context._speed < -context._maxSpeed) {
context._speed = -context._maxSpeed;
}
updateSpeed = context._speed * delta_time / 1000;
if (context._direction.x !== 0 ||
context._direction.y !== 0 ||
context._direction.z !== 0) {
context._controlMesh.position.addInPlace(new BABYLON.Vector3(
context._direction.x * updateSpeed,
context._direction.y * updateSpeed,
context._direction.z * updateSpeed));
}
context._controlMesh.computeWorldMatrix(true);
context._mesh.computeWorldMatrix(true);
if (context._canUpdate) { if (context._canUpdate) {
context._canUpdate = false; context._canUpdate = false;
return new RSVP.Queue() return new RSVP.Queue()
...@@ -163,7 +167,11 @@ var DroneManager = /** @class */ (function () { ...@@ -163,7 +167,11 @@ var DroneManager = /** @class */ (function () {
context._internal_crash(error); context._internal_crash(error);
}) })
.push(function () { .push(function () {
context._API.internal_update(context); context._API.internal_post_update(context);
})
.push(undefined, function (error) {
console.warn('Drone crashed on update due to error:', error);
context._internal_crash(error);
}); });
} }
return; return;
...@@ -181,29 +189,19 @@ var DroneManager = /** @class */ (function () { ...@@ -181,29 +189,19 @@ var DroneManager = /** @class */ (function () {
this.onTouched(); this.onTouched();
}; };
DroneManager.prototype.setStartingPosition = function (x, y, z) { DroneManager.prototype.setStartingPosition = function (x, y, z) {
if(isNaN(x) || isNaN(y) || isNaN(z)){ if (isNaN(x) || isNaN(y) || isNaN(z)) {
throw new Error('Position coordinates must be numbers'); throw new Error('Position coordinates must be numbers');
} }
if (!this._canPlay) { return this._API.setStartingPosition(this, x, y, z);
if (z <= 0.05) {
z = 0.05;
}
this._controlMesh.position = new BABYLON.Vector3(x, z, y);
}
this._controlMesh.computeWorldMatrix(true);
this._mesh.computeWorldMatrix(true);
}; };
DroneManager.prototype.setAcceleration = function (factor) { DroneManager.prototype.setSpeed = function (speed) {
if (!this._canPlay) { if (!this._canPlay) {
return; return;
} }
if (isNaN(factor)){ if (isNaN(speed)) {
throw new Error('Acceleration must be a number'); throw new Error('Speed must be a number');
} }
if (factor > this._maxAcceleration) { return this._API.setSpeed(this, speed);
factor = this._maxAcceleration;
}
this._acceleration = factor;
}; };
DroneManager.prototype.setDirection = function (x, y, z) { DroneManager.prototype.setDirection = function (x, y, z) {
if (!this._canPlay) { if (!this._canPlay) {
...@@ -212,8 +210,24 @@ var DroneManager = /** @class */ (function () { ...@@ -212,8 +210,24 @@ var DroneManager = /** @class */ (function () {
if (isNaN(x) || isNaN(y) || isNaN(z)) { if (isNaN(x) || isNaN(y) || isNaN(z)) {
throw new Error('Direction coordinates must be numbers'); throw new Error('Direction coordinates must be numbers');
} }
// swap y and z axis so z axis represents altitude
this._direction = new BABYLON.Vector3(x, z, y).normalize(); this._direction = new BABYLON.Vector3(x, z, y).normalize();
}; };
//TODO rotation
DroneManager.prototype.setRotation = function (x, y, z) {
if (!this._canPlay) {
return;
}
return this._API.setRotation(this, x, y, z);
};
DroneManager.prototype.setRotationBy = function (x, y, z) {
if (!this._canPlay) {
return;
}
return this._API.setRotation(this, x, y, z);
};
/** /**
* Send a message to drones * Send a message to drones
* @param msg The message to send * @param msg The message to send
...@@ -248,7 +262,7 @@ var DroneManager = /** @class */ (function () { ...@@ -248,7 +262,7 @@ var DroneManager = /** @class */ (function () {
return this._API.getMinHeight(); return this._API.getMinHeight();
}; };
DroneManager.prototype.getInitialAltitude = function () { DroneManager.prototype.getInitialAltitude = function () {
return this._API.getInitialAltitude(); return this._API.getInitialAltitude();
}; };
DroneManager.prototype.getAltitudeAbs = function () { DroneManager.prototype.getAltitudeAbs = function () {
if (this._controlMesh) { if (this._controlMesh) {
...@@ -269,6 +283,7 @@ var DroneManager = /** @class */ (function () { ...@@ -269,6 +283,7 @@ var DroneManager = /** @class */ (function () {
}; };
DroneManager.prototype.getCurrentPosition = function () { DroneManager.prototype.getCurrentPosition = function () {
if (this._controlMesh) { if (this._controlMesh) {
// swap y and z axis so z axis represents altitude
return this._API.getCurrentPosition( return this._API.getCurrentPosition(
this._controlMesh.position.x, this._controlMesh.position.x,
this._controlMesh.position.z, this._controlMesh.position.z,
...@@ -281,7 +296,7 @@ var DroneManager = /** @class */ (function () { ...@@ -281,7 +296,7 @@ var DroneManager = /** @class */ (function () {
if (!this._canPlay) { if (!this._canPlay) {
return; return;
} }
return this._API.setAltitude(altitude, this); return this._API.setAltitude(this, altitude);
}; };
/** /**
* Make the drone loiter (circle with a set radius) * Make the drone loiter (circle with a set radius)
...@@ -299,7 +314,16 @@ var DroneManager = /** @class */ (function () { ...@@ -299,7 +314,16 @@ var DroneManager = /** @class */ (function () {
return null; return null;
}; };
DroneManager.prototype.getYaw = function () { DroneManager.prototype.getYaw = function () {
return 0; return this._API.getYaw(this);
};
DroneManager.prototype.getSpeed = function () {
return this._speed;
};
DroneManager.prototype.getClimbRate = function () {
return this._API.getClimbRate(this);
};
DroneManager.prototype.getSinkRate = function () {
return this._API.getSinkRate();
}; };
DroneManager.prototype.triggerParachute = function () { DroneManager.prototype.triggerParachute = function () {
return this._API.triggerParachute(this); return this._API.triggerParachute(this);
...@@ -316,26 +340,27 @@ var DroneManager = /** @class */ (function () { ...@@ -316,26 +340,27 @@ var DroneManager = /** @class */ (function () {
* @param checkpoint to be set * @param checkpoint to be set
*/ */
DroneManager.prototype.setCheckpoint = function (checkpoint) { DroneManager.prototype.setCheckpoint = function (checkpoint) {
//TODO
return checkpoint; return checkpoint;
}; };
/** /**
* Function called on game start * Function called on game start
*/ */
DroneManager.prototype.onStart = function () { return;}; DroneManager.prototype.onStart = function () { return; };
/** /**
* Function called on game update * Function called on game update
* @param timestamp The tic value * @param timestamp The tic value
*/ */
DroneManager.prototype.onUpdate = function () { return;}; DroneManager.prototype.onUpdate = function () { return; };
/** /**
* Function called when drone crashes * Function called when drone crashes
*/ */
DroneManager.prototype.onTouched = function () { return;}; DroneManager.prototype.onTouched = function () { return; };
/** /**
* Function called when a message is received * Function called when a message is received
* @param msg The message * @param msg The message
*/ */
DroneManager.prototype.onGetMsg = function () { return;}; DroneManager.prototype.onGetMsg = function () { return; };
return DroneManager; return DroneManager;
}()); }());
...@@ -367,7 +392,8 @@ var MapManager = /** @class */ (function () { ...@@ -367,7 +392,8 @@ var MapManager = /** @class */ (function () {
position = map.normalize( position = map.normalize(
map.longitudToX(initial_position.longitude, map_size), map.longitudToX(initial_position.longitude, map_size),
map.latitudeToY(initial_position.latitude, map_size), map.latitudeToY(initial_position.latitude, map_size),
map_info); map_info
);
map_info.initial_position = { map_info.initial_position = {
"x": position[0], "x": position[0],
"y": position[1], "y": position[1],
...@@ -498,11 +524,10 @@ var GameManager = /** @class */ (function () { ...@@ -498,11 +524,10 @@ var GameManager = /** @class */ (function () {
if (GAMEPARAMETERS.draw_flight_path) { if (GAMEPARAMETERS.draw_flight_path) {
this._last_position_drawn = []; this._last_position_drawn = [];
this._trace_objects_per_drone = []; this._trace_objects_per_drone = [];
header_list = ["timestamp;", "latitude;", "longitude;", "AMSL (m);", header_list = ["timestamp", "latitude", "longitude", "AMSL (m)",
"rel altitude (m);", "pitch (°);", "roll(°);", "rel altitude (m)", "yaw(°)", "air speed (m/s)",
"yaw(°);", "air speed (m/s);", "throttle(%);",
"climb rate(m/s)"]; "climb rate(m/s)"];
for (drone = 0; drone < GAMEPARAMETERS.droneList.length; drone+=1) { for (drone = 0; drone < GAMEPARAMETERS.droneList.length; drone += 1) {
this._flight_log[drone] = []; this._flight_log[drone] = [];
this._flight_log[drone].push(header_list); this._flight_log[drone].push(header_list);
this._log_count[drone] = 0; this._log_count[drone] = 0;
...@@ -523,7 +548,7 @@ var GameManager = /** @class */ (function () { ...@@ -523,7 +548,7 @@ var GameManager = /** @class */ (function () {
]; ];
} }
this.APIs_dict = { this.APIs_dict = {
DroneAaileFixeAPI: DroneAaileFixeAPI, FixedWingDroneAPI: FixedWingDroneAPI,
DroneLogAPI: DroneLogAPI DroneLogAPI: DroneLogAPI
}; };
} }
...@@ -557,20 +582,25 @@ var GameManager = /** @class */ (function () { ...@@ -557,20 +582,25 @@ var GameManager = /** @class */ (function () {
if ((_this._canUpdate) && (_this.ongoing_update_promise === null) && if ((_this._canUpdate) && (_this.ongoing_update_promise === null) &&
(0 < _this.waiting_update_count)) { (0 < _this.waiting_update_count)) {
_this.ongoing_update_promise = _this._update( _this.ongoing_update_promise = _this._update(
TIME_DELTA, (_this.waiting_update_count === 1)) TIME_DELTA,
.push(function () { (_this.waiting_update_count === 1)
_this.waiting_update_count -= 1; ).push(function () {
_this.ongoing_update_promise = null; _this.waiting_update_count -= 1;
triggerUpdateIfPossible(); _this.ongoing_update_promise = null;
}) triggerUpdateIfPossible();
.push(undefined, function(error) { }).push(undefined, function (error) {
console.log("ERROR on update:", error); console.log("ERROR on Game Manager update:", error);
console.log("rejecting finish_deferred promise..."); _this.finish_deferred.reject.bind(_this.finish_deferred);
_this.finish_deferred.reject.bind(_this.finish_deferred); });
});
} }
} }
triggerUpdateIfPossible(); try {
triggerUpdateIfPossible();
} catch (error) {
console.log("ERROR on Game Manager update:", error);
_this.finish_deferred.reject.bind(_this.finish_deferred);
throw error;
}
}; };
GameManager.prototype.delay = function (callback, millisecond) { GameManager.prototype.delay = function (callback, millisecond) {
...@@ -582,7 +612,8 @@ var GameManager = /** @class */ (function () { ...@@ -582,7 +612,8 @@ var GameManager = /** @class */ (function () {
}; };
GameManager.prototype._checkDroneRules = function (drone) { GameManager.prototype._checkDroneRules = function (drone) {
//TODO move this to API methods //TODO move this to API methods.
//each type of drone should define its rules
if (drone.getCurrentPosition()) { if (drone.getCurrentPosition()) {
return drone.getCurrentPosition().z > 1; return drone.getCurrentPosition().z > 1;
} }
...@@ -631,57 +662,72 @@ var GameManager = /** @class */ (function () { ...@@ -631,57 +662,72 @@ var GameManager = /** @class */ (function () {
GameManager.prototype._updateTimeAndLog = GameManager.prototype._updateTimeAndLog =
function (delta_time) { function (delta_time) {
this._game_duration += delta_time; this._game_duration += delta_time;
var seconds = Math.floor(this._game_duration / 1000), drone, var color, drone_position, game_manager = this, geo_coordinates,
drone_position, map_info, geo_coordinates, position_obj, material, color; log_count, map_info, map_manager, material, position_obj,
if (GAMEPARAMETERS.log_drone_flight || GAMEPARAMETERS.draw_flight_path) { seconds = Math.floor(this._game_duration / 1000), trace_objects;
for (drone = 0; drone < GAMEPARAMETERS.droneList.length; drone+=1) {
if (this._droneList[drone].can_play) { if (GAMEPARAMETERS.log_drone_flight || GAMEPARAMETERS.draw_flight_path) {
drone_position = this._droneList[drone].position; this._droneList.forEach(function (drone, index) {
if (GAMEPARAMETERS.log_drone_flight) { if (drone.can_play) {
map_info = this._mapManager.getMapInfo(); drone_position = drone.position;
if (this._log_count[drone] === 0 || if (GAMEPARAMETERS.log_drone_flight) {
this._game_duration / this._log_count[drone] > 1) { map_manager = game_manager._mapManager;
this._log_count[drone] += GAMEPARAMETERS.log_interval_time; map_info = map_manager.getMapInfo();
geo_coordinates = this._mapManager.convertToGeoCoordinates( log_count = game_manager._log_count[index];
drone_position.x, drone_position.y, drone_position.z, map_info); if (log_count === 0 ||
this._flight_log[drone].push( game_manager._game_duration / log_count > 1) {
[this._game_duration, geo_coordinates.x, geo_coordinates.y, log_count += GAMEPARAMETERS.log_interval_time;
map_info.start_AMSL + drone_position.z, drone_position.z]); geo_coordinates = map_manager.convertToGeoCoordinates(
} drone_position.x,
} drone_position.y,
if (GAMEPARAMETERS.draw_flight_path) { drone_position.z,
//draw drone position every some seconds map_info
if (seconds - this._last_position_drawn[drone] > 0.2) { );
this._last_position_drawn[drone] = seconds; game_manager._flight_log[index].push([
position_obj = BABYLON.MeshBuilder.CreateBox("obs_" + seconds, game_manager._game_duration, geo_coordinates.x,
{ size: 1 }, geo_coordinates.y, map_info.start_AMSL + drone_position.z,
this._scene); drone_position.z, drone.getYaw(), drone.getSpeed(),
position_obj.position = new BABYLON.Vector3(drone_position.x, drone.getClimbRate()
drone_position.z, ]);
drone_position.y);
position_obj.scaling = new BABYLON.Vector3(4, 4, 4);
material = new BABYLON.StandardMaterial(this._scene);
material.alpha = 1;
color = new BABYLON.Color3(255, 0, 0);
if (this._colors[drone]) {
color = this._colors[drone];
} }
material.diffuseColor = color; }
position_obj.material = material; if (GAMEPARAMETERS.draw_flight_path) {
if (GAMEPARAMETERS.temp_flight_path) { //draw drone position every some seconds
if (this._trace_objects_per_drone[drone].length === 10) { if (seconds - game_manager._last_position_drawn[index] > 0.2) {
this._trace_objects_per_drone[drone][0].dispose(); game_manager._last_position_drawn[index] = seconds;
this._trace_objects_per_drone[drone].splice(0, 1); position_obj = BABYLON.MeshBuilder.CreateBox(
"obs_" + seconds,
{ size: 1 },
game_manager._scene
);
// swap y and z axis so z axis represents altitude
position_obj.position = new BABYLON.Vector3(drone_position.x,
drone_position.z,
drone_position.y);
position_obj.scaling = new BABYLON.Vector3(4, 4, 4);
material = new BABYLON.StandardMaterial(game_manager._scene);
material.alpha = 1;
color = new BABYLON.Color3(255, 0, 0);
if (game_manager._colors[index]) {
color = game_manager._colors[index];
}
material.diffuseColor = color;
position_obj.material = material;
if (GAMEPARAMETERS.temp_flight_path) {
trace_objects = game_manager._trace_objects_per_drone[index];
if (trace_objects.length === 10) {
trace_objects[0].dispose();
trace_objects.splice(0, 1);
}
trace_objects.push(position_obj);
} }
this._trace_objects_per_drone[drone].push(position_obj);
} }
} }
} }
} });
} }
} };
};
GameManager.prototype._timeOut = function () { GameManager.prototype._timeOut = function () {
var seconds = Math.floor(this._game_duration / 1000); var seconds = Math.floor(this._game_duration / 1000);
...@@ -723,16 +769,27 @@ var GameManager = /** @class */ (function () { ...@@ -723,16 +769,27 @@ var GameManager = /** @class */ (function () {
audioEngine: false audioEngine: false
}); });
this._scene = new BABYLON.Scene(this._engine); this._scene = new BABYLON.Scene(this._engine);
this._scene.clearColor = new BABYLON.Color4(88/255,171/255,217/255,255/255); this._scene.clearColor = new BABYLON.Color4(
88 / 255,
171 / 255,
217 / 255,
255 / 255
);
//removed for event handling //removed for event handling
//this._engine.enableOfflineSupport = false; //this._engine.enableOfflineSupport = false;
//this._scene.collisionsEnabled = true; //this._scene.collisionsEnabled = true;
// Lights // Lights
hemi_north = new BABYLON.HemisphericLight( hemi_north = new BABYLON.HemisphericLight(
"hemiN", new BABYLON.Vector3(1, -1, 1), this._scene); "hemiN",
new BABYLON.Vector3(1, -1, 1),
this._scene
);
hemi_north.intensity = 0.75; hemi_north.intensity = 0.75;
hemi_south = new BABYLON.HemisphericLight( hemi_south = new BABYLON.HemisphericLight(
"hemiS", new BABYLON.Vector3(-1, 1, -1), this._scene); "hemiS",
new BABYLON.Vector3(-1, 1, -1),
this._scene
);
hemi_south.intensity = 0.75; hemi_south.intensity = 0.75;
camera = new BABYLON.ArcRotateCamera("camera", 0, 1.25, 800, camera = new BABYLON.ArcRotateCamera("camera", 0, 1.25, 800,
BABYLON.Vector3.Zero(), this._scene); BABYLON.Vector3.Zero(), this._scene);
...@@ -762,12 +819,15 @@ var GameManager = /** @class */ (function () { ...@@ -762,12 +819,15 @@ var GameManager = /** @class */ (function () {
DroneManager.Prefab.isVisible = false; DroneManager.Prefab.isVisible = false;
//Hack to make advanced texture work //Hack to make advanced texture work
var documentTmp = document, advancedTexture, count, var documentTmp = document, advancedTexture, count,
controlMesh, rect, label; controlMesh, rect, label;
document = undefined; document = undefined;
advancedTexture = BABYLON.GUI.AdvancedDynamicTexture advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI(
.CreateFullscreenUI("UI", true, ctx._scene); "UI",
true,
ctx._scene
);
document = documentTmp; document = documentTmp;
for (count = 0; count < GAMEPARAMETERS.droneList.length; count+=1) { for (count = 0; count < GAMEPARAMETERS.droneList.length; count += 1) {
controlMesh = ctx._droneList[count].infosMesh; controlMesh = ctx._droneList[count].infosMesh;
rect = new BABYLON.GUI.Rectangle(); rect = new BABYLON.GUI.Rectangle();
rect.width = "10px"; rect.width = "10px";
...@@ -818,7 +878,9 @@ var GameManager = /** @class */ (function () { ...@@ -818,7 +878,9 @@ var GameManager = /** @class */ (function () {
promise_list = []; promise_list = [];
_this._droneList.forEach(function (drone) { _this._droneList.forEach(function (drone) {
drone._tick = 0; drone._tick = 0;
promise_list.push(drone.internal_start()); promise_list.push(drone.internal_start(
_this._mapManager.getMapInfo().initial_position
));
}); });
return RSVP.all(promise_list); return RSVP.all(promise_list);
}) })
...@@ -836,28 +898,28 @@ var GameManager = /** @class */ (function () { ...@@ -836,28 +898,28 @@ var GameManager = /** @class */ (function () {
droneTask = assetManager.addMeshTask("loadingDrone", "", "assets/drone/", droneTask = assetManager.addMeshTask("loadingDrone", "", "assets/drone/",
"drone.babylon"); "drone.babylon");
droneTask.onSuccess = function (task) { droneTask.onSuccess = function (task) {
task.loadedMeshes.forEach(function (mesh) { task.loadedMeshes.forEach(function (mesh) {
mesh.isPickable = false; mesh.isPickable = false;
mesh.isVisible = false; mesh.isVisible = false;
}); });
DroneManager.Prefab = _this._scene.getMeshByName("Dummy_Drone"); DroneManager.Prefab = _this._scene.getMeshByName("Dummy_Drone");
DroneManager.Prefab.scaling = new BABYLON.Vector3(0.006, 0.006, 0.006); DroneManager.Prefab.scaling = new BABYLON.Vector3(0.006, 0.006, 0.006);
DroneManager.Prefab.position = new BABYLON.Vector3(0, -5, 0); DroneManager.Prefab.position = new BABYLON.Vector3(0, -5, 0);
}; };
droneTask.onError = function () { droneTask.onError = function () {
console.log("Error loading 3D model for Drone"); console.log("Error loading 3D model for Drone");
}; };
// MAP // MAP
mapTask = assetManager.addMeshTask("loadingMap", "", "assets/map/", mapTask = assetManager.addMeshTask("loadingMap", "", "assets/map/",
"map.babylon"); "map.babylon");
mapTask.onSuccess = function (task) { mapTask.onSuccess = function (task) {
task.loadedMeshes.forEach(function (mesh) { task.loadedMeshes.forEach(function (mesh) {
mesh.isPickable = false; mesh.isPickable = false;
mesh.isVisible = false; mesh.isVisible = false;
}); });
}; };
mapTask.onError = function () { mapTask.onError = function () {
console.log("Error loading 3D model for Map"); console.log("Error loading 3D model for Map");
}; };
assetManager.onFinish = function () { assetManager.onFinish = function () {
return callback(); return callback();
...@@ -895,7 +957,7 @@ var GameManager = /** @class */ (function () { ...@@ -895,7 +957,7 @@ var GameManager = /** @class */ (function () {
code_eval = "let drone = new DroneManager(ctx._scene, " + code_eval = "let drone = new DroneManager(ctx._scene, " +
index + ', api);' + index + ', api);' +
"let droneMe = function(NativeDate, me, Math, window, DroneManager," + "let droneMe = function(NativeDate, me, Math, window, DroneManager," +
" GameManager, DroneLogAPI, DroneAaileFixeAPI, BABYLON, " + " GameManager, DroneLogAPI, FixedWingDroneAPI, BABYLON, " +
"GAMEPARAMETERS) {" + "GAMEPARAMETERS) {" +
"var start_time = (new Date(2070, 0, 0, 0, 0, 0, 0)).getTime();" + "var start_time = (new Date(2070, 0, 0, 0, 0, 0, 0)).getTime();" +
"Date.now = function () {" + "Date.now = function () {" +
...@@ -912,13 +974,12 @@ var GameManager = /** @class */ (function () { ...@@ -912,13 +974,12 @@ var GameManager = /** @class */ (function () {
} }
base = code_eval; base = code_eval;
code_eval += code + "}; droneMe(Date, drone, Math, {});"; code_eval += code + "}; droneMe(Date, drone, Math, {});";
base += "};ctx._droneList.push(drone)"; base += "};ctx._droneList.push(drone)";
code_eval += "ctx._droneList.push(drone)"; code_eval += "ctx._droneList.push(drone)";
/*jslint evil: true*/ /*jslint evil: true*/
try { try {
eval(code_eval); eval(code_eval);
} } catch (error) {
catch (error) {
eval(base); eval(base);
} }
/*jslint evil: false*/ /*jslint evil: false*/
...@@ -941,11 +1002,14 @@ var GameManager = /** @class */ (function () { ...@@ -941,11 +1002,14 @@ var GameManager = /** @class */ (function () {
if (collision_nb < max_collision) { if (collision_nb < max_collision) {
i -= 1; i -= 1;
} }
} } else {
else {
position_list.push(position); position_list.push(position);
api = new this.APIs_dict[drone_list[i].type]( api = new this.APIs_dict[drone_list[i].type](
this, drone_list[i], GAMEPARAMETERS, i); this,
drone_list[i],
GAMEPARAMETERS,
i
);
spawnDrone(position.x, position.y, position.z, i, spawnDrone(position.x, position.y, position.z, i,
drone_list[i], api); drone_list[i], api);
} }
...@@ -987,4 +1051,4 @@ var runGame, updateGame; ...@@ -987,4 +1051,4 @@ var runGame, updateGame;
}(this)); }(this));
/******************************************************************************/ /******************************************************************************/
\ No newline at end of file
...@@ -144,12 +144,6 @@ ...@@ -144,12 +144,6 @@
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent> <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value> </value>
</item> </item>
<item>
<key> <string>processing_status_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
</value>
</item>
</dictionary> </dictionary>
</value> </value>
</item> </item>
...@@ -195,7 +189,7 @@ ...@@ -195,7 +189,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1662477480.35</float> <float>1674834569.27</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
...@@ -244,7 +238,7 @@ ...@@ -244,7 +238,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>1004.32349.9544.44100</string> </value> <value> <string>1006.2016.60568.40294</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -262,70 +256,7 @@ ...@@ -262,70 +256,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1670852474.69</float> <float>1675086932.85</float>
<string>UTC</string>
</tuple>
</state>
</object>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="5" aka="AAAAAAAAAAU=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>actor</string> </key>
<value> <string>zope</string> </value>
</item>
<item>
<key> <string>comment</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>error_message</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_processing_state</string> </key>
<value> <string>empty</string> </value>
</item>
<item>
<key> <string>serial</string> </key>
<value> <string>0.0.0.0</string> </value>
</item>
<item>
<key> <string>time</string> </key>
<value>
<object>
<klass>
<global name="DateTime" module="DateTime.DateTime"/>
</klass>
<tuple>
<none/>
</tuple>
<state>
<tuple>
<float>1662477378.07</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
HEIGHT = 340, HEIGHT = 340,
LOGIC_FILE_LIST = [ LOGIC_FILE_LIST = [
'gadget_erp5_page_drone_simulator_logic.js', 'gadget_erp5_page_drone_simulator_logic.js',
'gadget_erp5_page_drone_simulator_droneaaailefixe.js', 'gadget_erp5_page_drone_simulator_fixedwingdrone.js',
'gadget_erp5_page_drone_simulator_dronelogfollower.js' 'gadget_erp5_page_drone_simulator_dronelogfollower.js'
]; ];
......
...@@ -244,7 +244,7 @@ ...@@ -244,7 +244,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>1005.1310.34623.11861</string> </value> <value> <string>1005.28725.31731.34065</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -262,7 +262,7 @@ ...@@ -262,7 +262,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1671112620.77</float> <float>1672757496.65</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -3,17 +3,25 @@ ...@@ -3,17 +3,25 @@
(function (window, rJS, domsugar, document, Blob) { (function (window, rJS, domsugar, document, Blob) {
"use strict"; "use strict";
//Default values //Default values - TODO: get them from the drone API
var SIMULATION_SPEED = 200, var SIMULATION_SPEED = 200,
SIMULATION_TIME = 1500, SIMULATION_TIME = 1500,
MAX_SPEED = 7.5, //16.666667,
MAX_ACCELERATION = 1,
min_lat = 45.6364, min_lat = 45.6364,
max_lat = 45.65, max_lat = 45.65,
min_lon = 14.2521, min_lon = 14.2521,
max_lon = 14.2766, max_lon = 14.2766,
map_height = 100, map_height = 100,
start_AMSL = 595, start_AMSL = 595,
DEFAULT_SPEED = 16,
MAX_ACCELERATION = 6,
MAX_DECELERATION = 1,
MIN_SPEED = 12,
MAX_SPEED = 26,
MAX_ROLL = 35,
MIN_PITCH = -20,
MAX_PITCH = 25,
MAX_CLIMB_RATE = 8,
MAX_SINK_RATE = 3,
INITIAL_POSITION = { INITIAL_POSITION = {
"latitude": 45.6412, "latitude": 45.6412,
"longitude": 14.2658, "longitude": 14.2658,
...@@ -122,7 +130,7 @@ ...@@ -122,7 +130,7 @@
HEIGHT = 340, HEIGHT = 340,
LOGIC_FILE_LIST = [ LOGIC_FILE_LIST = [
'gadget_erp5_page_drone_simulator_logic.js', 'gadget_erp5_page_drone_simulator_logic.js',
'gadget_erp5_page_drone_simulator_droneaaailefixe.js', 'gadget_erp5_page_drone_simulator_fixedwingdrone.js',
'gadget_erp5_page_drone_simulator_dronelogfollower.js' 'gadget_erp5_page_drone_simulator_dronelogfollower.js'
]; ];
...@@ -131,6 +139,7 @@ ...@@ -131,6 +139,7 @@
// Acquired methods // Acquired methods
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
.declareAcquiredMethod("updateHeader", "updateHeader") .declareAcquiredMethod("updateHeader", "updateHeader")
.declareAcquiredMethod("notifySubmitted", "notifySubmitted")
.allowPublicAcquisition('notifySubmit', function () { .allowPublicAcquisition('notifySubmit', function () {
return this.triggerSubmit(); return this.triggerSubmit();
...@@ -167,7 +176,7 @@ ...@@ -167,7 +176,7 @@
"editable": 1, "editable": 1,
"key": "simulation_speed", "key": "simulation_speed",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "IntegerField"
}, },
"my_simulation_time": { "my_simulation_time": {
"description": "Duration of the simulation (in seconds)", "description": "Duration of the simulation (in seconds)",
...@@ -178,29 +187,117 @@ ...@@ -178,29 +187,117 @@
"editable": 1, "editable": 1,
"key": "simulation_time", "key": "simulation_time",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "IntegerField"
},
"my_drone_min_speed": {
"description": "",
"title": "Drone min speed",
"default": MIN_SPEED,
"css_class": "",
"required": 0,
"editable": 1,
"key": "drone_min_speed",
"hidden": 0,
"type": "IntegerField"
}, },
"my_drone_speed": { "my_drone_speed": {
"description": "", "description": "",
"title": "Drone speed", "title": "Drone speed",
"default": MAX_SPEED, "default": DEFAULT_SPEED,
"css_class": "", "css_class": "",
"required": 1, "required": 0,
"editable": 1, "editable": 1,
"key": "drone_speed", "key": "drone_speed",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "FloatField"
}, },
"my_drone_acceleration": { "my_drone_max_speed": {
"description": "", "description": "",
"title": "Drone Acceleration", "title": "Drone max speed",
"default": MAX_SPEED,
"css_class": "",
"required": 0,
"editable": 1,
"key": "drone_max_speed",
"hidden": 0,
"type": "IntegerField"
},
"my_drone_max_acceleration": {
"description": "",
"title": "Drone max Acceleration",
"default": MAX_ACCELERATION, "default": MAX_ACCELERATION,
"css_class": "", "css_class": "",
"required": 1, "required": 0,
"editable": 1,
"key": "drone_max_acceleration",
"hidden": 0,
"type": "IntegerField"
},
"my_drone_max_deceleration": {
"description": "",
"title": "Drone max Deceleration",
"default": MAX_DECELERATION,
"css_class": "",
"required": 0,
"editable": 1, "editable": 1,
"key": "drone_acceleration", "key": "drone_max_deceleration",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "IntegerField"
},
"my_drone_max_roll": {
"description": "",
"title": "Drone max roll",
"default": MAX_ROLL,
"css_class": "",
"required": 0,
"editable": 1,
"key": "drone_max_roll",
"hidden": 0,
"type": "FloatField"
},
"my_drone_min_pitch": {
"description": "",
"title": "Drone min pitch",
"default": MIN_PITCH,
"css_class": "",
"required": 0,
"editable": 1,
"key": "drone_min_pitch",
"hidden": 0,
"type": "FloatField"
},
"my_drone_max_pitch": {
"description": "",
"title": "Drone max pitch",
"default": MAX_PITCH,
"css_class": "",
"required": 0,
"editable": 1,
"key": "drone_max_pitch",
"hidden": 0,
"type": "FloatField"
},
"my_drone_max_sink_rate": {
"description": "",
"title": "Drone max sink rate",
"default": MAX_SINK_RATE,
"css_class": "",
"required": 0,
"editable": 1,
"key": "drone_max_sink_rate",
"hidden": 0,
"type": "FloatField"
},
"my_drone_max_climb_rate": {
"description": "",
"title": "Drone max climb rate",
"default": MAX_CLIMB_RATE,
"css_class": "",
"required": 0,
"editable": 1,
"key": "drone_max_climb_rate",
"hidden": 0,
"type": "FloatField"
}, },
"my_minimum_latitud": { "my_minimum_latitud": {
"description": "", "description": "",
...@@ -211,7 +308,7 @@ ...@@ -211,7 +308,7 @@
"editable": 1, "editable": 1,
"key": "min_lat", "key": "min_lat",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "FloatField"
}, },
"my_maximum_latitud": { "my_maximum_latitud": {
"description": "", "description": "",
...@@ -222,7 +319,7 @@ ...@@ -222,7 +319,7 @@
"editable": 1, "editable": 1,
"key": "max_lat", "key": "max_lat",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "FloatField"
}, },
"my_minimum_longitud": { "my_minimum_longitud": {
"description": "", "description": "",
...@@ -233,7 +330,7 @@ ...@@ -233,7 +330,7 @@
"editable": 1, "editable": 1,
"key": "min_lon", "key": "min_lon",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "FloatField"
}, },
"my_maximum_longitud": { "my_maximum_longitud": {
"description": "", "description": "",
...@@ -244,7 +341,7 @@ ...@@ -244,7 +341,7 @@
"editable": 1, "editable": 1,
"key": "max_lon", "key": "max_lon",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "FloatField"
}, },
"my_start_AMSL": { "my_start_AMSL": {
"description": "", "description": "",
...@@ -255,7 +352,7 @@ ...@@ -255,7 +352,7 @@
"editable": 1, "editable": 1,
"key": "start_AMSL", "key": "start_AMSL",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "FloatField"
}, },
"my_map_height": { "my_map_height": {
"description": "", "description": "",
...@@ -266,7 +363,7 @@ ...@@ -266,7 +363,7 @@
"editable": 1, "editable": 1,
"key": "map_height", "key": "map_height",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "IntegerField"
}, },
"my_init_pos_lon": { "my_init_pos_lon": {
"description": "", "description": "",
...@@ -277,7 +374,7 @@ ...@@ -277,7 +374,7 @@
"editable": 1, "editable": 1,
"key": "init_pos_lon", "key": "init_pos_lon",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "FloatField"
}, },
"my_init_pos_lat": { "my_init_pos_lat": {
"description": "", "description": "",
...@@ -288,7 +385,7 @@ ...@@ -288,7 +385,7 @@
"editable": 1, "editable": 1,
"key": "init_pos_lat", "key": "init_pos_lat",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "FloatField"
}, },
"my_init_pos_z": { "my_init_pos_z": {
"description": "", "description": "",
...@@ -299,7 +396,7 @@ ...@@ -299,7 +396,7 @@
"editable": 1, "editable": 1,
"key": "init_pos_z", "key": "init_pos_z",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "FloatField"
}, },
"my_number_of_drones": { "my_number_of_drones": {
"description": "", "description": "",
...@@ -310,7 +407,7 @@ ...@@ -310,7 +407,7 @@
"editable": 1, "editable": 1,
"key": "number_of_drones", "key": "number_of_drones",
"hidden": 0, "hidden": 0,
"type": "StringField" "type": "IntegerField"
}, },
"my_script": { "my_script": {
"default": DEFAULT_SCRIPT_CONTENT, "default": DEFAULT_SCRIPT_CONTENT,
...@@ -334,14 +431,17 @@ ...@@ -334,14 +431,17 @@
form_definition: { form_definition: {
group_list: [[ group_list: [[
"left", "left",
[["my_simulation_speed"], ["my_simulation_time"], [["my_simulation_speed"], ["my_simulation_time"], ["my_number_of_drones"],
["my_drone_speed"], ["my_drone_acceleration"], ["my_minimum_latitud"], ["my_maximum_latitud"],
["my_number_of_drones"], ["my_map_height"], ["my_start_AMSL"]] ["my_minimum_longitud"], ["my_maximum_longitud"],
["my_init_pos_lat"], ["my_init_pos_lon"], ["my_init_pos_z"],
["my_map_height"]]
], [ ], [
"right", "right",
[["my_minimum_latitud"], ["my_maximum_latitud"], [["my_start_AMSL"], ["my_drone_min_speed"], ["my_drone_speed"], ["my_drone_max_speed"],
["my_minimum_longitud"], ["my_maximum_longitud"], ["my_drone_max_acceleration"], ["my_drone_max_deceleration"],
["my_init_pos_lat"], ["my_init_pos_lon"], ["my_init_pos_z"]] ["my_drone_max_roll"], ["my_drone_min_pitch"], ["my_drone_max_pitch"],
["my_drone_max_sink_rate"], ["my_drone_max_climb_rate"]]
], [ ], [
"bottom", "bottom",
[["my_script"]] [["my_script"]]
...@@ -358,23 +458,31 @@ ...@@ -358,23 +458,31 @@
}) })
.declareJob('runGame', function runGame(options) { .declareJob('runGame', function runGame(options) {
var gadget = this, simulator, i, var gadget = this, i,
fragment = gadget.element.querySelector('.simulator_div'), fragment = gadget.element.querySelector('.simulator_div'),
game_parameters_json; game_parameters_json;
fragment = domsugar(gadget.element.querySelector('.simulator_div'), fragment = domsugar(gadget.element.querySelector('.simulator_div'),
[domsugar('div')]).firstElementChild; [domsugar('div')]).firstElementChild;
DRONE_LIST = []; DRONE_LIST = [];
for (i = 0; i < options.number_of_drones; i += 1) { for (i = 0; i < options.number_of_drones; i += 1) {
DRONE_LIST[i] = {"id": i, "type": "DroneAaileFixeAPI", DRONE_LIST[i] = {"id": i, "type": "FixedWingDroneAPI",
"script_content": options.script}; "script_content": options.script};
} }
game_parameters_json = { game_parameters_json = {
"drone": { "drone": {
"maxAcceleration": parseFloat(options.drone_acceleration), "maxAcceleration": parseInt(options.drone_max_acceleration, 10),
"maxSpeed": parseFloat(options.drone_speed) "maxDeceleration": parseInt(options.drone_max_deceleration, 10),
"minSpeed": parseInt(options.drone_min_speed, 10),
"speed": parseFloat(options.drone_speed),
"maxSpeed": parseInt(options.drone_max_speed, 10),
"maxRoll": parseFloat(options.drone_max_roll),
"minPitchAngle": parseFloat(options.drone_min_pitch),
"maxPitchAngle": parseFloat(options.drone_max_pitch),
"maxSinkRate": parseFloat(options.drone_max_sink_rate),
"maxClimbRate": parseFloat(options.drone_max_climb_rate)
}, },
"gameTime": parseFloat(options.simulation_time), "gameTime": parseInt(options.simulation_time, 10),
"simulation_speed": parseFloat(options.simulation_speed), "simulation_speed": parseInt(options.simulation_speed, 10),
"latency": { "latency": {
"information": 0, "information": 0,
"communication": 0 "communication": 0
...@@ -384,7 +492,7 @@ ...@@ -384,7 +492,7 @@
"max_lat": parseFloat(options.max_lat), "max_lat": parseFloat(options.max_lat),
"min_lon": parseFloat(options.min_lon), "min_lon": parseFloat(options.min_lon),
"max_lon": parseFloat(options.max_lon), "max_lon": parseFloat(options.max_lon),
"height": parseFloat(options.map_height), "height": parseInt(options.map_height, 10),
"start_AMSL": parseFloat(options.start_AMSL) "start_AMSL": parseFloat(options.start_AMSL)
}, },
"initialPosition": { "initialPosition": {
...@@ -418,10 +526,10 @@ ...@@ -418,10 +526,10 @@
"url": "babylonjs.gadget.html", "url": "babylonjs.gadget.html",
"sandbox": "public", "sandbox": "public",
"renderjs_extra": '{"autorun": false, "width": ' + WIDTH + ', ' + "renderjs_extra": '{"autorun": false, "width": ' + WIDTH + ', ' +
'"height": ' + HEIGHT + ', ' + '"height": ' + HEIGHT + ', ' +
'"logic_file_list": ' + JSON.stringify(LOGIC_FILE_LIST) + ', ' + '"logic_file_list": ' + JSON.stringify(LOGIC_FILE_LIST) + ', ' +
'"game_parameters": ' + JSON.stringify(game_parameters_json) + '"game_parameters": ' + JSON.stringify(game_parameters_json) +
'}' '}'
} }
}}, }},
"_links": { "_links": {
...@@ -445,28 +553,34 @@ ...@@ -445,28 +553,34 @@
return form_gadget.getContent(); return form_gadget.getContent();
}) })
.push(function (result) { .push(function (result) {
var i = 0, var a, blob, div, key, log, log_content;
log_content, i = 0;
blob, for (key in result) {
a, if (result.hasOwnProperty(key)) {
log, log_content = result[key].join('\n').replaceAll(",", ";");
div; blob = new Blob([log_content], {type: 'text/plain'});
for (var key in result) { a = domsugar('a', {
log_content = result[key].join('\n').replaceAll(",", ";"); text: 'Download Simulation LOG ' + i,
blob = new Blob([log_content], {type: 'text/plain'}); download: 'simulation_log_' + i
a = domsugar('a', { + '_speed_' + game_parameters_json.drone.speed
text: 'Download Simulation LOG ' + i, + '_max-roll_' + game_parameters_json.drone.maxRoll
download: 'simulation_log_' + i + '.txt', + '_min-pitch_' + game_parameters_json.drone.minPitchAngle
href: window.URL.createObjectURL(blob) + '_max-pitch_' + game_parameters_json.drone.maxPitchAngle
}); + '.txt',
log = domsugar('textarea', { value: log_content }); href: window.URL.createObjectURL(blob)
div = domsugar('div', [a]); });
a.dataset.downloadurl = ['text/plain', a.download, log = domsugar('textarea', { value: log_content });
a.href].join(':'); div = domsugar('div', [a]);
document.querySelector('.container').appendChild(div); a.dataset.downloadurl = ['text/plain', a.download,
document.querySelector('.container').appendChild(log); a.href].join(':');
i++; document.querySelector('.container').appendChild(div);
document.querySelector('.container').appendChild(log);
i += 1;
}
} }
}, function (error) {
return gadget.notifySubmitted({message: "Error: " + error.message,
status: 'error'});
}); });
}); });
......
...@@ -244,7 +244,7 @@ ...@@ -244,7 +244,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>1005.37533.1915.8379</string> </value> <value> <string>1006.17791.59880.25668</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -262,7 +262,7 @@ ...@@ -262,7 +262,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1673286304.13</float> <float>1676033282.59</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -6,7 +6,7 @@ url_list = [ ...@@ -6,7 +6,7 @@ url_list = [
"gadget_erp5_page_drone_simulator_log_page.js", "gadget_erp5_page_drone_simulator_log_page.js",
"gadget_erp5_panel_drone_simulator.html", "gadget_erp5_panel_drone_simulator.html",
"gadget_erp5_panel_drone_simulator.js", "gadget_erp5_panel_drone_simulator.js",
"gadget_erp5_page_drone_simulator_droneaaailefixe.js", "gadget_erp5_page_drone_simulator_fixedwingdrone.js",
"gadget_erp5_page_drone_simulator_dronelogfollower.js", "gadget_erp5_page_drone_simulator_dronelogfollower.js",
"drone.png", "drone.png",
"gadget_officejs_drone_simulator.json", "gadget_officejs_drone_simulator.json",
......
...@@ -52,10 +52,16 @@ function mainToWorker(evt) { ...@@ -52,10 +52,16 @@ function mainToWorker(evt) {
}) })
.push(function () { .push(function () {
return postMessage({'type': 'updated'}); return postMessage({'type': 'updated'});
}, function (error) {
console.log("ERROR:", error);
return postMessage({'type': 'error', 'error': error});
}); });
case 'event': case 'event':
handleEvent(evt.data); return new RSVP.Queue(handleEvent(evt.data))
break; .push(undefined, function (error) {
console.log("ERROR:", error);
return postMessage({'type': 'error', 'error': error});
});
default: default:
throw new Error('Unsupported message ' + JSON.stringify(evt.data)); throw new Error('Unsupported message ' + JSON.stringify(evt.data));
} }
......
...@@ -244,7 +244,7 @@ ...@@ -244,7 +244,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>1004.22590.57904.22954</string> </value> <value> <string>1005.41422.8371.11861</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -262,7 +262,7 @@ ...@@ -262,7 +262,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1671113075.12</float> <float>1674224630.4</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
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