Thread: [Gcblue-commits] gcb_wx/src/sim tcSonarEnvironment.cpp, NONE, 1.1 tcSonarRay.cpp, NONE, 1.1 Game.cp
Status: Alpha
Brought to you by:
ddcforge
Update of /cvsroot/gcblue/gcb_wx/src/sim In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv25403/src/sim Modified Files: Game.cpp tcObjectControl.cpp tcSensorState.cpp tcSimState.cpp tcSonar.cpp Added Files: tcSonarEnvironment.cpp tcSonarRay.cpp Log Message: Index: tcObjectControl.cpp =================================================================== RCS file: /cvsroot/gcblue/gcb_wx/src/sim/tcObjectControl.cpp,v retrieving revision 1.56 retrieving revision 1.57 diff -C2 -d -r1.56 -r1.57 *** tcObjectControl.cpp 28 Nov 2006 01:57:37 -0000 1.56 --- tcObjectControl.cpp 20 Dec 2006 00:45:46 -0000 1.57 *************** *** 1949,1952 **** --- 1949,1955 ---- altitudeControl->SetActive(true); break; + case MTYPE_MISSILE: + altitudeControl->SetActive(false); + break; default: altitudeControl->SetActive(true); Index: tcSimState.cpp =================================================================== RCS file: /cvsroot/gcblue/gcb_wx/src/sim/tcSimState.cpp,v retrieving revision 1.103 retrieving revision 1.104 diff -C2 -d -r1.103 -r1.104 *** tcSimState.cpp 30 Nov 2006 04:11:13 -0000 1.103 --- tcSimState.cpp 20 Dec 2006 00:45:46 -0000 1.104 *************** *** 59,62 **** --- 59,63 ---- #include "tcSubObject.h" #include "tcSubDBObject.h" + #include "tcSonarEnvironment.h" #include "tcLauncher.h" *************** *** 2757,2760 **** --- 2758,2763 ---- objectNameMap.clear(); captiveObjectMap.clear(); + + tcSonarEnvironment::Get()->Clear(); } *************** *** 2828,2832 **** tcSimState::~tcSimState() { ! Clear(); if (positionRegistry) delete positionRegistry; --- 2831,2835 ---- tcSimState::~tcSimState() { ! maPlatformState.RemoveAll(); if (positionRegistry) delete positionRegistry; Index: tcSensorState.cpp =================================================================== RCS file: /cvsroot/gcblue/gcb_wx/src/sim/tcSensorState.cpp,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** tcSensorState.cpp 6 Dec 2006 01:20:43 -0000 1.20 --- tcSensorState.cpp 20 Dec 2006 00:45:46 -0000 1.21 *************** *** 38,42 **** tcDatabase* tcSensorState::database = NULL; tcSimState* tcSensorState::simState = NULL; ! /** --- 38,42 ---- tcDatabase* tcSensorState::database = NULL; tcSimState* tcSensorState::simState = NULL; ! long tcSensorState::nextSensorId = 1000; /** *************** *** 357,360 **** --- 357,362 ---- tcSensorState& tcSensorState::operator=(tcSensorState& ss) { + wxASSERT(false); // is this method used? + mbActive = ss.mbActive; isHidden = ss.isHidden; *************** *** 380,383 **** --- 382,387 ---- tcSensorState* tcSensorState::Clone() { + wxASSERT(false); // is this method used? + // TODO: should use a copy constructor (if this method is used) tcSensorState *pNew = new tcSensorState(); *************** *** 387,391 **** /** ! * */ tcSensorState::tcSensorState() : --- 391,396 ---- /** ! * Used to initialize tcSimState::mcDefaultRadar for detect before ! * create seeker test. */ tcSensorState::tcSensorState() : *************** *** 401,405 **** sensorPlatform(0), fireControlId(-1), ! fireControlIdx(0) { mcTrack.mnID = NULL_INDEX; --- 406,411 ---- sensorPlatform(0), fireControlId(-1), ! fireControlIdx(0), ! sensorId(nextSensorId++) { mcTrack.mnID = NULL_INDEX; *************** *** 424,428 **** fireControlIdx(0), parent(0), ! sensorPlatform(0) { wxASSERT(dbObj); --- 430,435 ---- fireControlIdx(0), parent(0), ! sensorPlatform(0), ! sensorId(nextSensorId++) { wxASSERT(dbObj); Index: tcSonar.cpp =================================================================== RCS file: /cvsroot/gcblue/gcb_wx/src/sim/tcSonar.cpp,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** tcSonar.cpp 27 Nov 2006 00:46:40 -0000 1.19 --- tcSonar.cpp 20 Dec 2006 00:45:46 -0000 1.20 *************** *** 33,37 **** --- 33,39 ---- #include "tcSimState.h" #include "tcGameObjIterator.h" + #include "tcSonarEnvironment.h" #include "common/tcObjStream.h" + #include "simmath.h" #ifdef _DEBUG *************** *** 141,151 **** range_km = C_RADTOKM * nsNav::GCDistanceApprox_rad(par_kin->mfLat_rad, par_kin->mfLon_rad, tgt_kin->mfLat_rad, tgt_kin->mfLon_rad); - float TL = 60.0f + 20.0f * log10f(range_km) + - mpDBObj->alpha * range_km; // one-way transmission loss referenced to 1 m ! ! float sonarAlt_m = par_kin->mfAlt_m; ! float targetAlt_m = tgt_kin->mfAlt_m; // if parent or target airborne, assume helo dipping sonar and subtract scope_m from alt --- 143,152 ---- range_km = C_RADTOKM * nsNav::GCDistanceApprox_rad(par_kin->mfLat_rad, par_kin->mfLon_rad, tgt_kin->mfLat_rad, tgt_kin->mfLon_rad); + float range_m = 1000.0f * range_km; ! ! float sonarAlt_m = (par_kin->mfAlt_m == 0) ? -5.0f : par_kin->mfAlt_m; ! float targetAlt_m = (tgt_kin->mfAlt_m == 0) ? -5.0f : tgt_kin->mfAlt_m; // if parent or target airborne, assume helo dipping sonar and subtract scope_m from alt *************** *** 169,181 **** else { ! wxASSERT(false); // non-helo dipping sonar? ! return false; } } ! // crude thermocline ! bool parentAbove = sonarAlt_m >= -80.0; ! bool targetAbove = targetAlt_m >= -80.0; ! if (parentAbove != targetAbove) TL += 10.0f; // add 10 dB loss float excessSNR; --- 170,186 ---- else { ! return false; // e.g. sonobuoy not in the water yet } } ! long key = sensorId; ! float TL = tcSonarEnvironment::Get()->GetTL(key, parent->mfStatusTime, -sonarAlt_m, range_m, -targetAlt_m); ! TL += mpDBObj->alpha * range_km; // add freq based atten here (not in tcSonarEnvironment yet) ! ! ! // ambient noise (flawed as is because assumes target signal is always centered in sonar passband) ! float NL_background_dB = tcSonarEnvironment::Get()->GetAmbientNL(mpDBObj->averageFreq_Hz); ! NL = Add_dB(NL_background_dB, NL); ! float excessSNR; --- NEW FILE: tcSonarRay.cpp --- /** ** @file tcSonarRay.cpp */ /* Copyright (C) 2006 Dewitt Colclough (de...@gc...) ** All rights reserved. ** This file is part of the Global Conflict Blue (GCB) program. ** GCB is free software; you can redistribute it and/or modify ** it under the terms of version 2 of the GNU General Public License as ** published by the Free Software Foundation. ** GCB is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** You should have received a copy of the GNU General Public License ** along with GCB; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA **/ #include "stdwx.h" #include "tcSonarRay.h" #include <osg/Timer> #ifdef _DEBUG #define new DEBUG_NEW #endif /** * @return depth of ray at range_m or -999.9f if beyond last point */ float tcSonarRay::CalculateDepth(float range_m, float& reflectionLoss_dB) const { const float beyondRay = -999.9f; reflectionLoss_dB = 99.0f; if (data.size() == 0) { wxASSERT(false); return beyondRay; } if (range_m >= data.back().xmax) return beyondRay; for (size_t k=0; k<data.size(); k++) { if (range_m < data[k].xmax) { reflectionLoss_dB = data[k].reflectionLoss_dB; float dx = range_m - data[k].xc; float yterm = sqrtf(data[k].R2 - dx*dx); return (data[k].R < 0) ? -yterm + data[k].yc : yterm + data[k].yc; } } wxASSERT(false); // error, not found in ray and not beyond ray return beyondRay; } /** * */ tcSonarRay::tcSonarRay() { } /** * */ tcSonarRay::~tcSonarRay() { } Index: Game.cpp =================================================================== RCS file: /cvsroot/gcblue/gcb_wx/src/sim/Game.cpp,v retrieving revision 1.166 retrieving revision 1.167 diff -C2 -d -r1.166 -r1.167 *** Game.cpp 6 Dec 2006 01:20:43 -0000 1.166 --- Game.cpp 20 Dec 2006 00:45:46 -0000 1.167 *************** *** 68,71 **** --- 68,72 ---- #include "tcPlatformDBObject.h" #include "tcDatabaseViewer.h" + #include "tcSonarEnvironment.h" #include <osg/Timer> *************** *** 562,565 **** --- 563,572 ---- std::cout << "Time init success" << std::endl; + #ifdef _DEBUG + // tcSonarEnvironment::Get()->Test(); + #endif + + + try { *************** *** 2784,2787 **** --- 2791,2799 ---- return; } + else if (chatBox->mbActive) + { + chatBox->SetActive(false); + return; + } --- NEW FILE: tcSonarEnvironment.cpp --- /** ** @file tcSonarEnvironment.cpp */ /* Copyright (C) 2006 Dewitt Colclough (de...@gc...) ** All rights reserved. ** This file is part of the Global Conflict Blue (GCB) program. ** GCB is free software; you can redistribute it and/or modify ** it under the terms of version 2 of the GNU General Public License as ** published by the Free Software Foundation. ** GCB is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** You should have received a copy of the GNU General Public License ** along with GCB; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA **/ #include "stdwx.h" #include "tcSonarEnvironment.h" #include "tcSonarRay.h" #include "tcOptions.h" #include <osg/Timer> #ifdef _DEBUG #define new DEBUG_NEW #endif tcSonarEnvironment* tcSonarEnvironment::Get() { static tcSonarEnvironment instance; return &instance; } void tcSonarEnvironment::AddSVPPoint(float depth_m, float speed_mps) { SVPData data; data.depth_m = depth_m; data.v_mps = speed_mps; svp.push_back(data); if (svp.size() < 2) return; if (!ValidateSVP()) return; for (size_t k=0; k<svp.size()-1; k++) { float inv_gradient = 0; if (svp[k+1].v_mps != svp[k].v_mps) { inv_gradient = (svp[k+1].depth_m - svp[k].depth_m) / (svp[k+1].v_mps - svp[k].v_mps); } else { inv_gradient = 1e7; } float R = svp[k].v_mps * inv_gradient; svp[k].R_m = R; svp[k].R2_m = R*R; } svp.back().R_m = 1e10f; svp.back().R2_m = 1e20f; } /** * @param startDepth_m depth of sonar (positive number) * @param startAngle_rad starting angle of ray, positive is down */ const tcSonarRay& tcSonarEnvironment::CalculateRay(float startDepth_m, float startAngle_rad) { static tcSonarRay ray; ray.data.clear(); const float max_x = 100e3; float x = 0; float y = startDepth_m; float angle = startAngle_rad; unsigned int bounces = 0; const unsigned int maxBounces = 4; float reflectionLoss_dB = 0; if (fabsf(angle) < 0.002f) { angle = (angle > 0) ? 0.002f : -0.002f; } if (!ValidateSVP()) { return ray; } while ((x <= max_x) && (reflectionLoss_dB < 20.0f) && (ray.data.size() < 100)) { tcSonarRay::RayPoint point; point.x = x; point.y = y; // find the SVP segment we're in size_t currentSegment = GetSVPSegment(angle, y, reflectionLoss_dB); float R = svp[currentSegment].R_m; float R2 = svp[currentSegment].R2_m; float xc = x + R*sinf(angle); float yc = y - R*cosf(angle); float y_next = (angle >= 0) ? svp[currentSegment+1].depth_m : svp[currentSegment].depth_m; float x_term = R2 - (y_next-yc)*(y_next-yc); float x_term2 = R2 - (y-yc)*(y-yc); float x_solve = 0; float y_solve = 0; if (x_term > 0) { float sqrt_x_term = sqrtf(x_term); float x_solve1 = xc + sqrt_x_term; float x_solve2 = xc - sqrt_x_term; if ((x_solve2 > x) && (x_solve2 < x_solve1)) x_solve = x_solve2; else x_solve = x_solve1; y_solve = y_next; } else if (x_term2 > 0) { x_solve = xc + sqrtf(x_term2); y_solve = y; } else { wxASSERT(false); return ray; } wxASSERT(x_solve > x); float angle_solve = atanf((xc-x_solve)/(y_solve-yc)); if (y_solve <= 0) // hit surface? { y = 0; angle_solve = (angle_solve < 0) ? -angle_solve : angle_solve; reflectionLoss_dB += surfaceLoss_dB; } x = x_solve; y = y_solve; angle = angle_solve; point.xmax = x; point.R = R; point.R2 = R2; point.xc = xc; point.yc = yc; point.reflectionLoss_dB = reflectionLoss_dB; ray.data.push_back(point); } return ray; } void tcSonarEnvironment::Clear() { ClearSVP(); beamCache.clear(); } void tcSonarEnvironment::ClearSVP() { SetDefaultSVP(); } float tcSonarEnvironment::GetAmbientNL(float freq_Hz) const { return noiseLevelBase - noiseLevelSlope * log10f(freq_Hz); } float tcSonarEnvironment::GetBottomLoss() const { return bottomLoss_dB; } unsigned int tcSonarEnvironment::GetSeaState() const { return seaState; } float tcSonarEnvironment::GetSurfaceLoss() const { return surfaceLoss_dB; } const std::vector<tcSonarEnvironment::SVPData>& tcSonarEnvironment::GetSVP() const { return svp; } size_t tcSonarEnvironment::GetSVPSegment(float& angle, float& depth, float& reflectionLoss_dB) { if (depth >= svp.back().depth_m) // hit bottom? { depth -= 0.001f; angle = -angle; reflectionLoss_dB += bottomLoss_dB; return svp.size()-2; } if (angle >= 0) { for (size_t k=0;(k<svp.size()-1); k++) { if ((depth >= svp[k].depth_m) && (depth < svp[k+1].depth_m)) { return k; } } } else { for (size_t k=0;(k<svp.size()-1); k++) { if ((depth > svp[k].depth_m) && (depth <= svp[k+1].depth_m)) { return k; } } } wxASSERT(false); fprintf(stderr, "tcSonarEnvironment::GetSVPSegment - unknown error\n"); return 0; } /** * @return transmission loss in dB (positive loss) * @param depth_m depth of sonar */ float tcSonarEnvironment::GetTL(long key, double t, float depth_m, float targetRange_m, float targetDepth_m) { if (tcOptions::Get()->useRayTracingSonar == 0) { return GetTLSimple(depth_m, targetRange_m, targetDepth_m); } std::map<long, BeamData>::iterator iter = beamCache.find(key); if (iter == beamCache.end()) { BeamData beamData; beamData.depth_m = -999.9f; // to force update beamData.t_update = t; beamCache[key] = beamData; iter = beamCache.find(key); } wxASSERT(iter != beamCache.end()); if (fabsf(iter->second.depth_m - depth_m) >= depthUpdateThreshold_m) { UpdateBeam(iter->second.beam, depth_m); iter->second.depth_m = depth_m; } float TL_min = 10.0f * log10f(targetRange_m); // cylindrical spreading ref 1 m float TL_max = 2.5f * TL_min; // cube law spreading float flux = 1e-6f; for (size_t k=0; k<iter->second.beam.size(); k++) { float reflectionLoss_dB; float dd_m = fabsf(iter->second.beam[k].CalculateDepth(targetRange_m, reflectionLoss_dB) - targetDepth_m); if (dd_m < 50.0) { float a = -fluxDecay*dd_m - 0.23026f*reflectionLoss_dB; flux += expf(a); } } float path_TL = rayCount_dB -10*log10(flux); wxASSERT(path_TL >= 0); float total_TL = path_TL + TL_min; if (total_TL < TL_max) { return total_TL; } else { return TL_max; } } float tcSonarEnvironment::GetTLSimple(float depth_m, float targetRange_m, float targetDepth_m) { float TL_dB = 20.0f * log10f(targetRange_m); // crude thermocline bool parentAbove = depth_m < 80.0; bool targetAbove = targetDepth_m < 80.0; if (parentAbove != targetAbove) TL_dB += 10.0f; // add 10 dB loss return TL_dB; } void tcSonarEnvironment::SetBottomLoss(float val_dB) { bottomLoss_dB = val_dB; } void tcSonarEnvironment::SetDefaultSVP() { svp.clear(); AddSVPPoint(0, 1515); AddSVPPoint(200, 1500); AddSVPPoint(300, 1510); AddSVPPoint(500, 1520); } void tcSonarEnvironment::SetSeaState(unsigned int val) { if (val > 7) { val = 7; wxASSERT(false); } seaState = val; noiseLevelSlope = 16.0; switch (seaState) { case 0: noiseLevelBase = 3.0f*noiseLevelSlope + 44.0f; break; case 1: noiseLevelBase = 3.0f*noiseLevelSlope + 53.0f; break; case 2: noiseLevelBase = 3.0f*noiseLevelSlope + 58.0f; break; case 3: noiseLevelBase = 3.0f*noiseLevelSlope + 62.0f; break; case 4: noiseLevelBase = 3.0f*noiseLevelSlope + 65.0f; break; case 5: noiseLevelBase = 3.0f*noiseLevelSlope + 67.0f; break; case 6: noiseLevelBase = 3.0f*noiseLevelSlope + 69.0f; break; case 7: noiseLevelBase = 3.0f*noiseLevelSlope + 73.0f; break; default: wxASSERT(false); } } void tcSonarEnvironment::SetSurfaceLoss(float val_dB) { surfaceLoss_dB = val_dB; } void tcSonarEnvironment::SetSVP(const std::vector<tcSonarEnvironment::SVPData>& svp_) { svp = svp_; } void tcSonarEnvironment::Test() { osg::Timer_t t1 = osg::Timer::instance()->tick(); float startDepth = 100.0f; std::vector<tcSonarRay> beam; UpdateBeam(beam, startDepth); osg::Timer_t t2 = osg::Timer::instance()->tick(); double elapsedTime_ms = osg::Timer::instance()->delta_m(t1, t2); WriteBeamToCSV(beam, "beam.csv"); float TL_dB = GetTL(1, 0, startDepth, 1000.0f, 300.0f); // call once to calc beam // calculate TL vs. range osg::Timer_t t3 = osg::Timer::instance()->tick(); std::vector<float> range_vect; std::vector<float> loss_vect; for (float range_m=0; range_m<100000.0f; range_m+=250.0f) { TL_dB = GetTL(1, 0, startDepth, range_m, 50.0f); range_vect.push_back(range_m); loss_vect.push_back(TL_dB); } osg::Timer_t t4 = osg::Timer::instance()->tick(); double elapsedTime2_ms = osg::Timer::instance()->delta_m(t3, t4); WriteTLToCSV(range_vect, loss_vect, "TL.csv"); wxString s; s.Printf("Elapsed time for %d rays: %.1f ms (%.1f ms/ray)\n" "TL time for %d calcs: %.1f ms (%.1f ms/calc)", beam.size(), elapsedTime_ms, elapsedTime_ms / float(beam.size()), range_vect.size(), elapsedTime2_ms, elapsedTime2_ms / float(range_vect.size())); wxMessageBox(s); } void tcSonarEnvironment::UpdateBeam(std::vector<tcSonarRay>& beam, float depth_m) { beam.clear(); for (float angle=minAngle_rad; angle<=maxAngle_rad; angle += angleStep_rad) { beam.push_back(CalculateRay(depth_m, angle)); } } /** * @return true if SVP is valid, false otherwise */ bool tcSonarEnvironment::ValidateSVP() { if (svp.size() < 2) { wxASSERT(false); fprintf(stderr, "tcSonarEnvironment::ValidateSVP - SVP must have at least 2 points\n"); return false; } if (svp[0].depth_m != 0) { wxASSERT(false); fprintf(stderr, "tcSonarEnvironment::ValidateSVP - first SVP depth must be 0 (currently = %f)\n", svp[0].depth_m); return false; } for (size_t k=1; k<svp.size(); k++) { if (svp[k].depth_m <= svp[k-1].depth_m) { wxASSERT(false); fprintf(stderr, "tcSonarEnvironment::ValidateSVP - SVP depth must monotonically increase (%d,%f <= %d,%f)\n", k, svp[k].depth_m, k-1, svp[k-1].depth_m); return false; } } return true; } void tcSonarEnvironment::WriteBeamToCSV(const std::vector<tcSonarRay>& beam, const std::string& fileName) { tcFile log; log.Open(fileName.c_str(), tcFile::modeCreate | tcFile::modeWrite | tcFile::modeText); for (float range_km=0; range_km<100.0f; range_km+=0.25f) { wxString s; s.Printf("%.1f,", range_km); log.WriteString(s.c_str()); for (size_t k=0; k<beam.size(); k+=10) { float reflectionLoss_dB; s.Printf("%.1f,", beam[k].CalculateDepth(1000.0f*range_km, reflectionLoss_dB)); log.WriteString(s.c_str()); } log.WriteString("\n"); } } void tcSonarEnvironment::WriteTLToCSV(const std::vector<float>& range_vect, const std::vector<float>& loss_vect, const std::string& fileName) { tcFile log; log.Open(fileName.c_str(), tcFile::modeCreate | tcFile::modeWrite | tcFile::modeText); for (size_t k=0; k<range_vect.size(); k++) { wxString s; s.Printf("%.1f,%.1f,%.1f,%.1f\n", range_vect[k], loss_vect[k], 10*log10(range_vect[k]), 30*log10(range_vect[k])); log.WriteString(s.c_str()); } } /** * */ tcSonarEnvironment::tcSonarEnvironment() : surfaceLoss_dB(10.0f), bottomLoss_dB(15.0f), minAngle_rad(-0.295f), maxAngle_rad(0.295f), angleStep_rad(0.01f), rayCount_dB(17.8f), depthUpdateThreshold_m(5.0f), fluxDecay(0.1), seaState(0) { SetDefaultSVP(); SetSeaState(3); } /** * */ tcSonarEnvironment::~tcSonarEnvironment() { } |