Common unit functions moved to unit class

This commit is contained in:
Pax1601 2023-06-06 12:50:18 +02:00
parent dca3438db0
commit 1d20a3b017
19 changed files with 274 additions and 197 deletions

View File

@ -1,5 +1,6 @@
import { getUnitsManager } from "../..";
import { Dropdown } from "../../controls/dropdown";
import { mToFt, msToKnots } from "../../other/utils";
import { ATC } from "../atc";
import { ATCBoard } from "../atcboard";
@ -139,7 +140,7 @@ export class ATCBoardTower extends ATCBoard {
assignedAltitude.value = flight.assignedAltitude;
}
flightData.altitude = Math.floor( flightData.altitude / 0.3048 );
flightData.altitude = Math.floor( mToFt(flightData.altitude) );
strip.element.querySelectorAll( `[data-point="altitude"]` ).forEach( el => {
if ( el instanceof HTMLElement ) {
@ -163,7 +164,7 @@ export class ATCBoardTower extends ATCBoard {
assignedSpeed.value = flight.assignedSpeed;
}
flightData.speed = Math.floor( flightData.speed * 1.94384 );
flightData.speed = Math.floor( msToKnots(flightData.speed) );
strip.element.querySelectorAll( `[data-point="speed"]` ).forEach( el => {
if ( el instanceof HTMLElement ) {

View File

@ -7,6 +7,7 @@ import { ContextMenu } from "./contextmenu";
import { Dropdown } from "./dropdown";
import { Switch } from "./switch";
import { Slider } from "./slider";
import { ftToM } from "../other/utils";
export interface SpawnOptions {
role: string;
@ -26,7 +27,7 @@ export class MapContextMenu extends ContextMenu {
#aircrafSpawnAltitudeSlider: Slider;
#groundUnitRoleDropdown: Dropdown;
#groundUnitTypeDropdown: Dropdown;
#spawnOptions: SpawnOptions = { role: "", type: "", latlng: new LatLng(0, 0), loadout: null, coalition: "blue", airbaseName: null, altitude: 20000 * 0.3048 };
#spawnOptions: SpawnOptions = { role: "", type: "", latlng: new LatLng(0, 0), loadout: null, coalition: "blue", airbaseName: null, altitude: ftToM(20000) };
constructor(id: string) {
super(id);
@ -37,7 +38,7 @@ export class MapContextMenu extends ContextMenu {
this.#aircraftRoleDropdown = new Dropdown("aircraft-role-options", (role: string) => this.#setAircraftRole(role));
this.#aircraftTypeDropdown = new Dropdown("aircraft-type-options", (type: string) => this.#setAircraftType(type));
this.#aircraftLoadoutDropdown = new Dropdown("loadout-options", (loadout: string) => this.#setAircraftLoadout(loadout));
this.#aircrafSpawnAltitudeSlider = new Slider("aircraft-spawn-altitude-slider", 0, 50000, "ft", (value: number) => {this.#spawnOptions.altitude = value * 0.3048;});
this.#aircrafSpawnAltitudeSlider = new Slider("aircraft-spawn-altitude-slider", 0, 50000, "ft", (value: number) => {this.#spawnOptions.altitude = ftToM(value);});
this.#groundUnitRoleDropdown = new Dropdown("ground-unit-role-options", (role: string) => this.#setGroundUnitRole(role));
this.#groundUnitTypeDropdown = new Dropdown("ground-unit-type-options", (type: string) => this.#setGroundUnitType(type));

View File

@ -1,4 +1,4 @@
import { deg2rad } from "../other/utils";
import { deg2rad, ftToM } from "../other/utils";
import { ContextMenu } from "./contextmenu";
export class UnitContextMenu extends ContextMenu {
@ -19,8 +19,8 @@ export class UnitContextMenu extends ContextMenu {
}
var angleDeg = 360 - (clock - 1) * 45;
var angleRad = deg2rad(angleDeg);
var distance = parseInt((<HTMLInputElement>dialog.querySelector(`#distance`)?.querySelector("input")).value) * 0.3048;
var upDown = parseInt((<HTMLInputElement>dialog.querySelector(`#up-down`)?.querySelector("input")).value) * 0.3048;
var distance = ftToM(parseInt((<HTMLInputElement>dialog.querySelector(`#distance`)?.querySelector("input")).value));
var upDown = ftToM(parseInt((<HTMLInputElement>dialog.querySelector(`#up-down`)?.querySelector("input")).value));
// X: front-rear, positive front
// Y: top-bottom, positive top

View File

@ -160,4 +160,20 @@ export function createDivWithClass(className: string) {
var el = document.createElement("div");
el.classList.add(className);
return el;
}
export function knotsToMs(knots: number) {
return knots / 1.94384;
}
export function msToKnots(ms: number) {
return ms * 1.94384;
}
export function ftToM(ft: number) {
return ft * 0.3048;
}
export function mToFt(m: number) {
return m / 0.3048;
}

View File

@ -7,6 +7,7 @@ import { Unit } from "../units/unit";
import { Panel } from "./panel";
import { Switch } from "../controls/switch";
import { ROEDescriptions, ROEs, altitudeIncrements, emissionsCountermeasures, emissionsCountermeasuresDescriptions, maxAltitudeValues, maxSpeedValues, minAltitudeValues, minSpeedValues, reactionsToThreat, reactionsToThreatDescriptions, speedIncrements } from "../constants/constants";
import { ftToM, knotsToMs, mToFt, msToKnots } from "../other/utils";
export class UnitControlPanel extends Panel {
#altitudeSlider: Slider;
@ -25,10 +26,10 @@ export class UnitControlPanel extends Panel {
super(ID);
/* Unit control sliders */
this.#altitudeSlider = new Slider("altitude-slider", 0, 100, "ft", (value: number) => { getUnitsManager().selectedUnitsSetAltitude(value * 0.3048); });
this.#altitudeSlider = new Slider("altitude-slider", 0, 100, "ft", (value: number) => { getUnitsManager().selectedUnitsSetAltitude(ftToM(value)); });
this.#altitudeTypeSwitch = new Switch("altitude-type-switch", (value: boolean) => { getUnitsManager().selectedUnitsSetAltitudeType(value? "AGL": "ASL"); });
this.#speedSlider = new Slider("speed-slider", 0, 100, "kts", (value: number) => { getUnitsManager().selectedUnitsSetSpeed(value / 1.94384); });
this.#speedSlider = new Slider("speed-slider", 0, 100, "kts", (value: number) => { getUnitsManager().selectedUnitsSetSpeed(knotsToMs(value)); });
this.#speedTypeSwitch = new Switch("speed-type-switch", (value: boolean) => { getUnitsManager().selectedUnitsSetSpeedType(value? "GS": "CAS"); });
/* Option buttons */
@ -156,11 +157,11 @@ export class UnitControlPanel extends Panel {
this.#speedSlider.setActive(targetSpeed != undefined);
if (targetSpeed != undefined)
this.#speedSlider.setValue(targetSpeed * 1.94384, false);
this.#speedSlider.setValue(msToKnots(targetSpeed), false);
this.#altitudeSlider.setActive(targetAltitude != undefined);
if (targetAltitude != undefined)
this.#altitudeSlider.setValue(targetAltitude / 0.3048, false);
this.#altitudeSlider.setValue(mToFt(targetAltitude), false);
}
else {
this.#speedSlider.setActive(false);

View File

@ -57,15 +57,8 @@ export class UnitInfoPanel extends Panel {
this.#unitLabel.innerText = aircraftDatabase.getByName(baseData.name)?.label || baseData.name;
this.#unitName.innerText = baseData.unitName;
this.#unitControl.innerText = ( ( baseData.AI ) ? "AI" : "Human" ) + " controlled";
// this.#groupName.innerText = baseData.groupName;
//this.#name.innerText = baseData.name;
//this.#heading.innerText = String(Math.floor(rad2deg(unit.getFlightData().heading)) + " °");
//this.#altitude.innerText = String(Math.floor(unit.getFlightData().altitude / 0.3048) + " ft");
//this.#groundSpeed.innerText = String(Math.floor(unit.getFlightData().speed * 1.94384) + " kts");
this.#fuelBar.style.width = String(unit.getMissionData().fuel + "%");
this.#fuelPercentage.dataset.percentage = "" + unit.getMissionData().fuel;
//this.#latitude.innerText = ConvertDDToDMS(unit.getFlightData().latitude, false);
//this.#longitude.innerText = ConvertDDToDMS(unit.getFlightData().longitude, true);
this.#currentTask.dataset.currentTask = unit.getTaskData().currentTask !== ""? unit.getTaskData().currentTask: "No task";
this.#currentTask.dataset.coalition = unit.getMissionData().coalition;

View File

@ -1,6 +1,6 @@
import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker, Map } from 'leaflet';
import { getMap, getUnitsManager } from '..';
import { rad2deg } from '../other/utils';
import { mToFt, msToKnots, rad2deg } from '../other/utils';
import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, getUnits, landAt, setAltitude, setReactionToThreat, setROE, setSpeed, refuel, setAdvacedOptions, followUnit, setEmissionsCountermeasures, setSpeedType, setAltitudeType, setOnOff, setFollowRoads } from '../server/server';
import { aircraftDatabase } from './aircraftdatabase';
import { groundUnitsDatabase } from './groundunitsdatabase';
@ -668,9 +668,9 @@ export class Unit extends CustomMarker {
/* Set altitude and speed */
if (element.querySelector(".unit-altitude"))
(<HTMLElement>element.querySelector(".unit-altitude")).innerText = "FL" + String(Math.floor(this.getFlightData().altitude / 0.3048 / 100));
(<HTMLElement>element.querySelector(".unit-altitude")).innerText = "FL" + String(Math.floor(mToFt(this.getFlightData().altitude) / 100));
if (element.querySelector(".unit-speed"))
(<HTMLElement>element.querySelector(".unit-speed")).innerText = String(Math.floor(this.getFlightData().speed * 1.94384));
(<HTMLElement>element.querySelector(".unit-speed")).innerText = String(Math.floor(msToKnots(this.getFlightData().speed))) + "GS";
/* Rotate elements according to heading */
element.querySelectorAll("[data-rotate-to-heading]").forEach(el => {

View File

@ -3,7 +3,7 @@ import { getHotgroupPanel, getInfoPopup, getMap, getUnitDataTable } from "..";
import { Unit } from "./unit";
import { cloneUnit } from "../server/server";
import { IDLE, MOVE_UNIT } from "../map/map";
import { deg2rad, keyEventWasInInput, latLngToMercator, mercatorToLatLng } from "../other/utils";
import { deg2rad, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots } from "../other/utils";
export class UnitsManager {
#units: { [ID: number]: Unit };
@ -250,7 +250,7 @@ export class UnitsManager {
for (let idx in selectedUnits) {
selectedUnits[idx].setSpeed(speed);
}
this.#showActionMessage(selectedUnits, `setting speed to ${speed * 1.94384} kts`);
this.#showActionMessage(selectedUnits, `setting speed to ${msToKnots(speed)} kts`);
}
selectedUnitsSetSpeedType(speedType: string) {
@ -266,7 +266,7 @@ export class UnitsManager {
for (let idx in selectedUnits) {
selectedUnits[idx].setAltitude(altitude);
}
this.#showActionMessage(selectedUnits, `setting altitude to ${altitude / 0.3048} ft`);
this.#showActionMessage(selectedUnits, `setting altitude to ${mToFt(altitude)} ft`);
}
selectedUnitsSetAltitudeType(altitudeType: string) {

View File

@ -12,19 +12,12 @@ class AirUnit : public Unit
public:
AirUnit(json::value json, int ID);
virtual wstring getCategory() = 0;
virtual void changeSpeed(wstring change) {};
virtual void changeAltitude(wstring change) {};
virtual void setTargetSpeed(double newTargetSpeed);
virtual void setTargetAltitude(double newTargetAltitude);
virtual void setTargetSpeedType(wstring newTargetSpeedType);
virtual void setTargetAltitudeType(wstring newTargetAltitudeType);
virtual void setState(int newState);
virtual wstring getCategory() = 0;
virtual void changeSpeed(wstring change) = 0;
virtual void changeAltitude(wstring change) = 0;
protected:
virtual void AIloop();
virtual void setState(int newState);
bool isDestinationReached();
bool setActiveDestination();
bool updateActivePath(bool looping);
void goToDestination(wstring enrouteTask = L"nil");
};

View File

@ -7,12 +7,14 @@ class GroundUnit : public Unit
{
public:
GroundUnit(json::value json, int ID);
virtual void AIloop();
virtual wstring getCategory() { return L"GroundUnit"; };
virtual void setState(int newState);
virtual void changeSpeed(wstring change);
virtual void changeAltitude(wstring change) {};
virtual void setOnOff(bool newOnOff);
virtual void setFollowRoads(bool newFollowRoads);
protected:
virtual void AIloop();
};

View File

@ -9,6 +9,5 @@ public:
virtual wstring getCategory() { return L"NavyUnit"; };
virtual void changeSpeed(wstring change);
virtual void changeAltitude(wstring change) {};
};

View File

@ -70,6 +70,7 @@ public:
void setAlive(bool newAlive) { alive = newAlive; addMeasure(L"alive", json::value(newAlive));}
void setType(json::value newType) { type = newType; addMeasure(L"type", newType);}
void setCountry(int newCountry) { country = newCountry; addMeasure(L"country", json::value(newCountry));}
bool getAI() { return AI; }
wstring getName() { return name; }
wstring getUnitName() { return unitName; }
@ -84,6 +85,7 @@ public:
void setAltitude(double newAltitude) {altitude = newAltitude; addMeasure(L"altitude", json::value(newAltitude));}
void setHeading(double newHeading) {heading = newHeading; addMeasure(L"heading", json::value(newHeading));}
void setSpeed(double newSpeed) {speed = newSpeed; addMeasure(L"speed", json::value(newSpeed));}
double getLatitude() { return latitude; }
double getLongitude() { return longitude; }
double getAltitude() { return altitude; }
@ -97,6 +99,7 @@ public:
void setHasTask(bool newHasTask) { hasTask = newHasTask; addMeasure(L"hasTask", json::value(newHasTask)); }
void setCoalitionID(int newCoalitionID);
void setFlags(json::value newFlags) { flags = newFlags; addMeasure(L"flags", json::value(newFlags));}
double getFuel() { return fuel; }
json::value getAmmo() { return ammo; }
json::value getTargets() { return targets; }
@ -108,21 +111,18 @@ public:
/********** Formation data **********/
void setLeaderID(int newLeaderID) { leaderID = newLeaderID; addMeasure(L"leaderID", json::value(newLeaderID)); }
void setFormationOffset(Offset formationOffset);
int getLeaderID() { return leaderID; }
Offset getFormationoffset() { return formationOffset; }
/********** Task data **********/
void setCurrentTask(wstring newCurrentTask) { currentTask = newCurrentTask; addMeasure(L"currentTask", json::value(newCurrentTask)); }
virtual void setTargetSpeed(double newTargetSpeed) { targetSpeed = newTargetSpeed; addMeasure(L"targetSpeed", json::value(newTargetSpeed));}
virtual void setTargetAltitude(double newTargetAltitude) { targetAltitude = newTargetAltitude; addMeasure(L"targetAltitude", json::value(newTargetAltitude));}
virtual void setTargetSpeedType(wstring newTargetSpeedType) { targetSpeedType = newTargetSpeedType; addMeasure(L"targetSpeedType", json::value(newTargetSpeedType)); }
virtual void setTargetAltitudeType(wstring newTargetAltitudeType) { targetAltitudeType = newTargetAltitudeType; addMeasure(L"targetAltitudeType", json::value(newTargetAltitudeType)); }
void setTargetSpeed(double newTargetSpeed);
void setTargetAltitude(double newTargetAltitude);
void setTargetSpeedType(wstring newTargetSpeedType);
void setTargetAltitudeType(wstring newTargetAltitudeType);
void setActiveDestination(Coords newActiveDestination) { activeDestination = newActiveDestination; addMeasure(L"activeDestination", json::value("")); } // TODO fix
void setActivePath(list<Coords> newActivePath);
void clearActivePath();
void pushActivePathFront(Coords newActivePathFront);
void pushActivePathBack(Coords newActivePathBack);
void popActivePathFront();
void setTargetID(int newTargetID) { targetID = newTargetID; addMeasure(L"targetID", json::value(newTargetID));}
void setIsTanker(bool newIsTanker);
void setIsAWACS(bool newIsAWACS);
@ -150,6 +150,7 @@ public:
void setRadio(Options::Radio newradio);
void setGeneralSettings(Options::GeneralSettings newGeneralSettings);
void setEPLRS(bool newEPLRS);
wstring getROE() { return ROE; }
wstring getReactionToThreat() { return reactionToThreat; }
wstring getEmissionsCountermeasures() { return emissionsCountermeasures; };
@ -160,11 +161,15 @@ public:
/********** Control functions **********/
void landAt(Coords loc);
virtual void changeSpeed(wstring change){};
virtual void changeAltitude(wstring change){};
virtual void changeSpeed(wstring change) {};
virtual void changeAltitude(wstring change) {};
void resetActiveDestination();
virtual void setState(int newState) { state = newState; };
void resetTask();
void clearActivePath();
void pushActivePathFront(Coords newActivePathFront);
void pushActivePathBack(Coords newActivePathBack);
void popActivePathFront();
protected:
int ID;
@ -236,4 +241,8 @@ protected:
bool isLeaderAlive();
virtual void AIloop() = 0;
void addMeasure(wstring key, json::value value);
bool isDestinationReached(double threshold);
bool setActiveDestination();
bool updateActivePath(bool looping);
void goToDestination(wstring enrouteTask = L"nil");
};

View File

@ -18,8 +18,8 @@ Aircraft::Aircraft(json::value json, int ID) : AirUnit(json, ID)
log("New Aircraft created with ID: " + to_string(ID));
addMeasure(L"category", json::value(getCategory()));
double targetSpeed = 300 / 1.94384;
double targetAltitude = 20000 * 0.3048;
double targetSpeed = knotsToMs(300);
double targetAltitude = ftToM(20000);
setTargetSpeed(targetSpeed);
setTargetAltitude(targetAltitude);
};
@ -27,16 +27,14 @@ Aircraft::Aircraft(json::value json, int ID) : AirUnit(json, ID)
void Aircraft::changeSpeed(wstring change)
{
if (change.compare(L"stop") == 0)
{
setState(State::IDLE);
}
else if (change.compare(L"slow") == 0)
setTargetSpeed(getTargetSpeed() - 25 / 1.94384);
setTargetSpeed(getTargetSpeed() - knotsToMs(25));
else if (change.compare(L"fast") == 0)
setTargetSpeed(getTargetSpeed() + 25 / 1.94384);
setTargetSpeed(getTargetSpeed() + knotsToMs(25));
if (getTargetSpeed() < 50 / 1.94384)
setTargetSpeed(50 / 1.94384);
if (getTargetSpeed() < knotsToMs(50))
setTargetSpeed(knotsToMs(50));
goToDestination(); /* Send the command to reach the destination */
}
@ -46,16 +44,16 @@ void Aircraft::changeAltitude(wstring change)
if (change.compare(L"descend") == 0)
{
if (getTargetAltitude() > 5000)
setTargetAltitude(getTargetAltitude() - 2500 / 3.28084);
setTargetAltitude(getTargetAltitude() - ftToM(2500));
else if (getTargetAltitude() > 0)
setTargetAltitude(getTargetAltitude() - 500 / 3.28084);
setTargetAltitude(getTargetAltitude() - ftToM(500));
}
else if (change.compare(L"climb") == 0)
{
if (getTargetAltitude() > 5000)
setTargetAltitude(getTargetAltitude() + 2500 / 3.28084);
setTargetAltitude(getTargetAltitude() + ftToM(2500));
else if (getTargetAltitude() >= 0)
setTargetAltitude(getTargetAltitude() + 500 / 3.28084);
setTargetAltitude(getTargetAltitude() + ftToM(500));
}
if (getTargetAltitude() < 0)
setTargetAltitude(0);

View File

@ -20,7 +20,7 @@ AirUnit::AirUnit(json::value json, int ID) : Unit(json, ID)
void AirUnit::setState(int newState)
{
/************ Perform any action required when LEAVING a certain state ************/
/************ Perform any action required when LEAVING a state ************/
if (newState != state) {
switch (state) {
case State::IDLE: {
@ -48,7 +48,7 @@ void AirUnit::setState(int newState)
}
}
/************ Perform any action required when ENTERING a certain state ************/
/************ Perform any action required when ENTERING a state ************/
switch (newState) {
case State::IDLE: {
clearActivePath();
@ -100,67 +100,6 @@ void AirUnit::setState(int newState)
state = newState;
}
bool AirUnit::isDestinationReached()
{
if (activeDestination != NULL)
{
double dist = 0;
Geodesic::WGS84().Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, dist);
if (dist < AIR_DEST_DIST_THR)
{
log(unitName + L" destination reached");
return true;
}
else {
return false;
}
}
else
return true;
}
bool AirUnit::setActiveDestination()
{
if (activePath.size() > 0)
{
activeDestination = activePath.front();
log(unitName + L" active destination set to queue front");
return true;
}
else
{
activeDestination = Coords(0);
log(unitName + L" active destination set to NULL");
return false;
}
}
bool AirUnit::updateActivePath(bool looping)
{
if (activePath.size() > 0)
{
/* Push the next destination in the queue to the front */
if (looping)
pushActivePathBack(activePath.front());
popActivePathFront();
log(unitName + L" active path front popped");
return true;
}
else {
return false;
}
}
void AirUnit::goToDestination(wstring enrouteTask)
{
if (activeDestination != NULL)
{
Command* command = dynamic_cast<Command*>(new Move(ID, activeDestination, getTargetSpeed(), getTargetSpeedType(), getTargetAltitude(), getTargetAltitudeType(), enrouteTask));
scheduler->appendCommand(command);
setHasTask(true);
}
}
void AirUnit::AIloop()
{
/* State machine */
@ -168,7 +107,7 @@ void AirUnit::AIloop()
case State::IDLE: {
currentTask = L"Idle";
if (!hasTask)
if (!getHasTask())
{
std::wostringstream taskSS;
if (isTanker) {
@ -206,7 +145,7 @@ void AirUnit::AIloop()
currentTask = L"Reaching destination";
}
if (activeDestination == NULL || !hasTask)
if (activeDestination == NULL || !getHasTask())
{
if (!setActiveDestination())
setState(State::IDLE);
@ -214,7 +153,7 @@ void AirUnit::AIloop()
goToDestination(enrouteTask);
}
else {
if (isDestinationReached()) {
if (isDestinationReached(AIR_DEST_DIST_THR)) {
if (updateActivePath(looping) && setActiveDestination())
goToDestination(enrouteTask);
else
@ -251,7 +190,7 @@ void AirUnit::AIloop()
wstring enrouteTask = enrouteTaskSS.str();
currentTask = L"Attacking " + getTargetName();
if (!hasTask)
if (!getHasTask())
{
setActiveDestination();
goToDestination(enrouteTask);
@ -272,7 +211,7 @@ void AirUnit::AIloop()
currentTask = L"Following " + getTargetName();
Unit* leader = unitsManager->getUnit(leaderID);
if (!hasTask) {
if (!getHasTask()) {
if (leader != nullptr && leader->getAlive() && formationOffset != NULL)
{
std::wostringstream taskSS;
@ -295,7 +234,7 @@ void AirUnit::AIloop()
case State::REFUEL: {
currentTask = L"Refueling";
if (!hasTask) {
if (!getHasTask()) {
if (fuel <= initialFuel) {
std::wostringstream taskSS;
taskSS << "{"
@ -316,23 +255,3 @@ void AirUnit::AIloop()
addMeasure(L"currentTask", json::value(currentTask));
}
void AirUnit::setTargetSpeed(double newTargetSpeed) {
Unit::setTargetSpeed(newTargetSpeed);
goToDestination();
}
void AirUnit::setTargetAltitude(double newTargetAltitude) {
Unit::setTargetAltitude(newTargetAltitude);
goToDestination();
}
void AirUnit::setTargetSpeedType(wstring newTargetSpeedType) {
Unit::setTargetSpeedType(newTargetSpeedType);
goToDestination();
}
void AirUnit::setTargetAltitudeType(wstring newTargetAltitudeType) {
Unit::setTargetAltitudeType(newTargetAltitudeType);
goToDestination();
}

View File

@ -22,60 +22,98 @@ GroundUnit::GroundUnit(json::value json, int ID) : Unit(json, ID)
setTargetSpeed(targetSpeed);
};
void GroundUnit::setState(int newState)
{
/************ Perform any action required when LEAVING a state ************/
if (newState != state) {
switch (state) {
case State::IDLE: {
break;
}
case State::REACH_DESTINATION: {
break;
}
default:
break;
}
}
/************ Perform any action required when ENTERING a state ************/
switch (newState) {
case State::IDLE: {
clearActivePath();
resetActiveDestination();
addMeasure(L"currentState", json::value(L"Idle"));
break;
}
case State::REACH_DESTINATION: {
resetActiveDestination();
addMeasure(L"currentState", json::value(L"Reach destination"));
break;
}
default:
break;
}
resetTask();
log(unitName + L" setting state from " + to_wstring(state) + L" to " + to_wstring(newState));
state = newState;
}
void GroundUnit::AIloop()
{
/* Set the active destination to be always equal to the first point of the active path. This is in common with all AI units */
if (activePath.size() > 0)
{
if (activeDestination != activePath.front())
{
activeDestination = activePath.front();
std::wostringstream taskSS;
taskSS << "{ id = 'FollowRoads', value = " << (getFollowRoads()? "true" : "false") << " }";
Command* command = dynamic_cast<Command*>(new Move(ID, activeDestination, getTargetSpeed(), getTargetSpeedType(), getTargetAltitude(), getTargetAltitudeType(), taskSS.str()));
scheduler->appendCommand(command);
}
switch (state) {
case State::IDLE: {
currentTask = L"Idle";
if (getHasTask())
resetTask();
break;
}
else
{
if (activeDestination != NULL)
case State::REACH_DESTINATION: {
wstring enrouteTask = L"";
bool looping = false;
std::wostringstream taskSS;
taskSS << "{ id = 'FollowRoads', value = " << (getFollowRoads() ? "true" : "false") << " }";
enrouteTask = taskSS.str();
if (activeDestination == NULL || !getHasTask())
{
log(unitName + L" no more points in active path");
activeDestination = Coords(0); // Set the active path to NULL
currentTask = L"Idle";
if (!setActiveDestination())
setState(State::IDLE);
else
goToDestination(enrouteTask);
}
else {
if (isDestinationReached(GROUND_DEST_DIST_THR)) {
if (updateActivePath(looping) && setActiveDestination())
goToDestination(enrouteTask);
else
setState(State::IDLE);
}
}
break;
}
default:
break;
}
/* Ground unit AI Loop */
if (activeDestination != NULL)
{
double newDist = 0;
Geodesic::WGS84().Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, newDist);
if (newDist < GROUND_DEST_DIST_THR)
{
/* Destination reached */
popActivePathFront();
log(unitName + L" destination reached");
}
}
addMeasure(L"currentTask", json::value(currentTask));
}
void GroundUnit::changeSpeed(wstring change)
{
if (change.compare(L"stop") == 0)
{
}
setState(State::IDLE);
else if (change.compare(L"slow") == 0)
{
}
setTargetSpeed(getTargetSpeed() - knotsToMs(5));
else if (change.compare(L"fast") == 0)
{
setTargetSpeed(getTargetSpeed() + knotsToMs(5));
}
if (getTargetSpeed() < 0)
setTargetSpeed(0);
}
void GroundUnit::setOnOff(bool newOnOff)

View File

@ -18,8 +18,8 @@ Helicopter::Helicopter(json::value json, int ID) : AirUnit(json, ID)
log("New Helicopter created with ID: " + to_string(ID));
addMeasure(L"category", json::value(getCategory()));
double targetSpeed = 100 / 1.94384;
double targetAltitude = 5000 * 0.3048;
double targetSpeed = knotsToMs(100);
double targetAltitude = ftToM(5000);
setTargetSpeed(targetSpeed);
setTargetAltitude(targetAltitude);
};
@ -32,9 +32,9 @@ void Helicopter::changeSpeed(wstring change)
clearActivePath();
}
else if (change.compare(L"slow") == 0)
targetSpeed -= 10 / 1.94384;
targetSpeed -= knotsToMs(10);
else if (change.compare(L"fast") == 0)
targetSpeed += 10 / 1.94384;
targetSpeed += knotsToMs(10);
if (targetSpeed < 0)
targetSpeed = 0;
@ -46,16 +46,16 @@ void Helicopter::changeAltitude(wstring change)
if (change.compare(L"descend") == 0)
{
if (targetAltitude > 100)
targetAltitude -= 100 / 3.28084;
targetAltitude -= ftToM(100);
else if (targetAltitude > 0)
targetAltitude -= 10 / 3.28084;
targetAltitude -= ftToM(10);
}
else if (change.compare(L"climb") == 0)
{
if (targetAltitude > 100)
targetAltitude += 100 / 3.28084;
targetAltitude += ftToM(100);
else if (targetAltitude >= 0)
targetAltitude += 10 / 3.28084;
targetAltitude += ftToM(10);
}
if (targetAltitude < 0)
targetAltitude = 0;

View File

@ -324,6 +324,7 @@ void Unit::resetTask()
{
Command* command = dynamic_cast<Command*>(new ResetTask(ID));
scheduler->appendCommand(command);
setHasTask(false);
}
void Unit::setFormationOffset(Offset newFormationOffset)
@ -576,3 +577,87 @@ void Unit::setGeneralSettings(Options::GeneralSettings newGeneralSettings) {
}
}
void Unit::setTargetSpeed(double newTargetSpeed) {
targetSpeed = newTargetSpeed;
addMeasure(L"targetSpeed", json::value(newTargetSpeed));
goToDestination();
}
void Unit::setTargetAltitude(double newTargetAltitude) {
targetAltitude = newTargetAltitude;
addMeasure(L"targetAltitude", json::value(newTargetAltitude));
goToDestination();
}
void Unit::setTargetSpeedType(wstring newTargetSpeedType) {
targetSpeedType = newTargetSpeedType;
addMeasure(L"targetSpeedType", json::value(newTargetSpeedType));
goToDestination();
}
void Unit::setTargetAltitudeType(wstring newTargetAltitudeType) {
targetAltitudeType = newTargetAltitudeType;
addMeasure(L"targetAltitudeType", json::value(newTargetAltitudeType));
goToDestination();
}
void Unit::goToDestination(wstring enrouteTask)
{
if (activeDestination != NULL)
{
Command* command = dynamic_cast<Command*>(new Move(ID, activeDestination, getTargetSpeed(), getTargetSpeedType(), getTargetAltitude(), getTargetAltitudeType(), enrouteTask));
scheduler->appendCommand(command);
setHasTask(true);
}
}
bool Unit::isDestinationReached(double threshold)
{
if (activeDestination != NULL)
{
double dist = 0;
Geodesic::WGS84().Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, dist);
if (dist < threshold)
{
log(unitName + L" destination reached");
return true;
}
else {
return false;
}
}
else
return true;
}
bool Unit::setActiveDestination()
{
if (activePath.size() > 0)
{
activeDestination = activePath.front();
log(unitName + L" active destination set to queue front");
return true;
}
else
{
activeDestination = Coords(0);
log(unitName + L" active destination set to NULL");
return false;
}
}
bool Unit::updateActivePath(bool looping)
{
if (activePath.size() > 0)
{
/* Push the next destination in the queue to the front */
if (looping)
pushActivePathBack(activePath.front());
popActivePathFront();
log(unitName + L" active path front popped");
return true;
}
else {
return false;
}
}

View File

@ -29,3 +29,8 @@ bool DllExport operator!= (const Offset& a, const Offset& b);
bool DllExport operator== (const Offset& a, const int& b);
bool DllExport operator!= (const Offset& a, const int& b);
double DllExport knotsToMs(const double knots);
double DllExport msToKnots(const double ms);
double DllExport ftToM(const double ft);
double DllExport mToFt(const double m);

View File

@ -63,3 +63,20 @@ bool operator== (const Offset& a, const Offset& b) { return a.x == b.x && a.y ==
bool operator!= (const Offset& a, const Offset& b) { return !(a == b); }
bool operator== (const Offset& a, const int& b) { return a.x == b && a.y == b && a.z == b; }
bool operator!= (const Offset& a, const int& b) { return !(a == b); }
double knotsToMs(const double knots) {
return knots / 1.94384;
}
double msToKnots(const double ms) {
return ms * 1.94384;
}
double ftToM(const double ft) {
return ft * 0.3048;
}
double mToFt(const double m) {
return m / 0.3048;
}