bool PlatformPosition::getPlatformPositionAtTime(JSDDateTime time, std::vector<double>& position, std::vector<double>& speed) { Ephemeris* ephemeris = this->Interpolate(time); double* position_ptr = ephemeris->get_position(); double* speed_ptr = ephemeris->get_speed(); if (position.size() != 3) position.resize(3); if (speed.size() != 3) speed.resize(3); position[0] = position_ptr[0]; position[1] = position_ptr[1]; position[2] = position_ptr[2]; speed[0] = speed_ptr[0]; speed[1] = speed_ptr[1]; speed[2] = speed_ptr[2]; return true; }
/*----------------------------------------------------------------------------------------------*/ void *Ephemeris_Thread(void *_arg) { Ephemeris *aEphemeris = pEphemeris; aEphemeris->SetPid(); while(grun) { aEphemeris->Import(); aEphemeris->Export(); aEphemeris->IncExecTic(); } pthread_exit(0); }
// Compute and log the measured periods of the moons. void LogPeriods(Ephemeris<KSP> const& ephemeris) { auto const position = [this, &ephemeris]( not_null<MassiveBody const*> body, Instant const& t) { return ephemeris.trajectory(body)->EvaluatePosition(t, nullptr); }; auto const barycentre = [this, &position](Instant const& t) { BarycentreCalculator<Position<KSP>, Mass> result; for (auto const body : jool_system_) { result.Add(position(body, t), body->mass()); } return result.Get(); }; auto const barycentric_position = [this, &barycentre, &ephemeris, &position]( not_null<MassiveBody const*> body, Instant const& t) { return position(body, t) - barycentre(t); }; for (auto const moon : {laythe_, vall_, tylo_}) { auto const moon_y = [this, &barycentric_position, moon](Instant const& t) { return barycentric_position(moon, t).coordinates().y; }; LOG(INFO) << (moon == laythe_ ? "Laythe" : moon == vall_ ? "Vall" : "Tylo"); Sign const s0(moon_y(game_epoch_)); Instant t0 = game_epoch_; Time const Δt = 45 * Minute; while (Sign(moon_y(t0)) == s0) { t0 += Δt; } // The moon crosses the xz plane between t0 and t0 - Δt. Instant t1 = t0; int const orbits = moon == laythe_ ? 8 : moon == vall_ ? 4 : 2; for (int i = 0; i < orbits; ++i) { while (Sign(moon_y(t1)) != s0) { t1 += Δt; } // The crossing of the xz plane halfway through the orbit occurs between // t1 and t1 - Δt. while (Sign(moon_y(t1)) == s0) { t1 += Δt; } // The |i|th orbit ends between t1 and t1 - Δt. } Time const actual_period = (Bisect(moon_y, t1 - Δt, t1) - Bisect(moon_y, t0 - Δt, t0)) / orbits; Time const expected_period = (2 * π * Radian) / *elements_[moon].mean_motion; LOG(INFO) << "actual period : " << actual_period; LOG(INFO) << "expected period : " << expected_period; LOG(INFO) << "error : " << RelativeError(expected_period, actual_period); } }
Ephemeris* PlatformPosition::Interpolate(JSDDateTime date) const { const double JOURCIVIL_LENGTH = 86400.0; Ephemeris* ephem = NULL; if (_nbrData <= 1) { return NULL; } /* * The first element of the list is cloned to ensure that the * output ephemeris is expressed in the same coordinate system as * input ones */ ephem = _data[0]->Clone(); /* NORMAL CASE */ /*------------*/ double dt = 0.0; if (ephem != NULL) { ephem->set_date(date); dt = (date.get_day0hTU().get_julianDate() - _data[0]->get_date().get_day0hTU().get_julianDate()) * JOURCIVIL_LENGTH + date.get_second() - _data[0]->get_date().get_second() + date.get_decimal() - _data[0]->get_date().get_decimal(); /* Computation by Everett */ /*---------------------*/ double pos[3]; double speed[3]; for (int j = 0; j < 3; j++) { _interpolator[j]->Interpolate(dt, pos[j], speed[j]); } ephem->set_position(pos); ephem->set_speed(speed); } return ephem; }
void LogEphemeris(Ephemeris<KSP> const& ephemeris, bool const reference, std::string const& name) { Instant const begin = reference ? game_epoch_ : long_time_; Instant const end = reference ? reference_ : comparison_; std::string const purpose = reference ? "reference" : "comparison"; // Mathematica tends to be slow when dealing with quantities, so we give // everything in SI units. std::vector<double> times; // Indexed chronologically, then by body. std::vector<std::vector<Vector<double, KSP>>> barycentric_positions; for (Instant t = begin; t < end; t += 45 * Minute) { auto const position = [&ephemeris, t](not_null<MassiveBody const*> body) { return ephemeris.trajectory(body)-> EvaluatePosition(t, /*hint=*/nullptr); }; times.emplace_back((t - game_epoch_) / Second); BarycentreCalculator<Position<KSP>, GravitationalParameter> jool_system_barycentre; for (auto const body : jool_system_) { jool_system_barycentre.Add(position(body), body->gravitational_parameter()); } barycentric_positions.emplace_back(); for (auto const body : jool_system_) { // TODO(egg): when our dynamic frames support that, it would make sense // to use a nonrotating dynamic frame centred at the barycentre of the // Jool system, instead of computing the barycentre and difference // ourselves. barycentric_positions.back().emplace_back( (position(body) - jool_system_barycentre.Get()) / Metre); } } std::ofstream file; file.open(name + "_" + purpose + ".generated.wl"); file << mathematica::Assign(name + purpose + "q", barycentric_positions); file << mathematica::Assign(name + purpose + "t", times); file.close(); }
osg::Group* addLights(osg::View* view, osg::Node* root, int lightNum) { MapNode* mapNode = MapNode::get(root); const SpatialReference* mapsrs = mapNode->getMapSRS(); const SpatialReference* geosrs = mapsrs->getGeographicSRS(); osg::Vec3d world; osg::Group* lights = new osg::Group(); // Add a directional light that simulates the sun - but skip this if a sky // was already added in the earth file. if (lightNum == 0) { Ephemeris e; DateTime dt(2016, 8, 10, 14.0); CelestialBody sun = e.getSunPosition(dt); world = sun.geocentric; osg::Light* sunLight = new osg::Light(lightNum++); world.normalize(); sunLight->setPosition(osg::Vec4d(world, 0.0)); sunLight->setAmbient(osg::Vec4(0.2, 0.2, 0.2, 1.0)); sunLight->setDiffuse(osg::Vec4(1.0, 1.0, 0.9, 1.0)); osg::LightSource* sunLS = new osg::LightSource(); sunLS->setLight(sunLight); lights->addChild( sunLS ); ShadowCaster* caster = osgEarth::findTopMostNodeOfType<ShadowCaster>(root); if (caster) { OE_INFO << "Found a shadow caster!\n"; caster->setLight(sunLight); } } #if 1 // A red spot light. A spot light has a real position in space // and points in a specific direciton. The Cutoff and Exponent // properties control the cone angle and sharpness, respectively { GeoPoint p(geosrs, -121, 34, 5000000., ALTMODE_ABSOLUTE); p.toWorld(world); osg::Light* spot = new osg::Light(lightNum++); spot->setPosition(worldToVec4(world)); spot->setAmbient(osg::Vec4(0,0.2,0,1)); spot->setDiffuse(osg::Vec4(1,0,0,1)); spot->setSpotCutoff(20.0f); spot->setSpotExponent(100.0f); // point straight down at the map: world.normalize(); spot->setDirection(-world); osg::LightSource* spotLS = new osg::LightSource(); spotLS->setLight(spot); lights->addChild( spotLS ); } // A green point light. A Point light lives at a real location in // space and lights equally in all directions. { GeoPoint p(geosrs, -45, -35, 1000000., ALTMODE_ABSOLUTE); p.toWorld(world); osg::Light* point = new osg::Light(lightNum++); point->setPosition(worldToVec4(world)); point->setAmbient(osg::Vec4(0,0,0,1)); point->setDiffuse(osg::Vec4(1.0, 1.0, 0.0,1)); osg::LightSource* pointLS = new osg::LightSource(); pointLS->setLight(point); lights->addChild( pointLS ); } #endif // Generate the necessary uniforms for the shaders. GenerateGL3LightingUniforms gen; lights->accept(gen); return lights; }
Ephemeris* PlatformPosition::Interpolate(JSDDateTime date) { const double JOURCIVIL_LENGTH = 86400.0 ; Ephemeris* ephem = NULL; if (_nbrData<=1) { std::cout << "a..." << std::endl; ephem = NULL; } else { /* * The first element of the list is cloned to ensure that the output ephemeris is expressed in the same coordinate system as input ones */ ephem = _data[0]->Clone(); /* NORMAL CASE */ /*------------*/ double * x = new double[_nbrData]; double * y = new double[_nbrData]; double * yd = new double[_nbrData]; double dt = 0.0; //double d; x[0] = 0.0 ; for (int i = 1 ; i < _nbrData ; i++) { x[i] = (_data[i]->get_date().get_day0hTU().get_julianDate() - _data[0]->get_date().get_day0hTU().get_julianDate()) * JOURCIVIL_LENGTH + _data[i]->get_date().get_second() - _data[0]->get_date().get_second() + _data[i]->get_date().get_decimal() - _data[0]->get_date().get_decimal(); } if (ephem != NULL) { ephem->set_date(date); dt = (date.get_day0hTU().get_julianDate() - _data[0]->get_date().get_day0hTU().get_julianDate()) * JOURCIVIL_LENGTH + date.get_second() - _data[0]->get_date().get_second() + date.get_decimal() - _data[0]->get_date().get_decimal(); /* Computation by Everett */ /*---------------------*/ double pos[3]; double vit[3]; for (int j = 0 ; j < 3 ; j++) { for (int i = 0 ; i < _nbrData ; i++) { y[i] = _data[i]->get_position()[j] ; yd[i] = _data[i]->get_vitesse()[j] ; } HermiteInterpolator interpolator(_nbrData,x,y,yd); interpolator.Interpolate(dt, pos[j], vit[j]); } ephem->set_position(pos); ephem->set_vitesse(vit); } delete[] x; delete[] y; delete[] yd; } return ephem; }
not_null<MassiveBody const*> SolarSystem<Frame>::massive_body( Ephemeris<Frame> const & ephemeris, std::string const & name) const { return ephemeris.bodies()[index(name)]; }
bool RINEX_NavigationMessage::ReadBody(std::ifstream &ifs, int leap_sec) { bool success = false; std::string buf; int top_field_length; if ((type == GPS_Navigation) && ((ver == RINEX::Ver2) || (ver == RINEX::Ver210) || (ver == RINEX::Ver211) || (ver == RINEX::Ver212))) { top_field_length = RINEX_TOP_FIELD_WIDTH_Normal; } else { top_field_length = RINEX_TOP_FIELD_WIDTH_QZS_and_300_above; } while (ifs) { Ephemeris ephem; int prn = 0; for (Ephemeris::Ephemeris_column column = Ephemeris::TOC; column < Ephemeris::END; column = (Ephemeris::Ephemeris_column)(column + 4)) { std::getline(ifs, buf); if (!ifs) { break; } else { if (column == Ephemeris::TOC) { int Epoch_offset; if ((type == GPS_Navigation) && ((ver == RINEX::Ver2) || (ver == RINEX::Ver210) || (ver == RINEX::Ver211) || (ver == RINEX::Ver212))) { prn = atoi(buf.substr(0, 2).c_str()); Epoch_offset = 2; } else { std::string satellite_type = buf.substr(0, 1); if (satellite_type == "G") { prn = atoi(buf.substr(1, 2).c_str()); } else if (satellite_type == "J") { prn = atoi(buf.substr(1, 2).c_str()) + RINEX::QZSS_PRN_Offset; } Epoch_offset = 3; } ephem.SetPRN(prn); int year = atoi(buf.substr(Epoch_offset, 3).c_str()); if (year < 80) { year += 2000; } else { year += 1900; } int month = atoi(buf.substr(Epoch_offset + 3, 3).c_str()); int day = atoi(buf.substr(Epoch_offset + 6, 3).c_str()); int hour = atoi(buf.substr(Epoch_offset + 9, 3).c_str()); int minute = atoi(buf.substr(Epoch_offset + 12, 3).c_str()); long double sec; sscanf(buf.substr(Epoch_offset + 15, 5).c_str(), "%Lf", &sec); ephem.SetToc(GPS_Time(year, month, day, hour, minute, sec, leap_sec)); success = true; } else { ephem.SetData(GetLongDouble(buf.substr(0, top_field_length)), column); } if (column != Ephemeris::TOT) { for (int i = 1; i < RINEX_NAV_FIELDS_LINE; i++) { ephem.SetData(GetLongDouble(buf.substr(top_field_length + (i - 1) * RINEX_NORMAL_FIELD_WIDTH, RINEX_NORMAL_FIELD_WIDTH)), (Ephemeris::Ephemeris_column)(column + i)); } } else { ephem.SetData(GetLongDouble(buf.substr(top_field_length, RINEX_NORMAL_FIELD_WIDTH)), Ephemeris::FIT); } } } if (prn < 1) { continue; } else { // Do nothing } ephem_map.insert(std::multimap<int, Ephemeris>::value_type(prn, ephem)); } return success; }