Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Buoy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ RadarData Buoy::getRadarData(irr::core::vector3df scannerPosition) const
radarData.hidden=false;
radarData.SART=false;

radarData.contactType = buoyContact;
radarData.contact = (void*)this;

return radarData;
Expand Down
25 changes: 23 additions & 2 deletions src/NetworkPrimary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,20 @@ void NetworkPrimary::receiveNetwork()
model->setSternThruster(overrideData);
}
}
} else if (thisCommand.substr(0, 2).compare("SR") == 0) {
//'SR', Set SART status
std::vector<std::string> parts = Utilities::split(thisCommand, ','); //Split into parts, 1st is command itself, 2nd and greater is the data
if (parts.size() == 3) {
int shipNo = Utilities::lexical_cast<int>(parts.at(1)) - 1; //Numbering on network starts at 1, internal numbering at 0
bool sartStatus;
if (parts.at(2) == "1") {
sartStatus = true;
}
else {
sartStatus = false;
}
model->setOtherShipSARTOn(shipNo, sartStatus);
}
}


Expand Down Expand Up @@ -526,7 +540,7 @@ std::string NetworkPrimary::generateSendString()
stringToSend.append(Utilities::lexical_cast<std::string>(model->getLines()->getNumberOfLines()));
stringToSend.append("#");

//3 Each 'Other' (Pos X (abs), Pos Z, angle, rate of turn, SART, MMSI |) #
//3 Each 'Other' (Pos X (abs), Pos Z, angle, speed, rate of turn, SART, MMSI |) #
for(int number = 0; number < (int)model->getNumberOfOtherShips(); number++ ) {
stringToSend.append(Utilities::lexical_cast<std::string>(model->getOtherShipPosX(number)));
stringToSend.append(",");
Expand All @@ -538,7 +552,14 @@ std::string NetworkPrimary::generateSendString()
stringToSend.append(",");
stringToSend.append("0"); // Rate of turn: This is not currently used in normal mode
stringToSend.append(",");
stringToSend.append("0"); //Fixme: Sart enabled

if (model->getOtherShipSARTOn(number)) {
stringToSend.append("1"); // Sart enabled
}
else {
stringToSend.append("0"); // Sart disabled
}

stringToSend.append(",");
stringToSend.append(Utilities::lexical_cast<std::string>(model->getOtherShipMMSI(number)));
stringToSend.append(",");
Expand Down
12 changes: 10 additions & 2 deletions src/NetworkSecondary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ void NetworkSecondary::getScenarioFromNetwork(std::string& dataString) //Not use
if ((receivedString.substr(0,4) == "SCN1") ||
(receivedString.substr(0,4) == "SCN2") ||
(receivedString.substr(0,4) == "SCN3") ||
(receivedString.substr(0,4) == "SCN4")) { //Check if it starts with SCN1-SCN4
(receivedString.substr(0,4) == "SCN4") ||
(receivedString.substr(0,4) == "SCN5")) { //Check if it starts with SCN1-SCN5
//If valid, use this string
dataString = receivedString;
}
Expand Down Expand Up @@ -244,8 +245,15 @@ void NetworkSecondary::receiveMessage()
irr::f32 receivedPosX = Utilities::lexical_cast<irr::f32>(thisShipData.at(0));
irr::f32 receivedPosZ = Utilities::lexical_cast<irr::f32>(thisShipData.at(1));
model->setOtherShipPos(i,receivedPosX,receivedPosZ);

// SART status
if (thisShipData.at(5) == "1") {
model->setOtherShipSARTOn(i,true);
} else {
model->setOtherShipSARTOn(i,false);
}
//Todo: Think about using timeError to extrapolate position to get more accurately.
//Todo: use SART etc

}
}
}
Expand Down
25 changes: 22 additions & 3 deletions src/OtherShip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

//using namespace irr;

OtherShip::OtherShip (const std::string& name, const std::string& internalName, const irr::u32& mmsi, const irr::core::vector3df& location, std::vector<Leg> legsLoaded, bool drifting, SimulationModel* model, irr::scene::ISceneManager* smgr, irr::IrrlichtDevice* dev)
OtherShip::OtherShip (const std::string& name, const std::string& internalName, const irr::u32& mmsi, const irr::core::vector3df& location, std::vector<Leg> legsLoaded, bool drifting, bool SART, SimulationModel* model, irr::scene::ISceneManager* smgr, irr::IrrlichtDevice* dev)
{

//Initialise speed and heading, normally updated from leg information
Expand All @@ -42,6 +42,9 @@ OtherShip::OtherShip (const std::string& name, const std::string& internalName,
this->name = name;
this->mmsi = mmsi;
this->drifting = drifting;
this->SART = SART;

SARTtimeStamp = 0;

std::string basePath = "Models/Othership/" + name + "/";
std::string userFolder = Utilities::getUserDir();
Expand Down Expand Up @@ -420,6 +423,21 @@ void OtherShip::setRateOfTurn(irr::f32 rateOfTurn) //Sets the rate of turn (only
this->rateOfTurn = rateOfTurn;
}

void OtherShip::setSARTtimeStamp(uint64_t timeStamp)
{
SARTtimeStamp = timeStamp;
}

bool OtherShip::getSARTOn() const
{
return SART;
}

void OtherShip::setSARTOn(bool sartState)
{
SART = sartState;
}

RadarData OtherShip::getRadarData(irr::core::vector3df scannerPosition) const
//Get data for OtherShip (number) relative to scannerPosition
//Similar code in Buoy.cpp
Expand Down Expand Up @@ -452,10 +470,11 @@ RadarData OtherShip::getRadarData(irr::core::vector3df scannerPosition) const
radarData.minAngle=std::min(relAngle1,relAngle2);
radarData.maxAngle=std::max(relAngle1,relAngle2);

//Initial defaults: Fixme: Will need changing with full implementation
radarData.hidden=false;
radarData.SART=false;
radarData.SART=SART;
radarData.SARTtimeStamp = SARTtimeStamp;

radarData.contactType = otherShipContact;
radarData.contact = (void*)this;

return radarData;
Expand Down
8 changes: 7 additions & 1 deletion src/OtherShip.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <cmath>
#include <vector>
#include <cstdint> // for uint64_t

// Forward declarations
class SimulationModel;
Expand All @@ -34,7 +35,7 @@ struct RadarData;
class OtherShip : public Ship
{
public:
OtherShip (const std::string& name, const std::string& internalName, const irr::u32& mmsi, const irr::core::vector3df& location, std::vector<Leg> legsLoaded, bool drifting, SimulationModel* model, irr::scene::ISceneManager* smgr, irr::IrrlichtDevice* dev);
OtherShip (const std::string& name, const std::string& internalName, const irr::u32& mmsi, const irr::core::vector3df& location, std::vector<Leg> legsLoaded, bool drifting, bool SART, SimulationModel* model, irr::scene::ISceneManager* smgr, irr::IrrlichtDevice* dev);
~OtherShip();

irr::f32 getHeight() const;
Expand All @@ -49,6 +50,9 @@ class OtherShip : public Ship
void update(irr::f32 deltaTime, irr::f32 scenarioTime, irr::f32 tideHeight, irr::u32 lightLevel);
void enableTriangleSelector(bool selectorEnabled);
void setRateOfTurn(irr::f32 rateOfTurn); // This could be moved to Ship.hpp
void setSARTtimeStamp(uint64_t timeStamp);
bool getSARTOn() const;
void setSARTOn(bool sartState);

protected:
private:
Expand All @@ -65,6 +69,8 @@ class OtherShip : public Ship
irr::scene::ITriangleSelector* selector;
bool triangleSelectorEnabled;
bool drifting;
bool SART; // If SART is enabled
uint64_t SARTtimeStamp;
};

#endif
22 changes: 21 additions & 1 deletion src/OtherShips.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ void OtherShips::load(std::vector<OtherShipData> otherShipsData, irr::f32 scenar
//Set if it's drifting with wind/stream
bool drifting = otherShipsData.at(i).drifting;

// Set if SART is on
bool SART = otherShipsData.at(i).SART;

//Load leg information
std::vector<Leg> legs;
irr::f32 legStartTime = scenarioStartTime;
Expand Down Expand Up @@ -92,7 +95,7 @@ void OtherShips::load(std::vector<OtherShipData> otherShipsData, irr::f32 scenar
//Create otherShip and load into vector
std::string internalName = "OtherShip_";
internalName.append(std::to_string(i));
otherShips.push_back(new OtherShip (otherShipName,internalName,mmsi,irr::core::vector3df(shipX,0.0f,shipZ),legs,drifting,model,smgr, dev));
otherShips.push_back(new OtherShip (otherShipName,internalName,mmsi,irr::core::vector3df(shipX,0.0f,shipZ),legs,drifting,SART,model,smgr, dev));
}

}
Expand Down Expand Up @@ -214,6 +217,23 @@ irr::f32 OtherShips::getEstimatedDisplacement(int number) const
}
}

bool OtherShips::getSARTOn(int number) const
{
if (number < (int)otherShips.size() && number >= 0) {
return otherShips.at(number)->getSARTOn();
}
else {
return false;
}
}

void OtherShips::setSARTOn(int number, bool sartState)
{
if (number < (int)otherShips.size() && number >= 0) {
otherShips.at(number)->setSARTOn(sartState);
}
}

void OtherShips::setSpeed(int number, irr::f32 speed)
{
if (number < (int)otherShips.size() && number >= 0) {
Expand Down
2 changes: 2 additions & 0 deletions src/OtherShips.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class OtherShips
irr::f32 getSpeed(int number) const; //Speed in m/s
irr::u32 getMMSI(int number) const;
irr::f32 getEstimatedDisplacement(int number) const;
bool getSARTOn(int number) const;
void setSARTOn(int number, bool sartState);
void setSpeed(int number, irr::f32 speed); //Speed in m/s
void setMMSI(int number, irr::u32 mmsi);
void setPos(int number, irr::f32 positionX, irr::f32 positionZ);
Expand Down
97 changes: 96 additions & 1 deletion src/RadarCalculation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "OwnShip.hpp"
#include "Buoys.hpp"
#include "OtherShips.hpp"
#include "OtherShip.hpp"
#include "RadarData.hpp"
#include "Angles.hpp"
#include "Constants.hpp"
Expand Down Expand Up @@ -784,7 +785,8 @@ void RadarCalculation::scan(irr::core::vector3d<int64_t> offsetPosition, const T
//Some tuning constants
irr::f32 radarFactorLand=2.0;
irr::f32 radarFactorVessel=0.0001;
irr::f32 radarFactorRACON= radarFactorVessel * pow(1852.0/200.0, 2); // for Equivalent RCS of 1m2 at 200m(Fig 8.11, Target detection by marine radar)
irr::f32 radarFactorRACON = radarFactorVessel * pow(1852.0/200.0, 2); // for Equivalent RCS of 1m2 at 200m(Fig 8.11, Target detection by marine radar)
irr::f32 radarFactorSART = radarFactorRACON * 0.1; // Like RACON, but lower strength;

//Convert range to cell size
irr::f32 cellLength = M_IN_NM*radarRangeNm.at(radarRangeIndex)/rangeResolution; ; //Assume that radarRangeIndex is in bounds
Expand All @@ -805,6 +807,11 @@ void RadarCalculation::scan(irr::core::vector3d<int64_t> offsetPosition, const T
irr::u32 scansPerLoop = RADAR_RPM * RPMtoDEGPERSECOND * deltaTime / (irr::f32) scanAngleStep + (irr::f32) rand() / RAND_MAX ; //Add random value (0-1, mean 0.5), so with rounding, we get the correct radar speed, even though we can only do an integer number of scans

if (scansPerLoop > 30) {scansPerLoop = 30;} //Limit to reasonable bounds

// By default show SART returns if scanned within 3s, but may need to be longer with high time acceleration)
// 30 here is max number of scans per loop
uint64_t maxTimeForSARTDetected = std::max(3, int(2 * deltaTime * 360 / (30 * scanAngleStep)));

for(irr::u32 i = 0; i<scansPerLoop;i++) { //Start of repeatable scan section

// the actual angle we want to work with has to be determined here
Expand Down Expand Up @@ -852,6 +859,24 @@ void RadarCalculation::scan(irr::core::vector3d<int64_t> offsetPosition, const T

//Scan other contacts here
for(unsigned int thisContact = 0; thisContact<radarData.size(); thisContact++) {

// Extra check for SART contacts
if (radarData.at(thisContact).SART &&
(radarData.at(thisContact).SARTtimeStamp > 0) &&
(absoluteTime - radarData.at(thisContact).SARTtimeStamp <= maxTimeForSARTDetected))
{
// Relative angle in range -180 to 180 degrees
irr::f32 relativeSARTAngle = currentScanAngle - radarData.at(thisContact).angle;
if (relativeSARTAngle > 180) {
relativeSARTAngle -= 360;
}
if (relativeSARTAngle < -180) {
relativeSARTAngle += 360;
}

scanArray[currentScanLine][currentStep] += getSARTStrength(radarFactorSART, radarData.at(thisContact).range, localRange, relativeSARTAngle);
}

irr::f32 contactHeightAboveLine = (radarData.at(thisContact).height - radarScannerHeight - dropWithCurvature) - scanSlope*localRange;
if (contactHeightAboveLine > 0) {
//Contact would be visible if in this cell. Check if it is
Expand Down Expand Up @@ -910,6 +935,17 @@ void RadarCalculation::scan(irr::core::vector3d<int64_t> offsetPosition, const T
}
}

// If SART on, and contact is detectable in noise
if (radarData.at(thisContact).SART) {
if (radarEchoStrength*2 > localNoise) {
// Check contact type before casting!
if (radarData.at(thisContact).contactType == otherShipContact) {
OtherShip* shipContact = static_cast<OtherShip*>(radarData.at(thisContact).contact);
shipContact->setSARTtimeStamp(absoluteTime);
}
}
}

//Start ARPA section
// ARPA mode - 0: Off/Manual, 1: MARPA, 2: ARPA
if (arpaMode > 0 && radarEchoStrength*2 > localNoise) {
Expand Down Expand Up @@ -1348,6 +1384,65 @@ void RadarCalculation::addRaconReturn(irr::f32 raconEchoStrength, irr::f32 cellL
raconEchoStart = raconEchoEnd + raconSpaceLength;
}

irr::f32 RadarCalculation::getSARTStrength(irr::f32 radarFactorSART, irr::f32 sartRange, irr::f32 localRange, irr::f32 relativeSARTAngle) const
{
irr::f32 relativeSARTRange = localRange - sartRange;
irr::f32 sartEchoStrength = radarFactorSART * std::pow(M_IN_NM / sartRange, 2); //RACON / SART goes with inverse square law as we are receiving the direct signal, not echo

// radar sidelobes, following 'Target detection by marine radar', section 2.8.1
irr::f32 widthFactor = 3.0;
irr::f32 waveLength = 0.1;
irr::f32 relativeAngleRadians = relativeSARTAngle * irr::core::DEGTORAD;

irr::f32 intermediateCalculation = widthFactor * relativeAngleRadians / waveLength;
irr::f32 angleFactor;
if (intermediateCalculation != 0) {
angleFactor = pow(sin(intermediateCalculation) / intermediateCalculation, 2);
} else {
angleFactor = 1;
}

irr::f32 returnStrength = 0;

irr::f32 mainReturnStart = 0.32 * M_IN_NM; // Dependent on receiving radar tuning within SART sweep
irr::f32 additionalReturnStart = 100; // Dependent on response time and fast response speed. IMO SN/Circ. 197 says no more than 150m
irr::f32 returnSpacing = 0.64 * M_IN_NM; // Set by SART sweep time
irr::f32 mainReturnLength = 0.1 * M_IN_NM; // Factor to account for how long SART pulse is within bandwidth;
irr::f32 additionalReturnLength = 0.05 * M_IN_NM; // Factor to account for how long SART pulse is within bandwidth;
irr::f32 additionalReturnFactor = 0.01; // Scaling factor so additional returns only show when close
int numberOfReturns = 12;
irr::f32 mainReturnEnd = mainReturnStart + returnSpacing * (numberOfReturns - 1);
irr::f32 additionalReturnEnd = additionalReturnStart + returnSpacing * (numberOfReturns - 1);

// Main returns:
if ((relativeSARTRange >= mainReturnStart - 0.5 * mainReturnLength) && (relativeSARTRange <= mainReturnEnd + 0.5 * mainReturnLength)) {
for (int i = 0; i < numberOfReturns; i++) {
irr::f32 thisReturnDist = mainReturnStart + i * returnSpacing;
irr::f32 thisReturnDistMin = thisReturnDist - mainReturnLength / 2;
irr::f32 thisReturnDistMax = thisReturnDistMin + mainReturnLength;

if ((relativeSARTRange >= thisReturnDistMin) && (relativeSARTRange <= thisReturnDistMax)) {
returnStrength += angleFactor * sartEchoStrength;
}
}
}

// Additional returns:
if ((relativeSARTRange >= additionalReturnStart - 0.5 * additionalReturnLength) && (relativeSARTRange <= additionalReturnEnd + 0.5 * additionalReturnLength)) {
for (int i = 0; i < numberOfReturns; i++) {
irr::f32 thisReturnDist = additionalReturnStart + i * returnSpacing;
irr::f32 thisReturnDistMin = thisReturnDist - additionalReturnLength / 2;
irr::f32 thisReturnDistMax = thisReturnDistMin + additionalReturnLength;

if ((relativeSARTRange >= thisReturnDistMin) && (relativeSARTRange <= thisReturnDistMax)) {
returnStrength += angleFactor * sartEchoStrength * additionalReturnFactor;
}
}
}

return returnStrength;
}

void RadarCalculation::addManualPoint(bool newContact, irr::core::vector3d<int64_t> offsetPosition, const OwnShip& ownShip, uint64_t absoluteTime)
{
// Assumes that CursorRangeNm and CursorBrg reflect the current cursor point
Expand Down
1 change: 1 addition & 0 deletions src/RadarCalculation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ class RadarCalculation
void scan(irr::core::vector3d<int64_t> offsetPosition, const Terrain& terrain, const OwnShip& ownShip, const Buoys& buoys, const OtherShips& otherShips, irr::f32 weather, irr::f32 rain, irr::f32 tideHeight, irr::f32 deltaTime, uint64_t absoluteTime, irr::f32 scenarioTime);
void addRaconString(irr::f32 raconEchoStrength, irr::f32 cellLength, irr::f32 contactRange, std::string raconCode);
void addRaconReturn(irr::f32 raconEchoStrength, irr::f32 cellLength, irr::f32 raconEchoLength, irr::f32 raconSpaceLength, irr::f32& raconEchoStart);
irr::f32 getSARTStrength(irr::f32 radarFactorSART, irr::f32 sartRange, irr::f32 localRange, irr::f32 relativeSARTAngle) const;
void updateARPA(irr::core::vector3d<int64_t> offsetPosition, const OwnShip& ownShip, uint64_t absoluteTime);
void updateArpaEstimate(ARPAContact& thisArpaContact, int contactID, const OwnShip& ownShip, irr::core::vector3d<int64_t> absolutePosition, uint64_t absoluteTime);
irr::f32 radarNoise(irr::f32 radarNoiseLevel, irr::f32 radarSeaClutter, irr::f32 radarRainClutter, irr::f32 weather, irr::f32 radarRange,irr::f32 radarBrgDeg, irr::f32 windDirectionDeg, irr::f32 radarInclinationAngle, irr::f32 rainIntensity);
Expand Down
Loading
Loading