1 #include "RefractionModel.h" 2 #include "AntarcticAtmosphere.h" 3 #include "AntarcticaGeometry.h" 14 static const double A[nh][nH] =
16 { 3.5553, 4.7295, 4.4731, 5.1151, 4.8049 },
17 { 3.2987, 3.1228, 4.0890, 3.7471, 4.4854 },
18 { 2.9440, 2.8858, 2.6563, 3.4098, 3.2843 },
19 { 2.4514, 2.6189, 2.4666, 2.8971, 3.1265 }
23 static const double B[nh][nH] =
25 { -0.0095, 0.1173, 0.0907, 0.1432, 0.1149 },
26 { 0.0029, -0.0141, 0.0898, 0.0533, 0.1190 },
27 { 0.0001, -0.0052, -0.0245, 0.0517, 0.0406 },
28 { -0.0156, -0.0026, -0.0170, 0.0214, 0.0584 }
32 static const double C[nh][nH] =
34 { 4.3780, 4.5653, 4.5795, 4.7217, 4.7491 },
35 { 4.2998, 4.3507, 4.5034, 4.5180, 4.6733 },
36 { 4.2362, 4.2858, 4.3466, 4.4356, 4.4903 },
37 { 4.3714, 4.3139, 4.3234, 4.3701, 4.4639 }
40 static const double D[nh][nH] =
42 { 5.0281, 7.0018, 6.3010, 7.9669, 7.1021 },
43 { 5.4476, 5.3225, 6.8895, 5.8489, 7.8475 },
44 { 5.5789, 5.8992, 5.0228, 6.4541, 6.1882 },
45 { 6.4298, 7.4389, 7.0311, 7.2302, 7.9347 }
48 static const double E[nh][nH] =
50 { -5.5423, -5.8028, -5.8366, -6.0156, -6.0501 },
51 { -5.4901, -5.5646, -5.7826, -5.7774, -5.9982 },
52 { -5.4010, -5.5246, -5.5159, -5.7338, -5.7958 },
53 { -5.3860, -5.5437, -5.6085, -5.7002, -5.8241 }
56 static TH2 * hCoeffs[5] = {0};
59 static void init_hists()
61 for (
int coeff = 0; coeff < 5; coeff++)
64 hCoeffs[coeff] =
new TH2D(TString::Format(
"pg_coeffs_%c",
'A' + coeff),TString::Format(
"%c Coeffs",
'A' + coeff) ,
65 nh, -0.5e3, 0.35e3, nH, 35.5e3 , 40.5e3);
67 hCoeffs[coeff]->SetDirectory(0);
69 for (
int i = 1; i <= nh; i++)
71 for (
int j = 1; j<= nH; j++)
73 hCoeffs[coeff]->SetBinContent(i,j, (coeff == 0 ? A :
85 double Refraction::PositionIndependentModel::getElevationCorrection(
const Adu5Pat * pat,
const AntarcticCoord * source,
double * correction_at_source,
double dth)
const 89 double H = AntarcticAtmosphere::WGS84toMSL(pat);
91 double h = AntarcticAtmosphere::WGS84toMSL(s.x,s.y,s.z);
94 double last_at_source= 0;
95 double theta = pp.source_theta + dth;
100 double corr = getElevationCorrection(theta, h,H, &at_source);
105 last_at_source = at_source;
107 if (theta + corr > pp.source_theta);
117 if (correction_at_source) *correction_at_source = last_at_source;
121 double Refraction::PGFit::getElevationCorrection(
double theta,
double h,
double H,
double * correction_at_source)
const 125 if (h > 4e3) h = 4e3;
127 if (H < 36e3) H = 36e3;
128 if (H > 40e3) H = 40e3;
130 double a = hCoeffs[0]->Interpolate(h,H);
131 double b = hCoeffs[1]->Interpolate(h,H);
132 double c = hCoeffs[2]->Interpolate(h,H);
133 double d = hCoeffs[3]->Interpolate(h,H);
134 double e = hCoeffs[4]->Interpolate(h,H);
136 return -(a / (el * el) + b / (el) + c * exp(d * (el-e)));
137 if (correction_at_source) *correction_at_source = 0;
141 const double speed_of_light=299792458;
142 int Refraction::RaytracerSpherical::raytrace(
const Setup * setup, Result * result)
150 last_R_c = setup->R_c;
152 double r0 = setup->start_alt + setup->R_c;
153 double r1 = setup->end_alt + setup->R_c;
154 double theta = setup->thrown_payload_angle * TMath::DegToRad();
162 result->ray_distance = 0;
163 result->ray_time = 0;
164 result->reflected =
false;
165 result->reflection_angle =-1;
166 result->reflect_xy[0] = 0;
167 result->reflect_xy[1] = 0;
169 double reflect_r = setup->R_c + setup->surface_alt;
175 last_path_x.push_back(x);
176 last_path_X.push_back(X);
177 last_path_y.push_back(y);
178 last_path_s.push_back(result->ray_distance);
179 last_path_t.push_back(result->ray_time);
182 double dphi = step_size / r;
183 double dr= step_size * tan(theta);
185 bool am_reflecting =
false;
187 if (r+dr < reflect_r)
189 am_reflecting =
true;
191 double temp_step_size = dr/tan(theta);
192 dphi = temp_step_size / r;
195 double N = m->get(r-setup->R_c, AntarcticAtmosphere::REFRACTIVITY);
196 double N1 = m->get(r-setup->R_c+dr, AntarcticAtmosphere::REFRACTIVITY);
198 double dn = DN * 1e-6;
199 double n = 1 + N * 1e-6;
201 double dtheta = dn/n/tan(theta) + dphi;
204 double dL = sqrt((r*dphi)*(r*dphi) + dr*dr);
205 double rho = m->get(r-setup->R_c,AntarcticAtmosphere::DENSITY);
206 result->ray_distance += dL;
207 if (rho < 0) rho = 0;
209 result->ray_time += dL * n / speed_of_light;
221 for (
unsigned i =0; i < last_path_X.size(); i++) last_path_X[i] = 0;
223 result->reflected =
true;
224 result->reflection_angle = theta * TMath::RadToDeg();
225 result->reflect_xy[0] = x;
226 result->reflect_xy[1] = y;
230 last_path_x.push_back(x);
231 last_path_y.push_back(y);
232 last_path_s.push_back(result->ray_distance);
233 last_path_t.push_back(result->ray_time);
234 last_path_X.push_back(X);
236 for (
unsigned i = 0; i < last_path_X.size();i++) last_path_X[i]=X-last_path_X[i];
239 double dM = sqrt(dx*dx + dy*dy);
241 double last_dx = last_path_x[last_path_x.size()-1]-last_path_x[last_path_x.size()-2];
242 double last_dy = last_path_y[last_path_y.size()-1]-last_path_y[last_path_y.size()-2];
243 double last_r = sqrt(last_dx*last_dx + last_dy*last_dy);
244 result->last_dx = last_dx/last_r;
245 result->last_dy = last_dy/last_r;
246 result->full_dx = dx/dM;
247 result->full_dy = dy/dM;
251 result->actual_distance = dM;
252 result->surface_distance = phi * setup->R_c;
253 result->apparent_source_angle = theta * TMath::RadToDeg();
254 result->actual_source_angle = 90 - acos( (dx*x + dy*y) / (r * dM)) *TMath::RadToDeg();
255 result->actual_payload_angle = 90 - acos(dy/dM) * TMath::RadToDeg();
261 TGraph* Refraction::RaytracerSpherical::makeXYGraph(TGraph * g)
const 263 if (!g)
return new TGraph (last_path_x.size(), &last_path_x[0], &last_path_y[0]);
264 g->Set(last_path_x.size());
265 memcpy(g->GetY(), &last_path_y[0], g->GetN()*
sizeof(double));
266 memcpy(g->GetX(), &last_path_x[0], g->GetN()*
sizeof(double));
273 TGraph* Refraction::RaytracerSpherical::makeXTGraph(TGraph *g)
const 275 if (!g)
return new TGraph (last_path_x.size(), &last_path_x[0], &last_path_t[0]);
276 g->Set(last_path_x.size());
277 memcpy(g->GetY(), &last_path_t[0], g->GetN()*
sizeof(double));
278 memcpy(g->GetX(), &last_path_x[0], g->GetN()*
sizeof(double));
284 TGraph * Refraction::RaytracerSpherical::makePhiAltGraph(TGraph * g)
const 287 if (!g) g =
new TGraph(last_path_x.size());
288 else g->Set(last_path_x.size());
290 for (
int i = 0; i < g->GetN(); i++)
292 g->SetPoint(i, 90-atan2(last_path_y[i], last_path_x[i])*TMath::RadToDeg(), sqrt(last_path_x[i]*last_path_x[i] + last_path_y[i]*last_path_y[i])- last_R_c);
297 TGraph* Refraction::RaytracerSpherical::makeSTGraph(TGraph *g)
const 299 if (!g)
return new TGraph (last_path_x.size(), &last_path_s[0], &last_path_t[0]);
300 g->Set(last_path_x.size());
301 memcpy(g->GetY(), &last_path_t[0], g->GetN()*
sizeof(double));
302 memcpy(g->GetX(), &last_path_s[0], g->GetN()*
sizeof(double));
307 double Refraction::RaytracerSpherical::lastMinAlt()
const 309 if (!nSteps())
return -9999;
311 double R2min = last_path_x[0]*last_path_x[0] + last_path_y[0] * last_path_y[0];
313 for (
int i =1; i < nSteps(); i++)
315 double R2= last_path_x[i]*last_path_x[i] + last_path_y[i] * last_path_y[i];
316 if (R2 < R2min) R2min = R2;
319 return sqrt(R2min) - last_R_c;
322 TGraph* Refraction::RaytracerSpherical::makeRTGraph(TGraph * g)
const 324 if (!g) g =
new TGraph (last_path_t.size());
325 else g->Set(last_path_t.size());
327 for (
int i = 0; i < g->GetN(); i++)
329 g->SetPoint(i,last_path_t[i],sqrt(last_path_x[i]*last_path_x[i] + last_path_y[i]*last_path_y[i]) -last_R_c);
336 double Refraction::SphRay::getElevationCorrection(
double el,
double hSource,
double hPayload,
double * correction_at_source )
const 347 hSource = TMath::Max(0., hSource);
348 hSource = TMath::Min(4999., hSource);
349 hSource = ((int)hSource/100) * 100;
350 hash += hSource / 100;
353 hPayload = TMath::Max(36e3, hPayload);
354 hPayload = TMath::Min(40.999e3, hPayload);
355 hPayload = ((int)hPayload/100) * 100;
356 hash += 50 * ((hPayload-36e3) / 100);
360 el = TMath::Min(90.,el);
361 el = TMath::Max(0.,el);
362 el = ((int) (el * 100)) / 100.;
364 hash += 50 * 50 * el * 100;
366 TLockGuard l(&cache_lock);
367 if (cache.count(hash))
369 if (correction_at_source)
370 *correction_at_source = cache[hash].second;
371 return cache[hash].first;
376 RaytracerSpherical ray(atm);
377 ray.step_size = step;
381 double throw_angle = TMath::RadToDeg() * acos ( cos(el * TMath::DegToRad()) * (R_c + hPayload) / (R_c + hSource) * (1 + 1e-6 * atm->get(hPayload, AntarcticAtmosphere::REFRACTIVITY)) / (1 + 1e-6 * atm->get(hSource, AntarcticAtmosphere::REFRACTIVITY)));
383 RaytracerSpherical::Setup s;
384 RaytracerSpherical::Result r;
386 s.start_alt = hSource;
387 s.end_alt = hPayload;
388 s.thrown_payload_angle = throw_angle;
394 double answer = r.actual_source_angle - r.apparent_source_angle;
395 double correction = r.actual_payload_angle - s.thrown_payload_angle;
400 TLockGuard l(&cache_lock);
401 if (!cache.count(hash))
402 cache[hash] = std::pair<double,double> (answer, correction) ;
405 if (correction_at_source) *correction_at_source = correction;
410 void Refraction::SphRay::adjustLatitude(
double lat,
double bearing)
414 TLockGuard l(&cache_lock);
419 const double a = 6378137.0 ;
420 const double b = 6356752.3;
421 const double ab = a*b;
422 const double ab2inv = 1./(ab*ab);
423 const double a2 = a*a;
424 const double a2inv = 1./a2;
425 const double b2 = b*b;
426 double sin_lat = sin(lat*TMath::DegToRad());
427 double cos_lat = cos(lat*TMath::DegToRad());
428 double sin2_lat = sin_lat*sin_lat;
429 double cos2_lat = cos_lat*cos_lat;
431 double arg = a2*cos2_lat + b2*sin2_lat;
432 double Minv = ab2inv * pow(arg,1.5);
433 double Ninv = a2inv * sqrt(arg);
435 double sin_alpha = sin(bearing*TMath::DegToRad());
436 double cos_alpha = cos(bearing*TMath::DegToRad());
437 double sin2_alpha = sin_alpha*sin_alpha;
438 double cos2_alpha = cos_alpha*cos_alpha;
440 R_c = pow(cos2_alpha*Minv + sin2_alpha*Ninv,-1);
struct __attribute__((packed))
Debugging use only TURF scaler data.
Adu5Pat – The ADU5 Position and Attitude Data.