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

@@ -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;
}