diff --git a/bin/World/SimpleEstuary/buoy.ini b/bin/World/SimpleEstuary/buoy.ini
index dc148d846..35919cbe7 100644
--- a/bin/World/SimpleEstuary/buoy.ini
+++ b/bin/World/SimpleEstuary/buoy.ini
@@ -295,3 +295,5 @@ Lat(67)=50.0088
Type(68)="safe"
Long(68)=-9.979
Lat(68)=50.0396
+Racon(68)="M"
+RaconOnTime(68)=20
diff --git a/bin/World/SimpleEstuary/radarreflector.ini b/bin/World/SimpleEstuary/radarreflector.ini
deleted file mode 100644
index 26d0b4f2f..000000000
--- a/bin/World/SimpleEstuary/radarreflector.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-Number=1
-Buoy(1)=68
-Height(1)=2
-Racon(1)="M"
\ No newline at end of file
diff --git a/doc/WorldFileSpec.html b/doc/WorldFileSpec.html
index badd08e7b..86e3eb521 100755
--- a/doc/WorldFileSpec.html
+++ b/doc/WorldFileSpec.html
@@ -172,16 +172,23 @@
terrain.ini
buoy.ini
-Contains 1 general variable, and a set of 3 to 6 variables for each buoy defined. The global variable is Number, which is the number of
+
Contains 1 general variable, and a set of 3 to 8 variables for each buoy defined. The global variable is Number, which is the number of
buoys to be defined in the file. This can be zero, in which case no buoys are defined, and nothing further is required in this file. The three
required variables for each buoy are Type(#), Long(#) and Lat(#). Type(#) takes the buoy type, as a text string. This must correspond to an
available buoy model as defined in the Models\Buoy folder under the Bridge Command root directory.
Long(#) and Lat(#) take respectively the buoy's Longitude and Latitude in standard decimal degrees. Note that only the buoy model and its
location is specified here - if the buoy has a light attached, it must be specified in light.ini, as specified below.
-The first optional variable is RCS(#), which sets the buoy's radar cross section in metres squared. If not set, a default value will be used.
-The second optional variable is Grounded(#). If set to 1, this means that the 'buoy' will not respond to wave or tide, for example
-for a post. The third optional variable is HeightCorrection, which adjusts the vertical position of the buoy, and is set in metres, with a positive
-value moving the 'buoy' higher. Again this is useful for adjusting the height of a post.
+
+The optional variables are:
+
+
+ - RCS(#), which sets the buoy's radar cross section in metres squared. If not set, a default value will be used.
+ - Racon(#), if set to a string of 1 or more characters, this RACON code will be shown in morse code on the radar.
+ - RaconOnTime(#), used with the Racon setting above, sets how many seconds per minute the RACON is active for (default 20s per minute).
+ - Grounded(#), if set to 1, this means that the 'buoy' will not respond to wave or tide, for example for a post.
+ - HeightCorrection(#), which adjusts the vertical position of the buoy, and is set in metres, with a positive value moving the 'buoy' higher. Again this is useful for adjusting the height of a post.
+
+
Note that a folder Models/Buoy can be created in the world model folder to hold buoys required for this world model.
diff --git a/src/Buoy.cpp b/src/Buoy.cpp
index d79052f69..17ebf4514 100644
--- a/src/Buoy.cpp
+++ b/src/Buoy.cpp
@@ -23,10 +23,11 @@
#include
#include
+#include //For rand()
//using namespace irr;
-Buoy::Buoy(const std::string& name, const std::string& internalName, const std::string& worldName, const irr::core::vector3df& location, irr::f32 radarCrossSection, bool floating, irr::f32 heightCorrection, irr::scene::ISceneManager* smgr, irr::IrrlichtDevice* dev)
+Buoy::Buoy(const std::string& name, const std::string& internalName, const std::string& worldName, const irr::core::vector3df& location, irr::f32 radarCrossSection, std::string raconCode, irr::f32 raconOnTime, bool floating, irr::f32 heightCorrection, irr::scene::ISceneManager* smgr, irr::IrrlichtDevice* dev)
{
std::string basePath = "Models/Buoy/" + name + "/";
@@ -100,6 +101,11 @@ Buoy::Buoy(const std::string& name, const std::string& internalName, const std::
rcs = 0.005*std::pow(length,3); //Default RCS if not set, base radar cross section on length^3 (following RCS table Ship_RCS_table.pdf)
}
+ racon = raconCode;
+ this->raconOnTime = raconOnTime;
+
+ raconOffsetTime = 60.0f * (irr::f32) rand() / RAND_MAX;
+
this->floating = floating; //Does the buoy respond to the water
}
@@ -190,10 +196,12 @@ RadarData Buoy::getRadarData(irr::core::vector3df scannerPosition) const
radarData.minAngle=std::min(relAngle1,relAngle2);
radarData.maxAngle=std::max(relAngle1,relAngle2);
+ radarData.racon = racon; //Racon code if set
+ radarData.raconOnTime = raconOnTime;
+ radarData.raconOffsetTime = raconOffsetTime;
+
//Initial defaults: Will need changing with full implementation
radarData.hidden=false;
- radarData.racon=""; //Racon code if set
- radarData.raconOffsetTime=0.0;
radarData.SART=false;
radarData.contact = (void*)this;
diff --git a/src/Buoy.hpp b/src/Buoy.hpp
index 397dcbcb1..6d8e9f81b 100644
--- a/src/Buoy.hpp
+++ b/src/Buoy.hpp
@@ -27,7 +27,7 @@ struct RadarData;
class Buoy
{
public:
- Buoy(const std::string& name, const std::string& internalName, const std::string& worldName, const irr::core::vector3df& location, irr::f32 radarCrossSection, bool floating, irr::f32 heightCorrection, irr::scene::ISceneManager* smgr, irr::IrrlichtDevice* dev);
+ Buoy(const std::string& name, const std::string& internalName, const std::string& worldName, const irr::core::vector3df& location, irr::f32 radarCrossSection, std::string raconCode, irr::f32 raconOnTime, bool floating, irr::f32 heightCorrection, irr::scene::ISceneManager* smgr, irr::IrrlichtDevice* dev);
virtual ~Buoy();
irr::core::vector3df getPosition() const;
void setPosition(irr::core::vector3df position);
@@ -49,6 +49,9 @@ class Buoy
irr::f32 height; //For radar calculation
irr::f32 heightCorrection;
irr::f32 rcs;
+ std::string racon;
+ irr::f32 raconOnTime;
+ irr::f32 raconOffsetTime;
bool floating; //Does the buoy move with water (normally true, false for a post etc)
bool triangleSelectorEnabled; //Keep track of this so we don't keep re-setting the selector
};
diff --git a/src/Buoys.cpp b/src/Buoys.cpp
index 7e9b75e40..b6913e62a 100644
--- a/src/Buoys.cpp
+++ b/src/Buoys.cpp
@@ -63,6 +63,8 @@ void Buoys::load(const std::string& worldName, irr::scene::ISceneManager* smgr,
//get buoy RCS if set
irr::f32 rcs = IniFile::iniFileTof32(scenarioBuoyFilename,IniFile::enumerate1("RCS",currentBuoy));
+ std::string racon = IniFile::iniFileToString(scenarioBuoyFilename, IniFile::enumerate1("RACON", currentBuoy));
+ irr::f32 raconOnTime = IniFile::iniFileTof32(scenarioBuoyFilename,IniFile::enumerate1("RaconOnTime",currentBuoy), 20.0f);
irr::f32 heightCorrection = IniFile::iniFileTof32(scenarioBuoyFilename,IniFile::enumerate1("HeightCorrection",currentBuoy));
@@ -75,7 +77,7 @@ void Buoys::load(const std::string& worldName, irr::scene::ISceneManager* smgr,
//Create buoy and load into vector
std::string internalName = "Buoy_";
internalName.append(std::to_string(currentBuoy-1)); // -1 as we want index from 0
- buoys.push_back(Buoy (buoyName.c_str(),internalName,worldName,irr::core::vector3df(buoyX,0.0f,buoyZ),rcs,floating,heightCorrection,smgr,dev));
+ buoys.push_back(Buoy (buoyName.c_str(),internalName,worldName,irr::core::vector3df(buoyX,0.0f,buoyZ),rcs,racon,raconOnTime,floating,heightCorrection,smgr,dev));
//Find scene node
irr::scene::ISceneNode* buoyNode = buoys.back().getSceneNode();
diff --git a/src/OtherShip.cpp b/src/OtherShip.cpp
index 89e1a8323..d81a4a026 100644
--- a/src/OtherShip.cpp
+++ b/src/OtherShip.cpp
@@ -454,8 +454,6 @@ RadarData OtherShip::getRadarData(irr::core::vector3df scannerPosition) const
//Initial defaults: Fixme: Will need changing with full implementation
radarData.hidden=false;
- radarData.racon=""; //Racon code if set
- radarData.raconOffsetTime=0.0;
radarData.SART=false;
radarData.contact = (void*)this;
diff --git a/src/RadarCalculation.cpp b/src/RadarCalculation.cpp
index 45d37f271..80276e01a 100644
--- a/src/RadarCalculation.cpp
+++ b/src/RadarCalculation.cpp
@@ -705,7 +705,7 @@ void RadarCalculation::changeRadarColourChoice()
radarScreenStale = true;
}
-void RadarCalculation::update(irr::video::IImage * radarImage, irr::video::IImage * radarImageOverlaid, irr::core::vector3d 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::core::vector2di mouseRelPosition, bool isMouseDown)
+void RadarCalculation::update(irr::video::IImage * radarImage, irr::video::IImage * radarImageOverlaid, irr::core::vector3d 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, irr::core::vector2di mouseRelPosition, bool isMouseDown)
{
#ifdef WITH_PROFILING
@@ -753,7 +753,7 @@ void RadarCalculation::update(irr::video::IImage * radarImage, irr::video::IImag
CursorRangeNm = pow(pow(cursorRangeXNm,2)+pow(cursorRangeYNm,2),0.5);
} { IPROF("Scan");
- scan(offsetPosition, terrain, ownShip, buoys, otherShips, weather, rain, tideHeight, deltaTime, absoluteTime); // scan into scanArray[row (angle)][column (step)], and with filtering and amplification into scanArrayAmplified[][]
+ scan(offsetPosition, terrain, ownShip, buoys, otherShips, weather, rain, tideHeight, deltaTime, absoluteTime, scenarioTime); // scan into scanArray[row (angle)][column (step)], and with filtering and amplification into scanArrayAmplified[][]
} { IPROF("Update ARPA");
updateARPA(offsetPosition, ownShip, absoluteTime); //From data in arpaContacts, updated in scan()
} { IPROF("Render");
@@ -763,7 +763,7 @@ void RadarCalculation::update(irr::video::IImage * radarImage, irr::video::IImag
}
-void RadarCalculation::scan(irr::core::vector3d 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)
+void RadarCalculation::scan(irr::core::vector3d 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)
{
//IPROF_FUNC;
@@ -779,6 +779,7 @@ void RadarCalculation::scan(irr::core::vector3d 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)
//Convert range to cell size
irr::f32 cellLength = M_IN_NM*radarRangeNm.at(radarRangeIndex)/rangeResolution; ; //Assume that radarRangeIndex is in bounds
@@ -805,12 +806,16 @@ void RadarCalculation::scan(irr::core::vector3d offsetPosition, const T
currentScanAngle = ((irr::f32) currentScanLine / (irr::f32) angularResolution) * 360.0f;
irr::f32 scanSlope = -0.5; //Slope at start of scan (in metres/metre) - Make slightly negative so vessel contacts close in get detected
+
+ // clear this line (before the main scan loop, so we can add things like racon which will appear beyond contact
+ for (irr::u32 currentStep = 1; currentStep < rangeResolution; currentStep++) { //Note that currentStep starts as 1, not 0. This is used in anti-rain clutter filter, which checks element at currentStep-1
+ scanArray[currentScanLine][currentStep] = 0.0;
+ }
+
+
for (irr::u32 currentStep = 1; currentStep offsetPosition, const T
irr::f32 radarEchoStrength = radarFactorVessel * std::pow(M_IN_NM/localRange,4) * radarData.at(thisContact).rcs;
scanArray[currentScanLine][currentStep] += radarEchoStrength;
+ if (radarData.at(thisContact).racon != "") {
+ if (std::fmod(scenarioTime + radarData.at(thisContact).raconOffsetTime, 60.0f) <= radarData.at(thisContact).raconOnTime) {
+ irr::f32 raconEchoStrength = radarFactorRACON * std::pow(M_IN_NM / localRange, 2); //RACON / SART goes with inverse square law as we are receiving the direct signal, not echo
+ addRaconString(raconEchoStrength, cellLength, localRange, radarData.at(thisContact).racon);
+ }
+ }
+
//Start ARPA section
// ARPA mode - 0: Off/Manual, 1: MARPA, 2: ARPA
if (arpaMode > 0 && radarEchoStrength*2 > localNoise) {
@@ -1135,6 +1147,202 @@ void RadarCalculation::scan(irr::core::vector3d offsetPosition, const T
}
+void RadarCalculation::addRaconString(irr::f32 raconEchoStrength, irr::f32 cellLength, irr::f32 contactRange, std::string raconCode)
+{
+ const irr::f32 racon_pulse_length = 750; // 'Short' racon pulse length in metres
+
+ irr::f32 raconEchoStart = contactRange + racon_pulse_length/4; // Start 1/4th of a pulse beyond the target
+
+ int stringLength = raconCode.length();
+ for (int i = 0; i < stringLength; i++) {
+ switch (raconCode[i]) {
+ case 'A':
+ case 'a':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ break;
+ case 'B':
+ case 'b':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'C':
+ case 'c':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'D':
+ case 'd':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'E':
+ case 'e':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'F':
+ case 'f':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'G':
+ case 'g':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'H':
+ case 'h':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'I':
+ case 'i':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'J':
+ case 'j':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ break;
+ case 'K':
+ case 'k':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ break;
+ case 'L':
+ case 'l':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'M':
+ case 'm':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ break;
+ case 'N':
+ case 'n':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'O':
+ case 'o':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ break;
+ case 'P':
+ case 'p':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'Q':
+ case 'q':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ break;
+ case 'R':
+ case 'r':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'S':
+ case 's':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ case 'T':
+ case 't':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ break;
+ case 'U':
+ case 'u':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ break;
+ case 'V':
+ case 'v':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ break;
+ case 'W':
+ case 'w':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ break;
+ case 'X':
+ case 'x':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ break;
+ case 'Y':
+ case 'y':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ break;
+ case 'Z':
+ case 'z':
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 3, racon_pulse_length * 1, raconEchoStart); // Long
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ addRaconReturn(raconEchoStrength, cellLength, racon_pulse_length * 1, racon_pulse_length * 1, raconEchoStart); // Short
+ break;
+ default:
+ break;
+ }
+
+ // Add space after each character
+ raconEchoStart = raconEchoStart + 3 * racon_pulse_length;
+
+ }
+
+}
+
+void RadarCalculation::addRaconReturn(irr::f32 raconEchoStrength, irr::f32 cellLength, irr::f32 raconEchoLength, irr::f32 raconSpaceLength, irr::f32& raconEchoStart)
+{
+ irr::f32 raconEchoEnd = raconEchoStart + raconEchoLength;
+
+ // As with other radar scans, start sweep at 1 (0 reserved so we can do rain clutter 'graient' calculation)
+ for (irr::u32 raconStep = 1; raconStep < rangeResolution; raconStep++) {
+
+ if ((raconStep * cellLength >= raconEchoStart) && (raconStep * cellLength <= raconEchoEnd)) {
+ scanArray[currentScanLine][raconStep] += raconEchoStrength;
+ }
+ }
+
+ // Update raconEchoStart for the next character
+ raconEchoStart = raconEchoEnd + raconSpaceLength;
+}
+
void RadarCalculation::addManualPoint(bool newContact, irr::core::vector3d offsetPosition, const OwnShip& ownShip, uint64_t absoluteTime)
{
// Assumes that CursorRangeNm and CursorBrg reflect the current cursor point
diff --git a/src/RadarCalculation.hpp b/src/RadarCalculation.hpp
index c669dacde..41b48cea7 100644
--- a/src/RadarCalculation.hpp
+++ b/src/RadarCalculation.hpp
@@ -171,7 +171,7 @@ class RadarCalculation
irr::video::SColor getRadarSurroundColour() const;
irr::f32 getBrilliance() const;
void setBrilliance(irr::f32 brilliance);
- void update(irr::video::IImage * radarImage, irr::video::IImage * radarImageOverlaid, irr::core::vector3d 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::core::vector2di mouseRelPosition, bool isMouseDown);
+ void update(irr::video::IImage * radarImage, irr::video::IImage * radarImageOverlaid, irr::core::vector3d 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, irr::core::vector2di mouseRelPosition, bool isMouseDown);
private:
irr::IrrlichtDevice* device;
@@ -229,7 +229,9 @@ class RadarCalculation
irr::f32 brilliance;
std::vector radarRangeNm;
- void scan(irr::core::vector3d 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);
+ void scan(irr::core::vector3d 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);
void updateARPA(irr::core::vector3d offsetPosition, const OwnShip& ownShip, uint64_t absoluteTime);
void updateArpaEstimate(ARPAContact& thisArpaContact, int contactID, const OwnShip& ownShip, irr::core::vector3d 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);
diff --git a/src/RadarData.hpp b/src/RadarData.hpp
index ff4c0e02d..18b93d722 100644
--- a/src/RadarData.hpp
+++ b/src/RadarData.hpp
@@ -41,7 +41,8 @@ struct RadarData {
bool hidden;
std::string racon; //Racon code if set
- irr::f32 raconOffsetTime;
+ irr::f32 raconOnTime; //Duration on per minute, in seconds
+ irr::f32 raconOffsetTime; // Offset in seconds
bool SART; //SART enabled?
//irr::f32 radarHorizon; //Only used for tracking contacts outside current radar visibility range
@@ -65,6 +66,7 @@ struct RadarData {
hidden(false),
racon(""),
raconOffsetTime(0),
+ raconOnTime(0),
SART(false)
{}
diff --git a/src/SimulationModel.cpp b/src/SimulationModel.cpp
index 1d144b0ee..800b28cc2 100644
--- a/src/SimulationModel.cpp
+++ b/src/SimulationModel.cpp
@@ -1980,7 +1980,7 @@ SimulationModel::~SimulationModel()
radarImageChosen = radarImage;
radarImageOverlaidChosen = radarImageOverlaid;
}
- radarCalculation.update(radarImageChosen,radarImageOverlaidChosen,offsetPosition,terrain,ownShip,buoys,otherShips,weather,rainIntensity,tideHeight,deltaTime,absoluteTime,cursorPositionRadar,isMouseDown);
+ radarCalculation.update(radarImageChosen,radarImageOverlaidChosen,offsetPosition,terrain,ownShip,buoys,otherShips,weather,rainIntensity,tideHeight,deltaTime,absoluteTime,scenarioTime,cursorPositionRadar,isMouseDown);
}{ IPROF("Update radar screen");
radarScreen.update(radarImageOverlaidChosen);
}{ IPROF("Update radar camera");