void ReachableList::setInitValues() { // This info we do need from the calculator lastPosition = calculator->getlastPosition(); lastAltitude = calculator->getlastAltitude().getMeters(); _maxReach = RANGE_RADIUS; // default range radius Polar* polar = calculator->getPolar(); calcMode = ReachableList::altitude; if ( ! polar ) { calcMode = ReachableList::distance; // If no glider selected calculate nearest sites only. return; } Speed speed = polar->bestSpeed(0.0, 0.0, Speed(0)); // qDebug("speed for best LD= %f", speed.getKph() ); double ld = polar->bestLD( speed, speed, 0.0 ); // for coarse estimation (no wind) _maxReach = qMax( (lastAltitude/1000) * ld, _maxReach ); // look at least within 75km // Thats the maximum range we can reach // it in hard to get under sea level :-) // qDebug("maxReach: %f %f", _maxReach, (float)ld ); }
void Scene03::updateSpaceShip(float deltaTime) { spaceship->line()->color = WHITE; float rotspeed = 3.14f; static Vector2 velocity = Vector2((rand()%100)-50, (rand()%100)-50); static Polar polar = Polar((rand()%360) * DEG_TO_RAD, 400.0f); if (input()->getKey( GLFW_KEY_UP )) { spaceship->line()->color = RED; velocity += polar.cartesian() * deltaTime; // thrust } if (input()->getKey( GLFW_KEY_RIGHT )) { polar.angle += rotspeed * deltaTime; // rotate right } if (input()->getKey( GLFW_KEY_LEFT )) { polar.angle -= rotspeed * deltaTime; // rotate left } spaceship->rotation = polar.angle; spaceship->position += velocity * deltaTime; if (spaceship->position.x < 0) { spaceship->position.x = SWIDTH; } if (spaceship->position.x > SWIDTH) { spaceship->position.x = 0; } if (spaceship->position.y < 0) { spaceship->position.y = SHEIGHT; } if (spaceship->position.y > SHEIGHT) { spaceship->position.y = 0; } }
/** * {@inheritDoc} */ list<Polar> APF::findLocalMinima(list<Polar> points) { // List of local minima that have been found. list<Polar> localMinima; // Whether the last angle's distance was smaller than the current one. bool lastWasCloser = false; // The previous point; init to an invalid point. Polar prev = {-1.0, 0.0}; for (list<Polar>::iterator i = points.begin(); i != points.end(); i++) { Polar p = *i; // If p is a valid point and closer than the previous one. if (p.isValid() && (!prev.isValid() || p.d < prev.d)) { // We mark it as a potential candidate for being a local minima. lastWasCloser = true; } else { // Otherwise if i-1 was closer than i-2, i-1 is a local minima. if (lastWasCloser) { localMinima.push_back(prev); } lastWasCloser = false;; } prev = p; } // Check in case the last point was a minima. if (lastWasCloser) { localMinima.push_back(prev); } return localMinima; }
void PreFlightGliderPage::slotUpdateWingLoad( int value ) { Q_UNUSED(value) Glider* glider = m_gliderList->getSelectedGlider(); if( glider == 0 || glider->polar() == 0 || glider->polar()->wingArea() == 0.0 ) { // Clear label m_wingLoad->setText(""); return; } Polar* polar = glider->polar(); double wload = 0.0; if( polar->grossWeight() ) { wload = (polar->grossWeight() + m_edtLoad->value() + m_edtWater->value()) / polar->wingArea(); } QString msg = ""; if( wload ) { msg = QString("%1 Kg/m").arg( wload, 0, 'f', 1 ) + QChar(Qt::Key_twosuperior); } m_wingLoad->setText(msg); }
TEST_F( PolarTest, computeAverageAndStddev) { Polar<double> P; double mean, stddev; P.getPolarFromCartesianBSpline(mulDouble,0,1); P.computeAverageAndStddev(mean,stddev); EXPECT_NEAR(mean,1.886528450043468,XMIPP_EQUAL_ACCURACY); EXPECT_NEAR(stddev,0.49643800057938808,XMIPP_EQUAL_ACCURACY); }
void polarList::stats(void) { qWarning() << "Nb polar: " << polars.count(); QListIterator<Polar*> i (polars); int k=0; while(i.hasNext()) { Polar * item = i.next(); qWarning() << k << ": " << item->getName() << "(nb used=" << item->nbUsed << ")"; k++; } }
void Vector2::set( const Polar& p ) { __X = p.radius * cos(p.theta); __Y = p.radius * sin(p.theta) GEOM_ASSERT(p.isValid()); GEOM_ASSERT(isValid()); }
void polarList::releasePolar(QString fname) { QListIterator<Polar*> i (polars); while(i.hasNext()) { Polar * item = i.next(); if(item->getName()==fname) { item->nbUsed--; if(item->nbUsed==0) { polars.removeAll(item); delete item; } break; } } }
PolarDialog::PolarDialog( Polar& polar, QWidget* parent) : QWidget(parent), _polar(polar) { setWindowFlags( Qt::Tool ); setWindowModality( Qt::WindowModal ); setAttribute(Qt::WA_DeleteOnClose); if( _globalMainWindow ) { // Resize the window to the same size as the main window has. That will // completely hide the parent window. resize( _globalMainWindow->size() ); } QPalette palette; palette.setColor(backgroundRole(), Qt::white); setPalette(palette); setWindowTitle ( polar.name() + tr(" - Mouse click to Close") ); QShortcut* rcUp = new QShortcut(this); QShortcut* rcDown = new QShortcut(this); QShortcut* rcShiftUp = new QShortcut(this); QShortcut* rcShiftDown = new QShortcut(this); QShortcut* rcLeft = new QShortcut(this); QShortcut* rcRight = new QShortcut(this); QShortcut* rcSpace = new QShortcut(this); QShortcut* rcReturn = new QShortcut(this); rcUp->setKey (Qt::Key_Up); rcDown->setKey (Qt::Key_Down); rcShiftUp->setKey (Qt::Key_Up + Qt::SHIFT); rcShiftDown->setKey (Qt::Key_Down + Qt::SHIFT); rcLeft->setKey (Qt::Key_Left); rcRight->setKey (Qt::Key_Right); rcSpace->setKey (Qt::Key_Space); rcReturn->setKey (Qt::Key_Return); connect(rcUp, SIGNAL(activated()), this, SLOT(slot_keyup())); connect(rcDown, SIGNAL(activated()), this, SLOT(slot_keydown())); connect(rcShiftUp, SIGNAL(activated()), this, SLOT(slot_shiftkeyup())); connect(rcShiftDown,SIGNAL(activated()), this, SLOT(slot_shiftkeydown())); connect(rcLeft, SIGNAL(activated()), this, SLOT(slot_keyleft())); connect(rcRight, SIGNAL(activated()), this, SLOT(slot_keyright())); connect(rcSpace, SIGNAL(activated()), this, SLOT(slot_keyhome())); connect(rcReturn, SIGNAL(activated()), this, SLOT(slot_keyreturn())); setVisible(true ); }
void polarList::loadPolars(void) { isLoading=true; while(loadList.count()!=0) { QString fname=loadList.takeFirst(); //qWarning() << "loop on " << fname; Polar * res=NULL; QListIterator<Polar*> i (polars); while(i.hasNext()) { Polar * item = i.next(); if(item->getName()==fname) { //qWarning() << "polar already loaded"; res=item; item->nbUsed++; break; } } if(!res) { //qWarning() << "loading polar from disk"; res = new Polar(fname,mainWindow); if(res && res->isLoaded()) { res->nbUsed++; polars.append(res); } else res=NULL; } if(res==NULL) qWarning() << "Polar not found: " << fname; //qWarning() << "Sending polar " << fname; emit polarLoaded(fname,res); } isLoading=false; }
int main (int argc, char** argv) try { //Function::very_verbose = true; Function::verbose = true; cerr << "Instantiating BasisRule<7,Complex2>" << endl; BasisRule<7, Complex2> basis; cerr << "Instantiating Polar" << endl; Polar polar; cerr << "Calling BasisRule<7,Complex2>::set_model" << endl; basis.set_model (&polar); if (basis.get_nparam() != 7 + polar.get_nparam()) { cerr << "BasisRule<7,Complex2>::get_nparam = " << basis.get_nparam() << " != " << 7 + polar.get_nparam() << endl; return -1; } basis.set_param (0, 1.0); basis.set_param (1, 0.1); basis.set_param (2, 0.2); basis.set_param (3, 0.3); basis.set_param (4, 0.1); basis.set_param (5, 0.2); basis.set_param (6, 0.3); vector< Jones<double> > grad; Jones<double> result = basis.evaluate (&grad); if (result == 0.0) { cerr << "result = " << result << endl; return -1; } if (grad.size() != basis.get_nparam()) { cerr << "gradient size = " << grad.size() << " != BasisRule<7,Complex2>::get_nparam = " << basis.get_nparam() << endl; return -1; } for (unsigned i=0; i < 7; i++) if (grad[i] != grad[i+7]) { cerr << "gradient[" << i << "] = " << grad[i] << " != " "gradient[" << i+7 << "] = " << grad[i+7] << endl; return -1; } Matrix<7,7,double> xform; matrix_identity (xform); basis.set_transformation (xform); cerr << "BasisRule template passes all tests" << endl; return 0; } catch (Error& error) { cerr << error << endl; return -1; }
void BoatDialog::OnAddPolar( wxCommandEvent& event ) { wxFileConfig *pConf = GetOCPNConfigObject(); pConf->SetPath ( _T( "/PlugIns/WeatherRouting/BoatDialog" ) ); wxString path; pConf->Read ( _T ( "FilePath" ), &path, *GetpSharedDataLocation() + _T("plugins/weather_routing_pi/data/polars")); path = wxFileName(path).GetPath(); wxFileDialog openDialog ( this, _( "Select Polar File" ), path, wxT ( "" ), wxT ( "CSV, POL, TXT (*.csv, *.pol, *.txt)|*.CSV;*.csv;*.csv.gz;*.csv.bz2;*.POL;*.pol;*.pol.gz;*.pol.bz2;*.TXT;*.txt;*.txt.gz;*.txt.bz2|All files (*.*)|*.*" ), wxFD_OPEN | wxFD_MULTIPLE ); if( openDialog.ShowModal() != wxID_OK ) return; pConf->Write( _T ( "FilePath" ), openDialog.GetPath()); wxArrayString paths; openDialog.GetPaths(paths); bool generate = false, existed = true; for(unsigned int i=0; i<paths.GetCount(); i++) { wxString filename = paths[i], message; Polar polar; for(unsigned int j=0; j<m_Boat.Polars.size(); j++) if(m_Boat.Polars[j].FileName == filename) goto skip; existed = wxFileName::Exists(filename); // write dummy file if(!existed) { wxFile file; if(file.Open(filename, wxFile::write)) file.Write(dummy_polar); } if(polar.Open(filename, message)) { m_Boat.Polars.push_back(polar); RepopulatePolars(); m_lPolars->SetItemState(m_Boat.Polars.size()-1, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); generate = true; } else { wxMessageDialog md(this, message, _("OpenCPN Weather Routing Plugin"), wxICON_ERROR | wxOK ); md.ShowModal(); } skip:; } if(generate) GenerateCrossOverChart(); if(!existed) OnEditPolar(event); }
/* * https://github.com/LK8000/LK8000/tree/master/Common/Distribution/LK8000/_Polars * * Format explanation: all lines starting with a * are comments and you can also have empty lines * * Field 1: Gross weight of the glider, excluded ballast, when the values were measured * Field 2: Max ballast you can load (water). It will add wing loading, separately * Field 3-4, 5-6, 7-8 are couples of speed,sink rate in km/h and m/s . * these values are used to create an interpolated curve of sink rates * Field 9: NEW! Normally winpilot does not have this value. Put here at all cost the glider * surface area in squared meters (m2). If the polar curve you are using does not have * this value, go on wikipedia to find the wing area for that glider and add it after a comma. * * Here is the REAL polar used internally, that you have to create or change, for a glider * that during test flight was weighting 330kg including pilots and everything, that can load * extra 90 liters of water ballast, that at 75km/h has a sink rate of 0.7 m/s , at 93 km/h of 0,74 * at 185 km/h sinks at 3.1 m/s and finally that has a wing surface of 10.6 m2. * Thus, the polar was calculated with a default wing loading of 31.1 kg/m2 * So this is an example * * 330, 90, 75.0, -0.7, 93.0, -0.74, 185.00, -3.1, 10.6 * * Speed Astir.plr file content * * LK8000 polar for: Speed Astir * MassDryGross[kg], MaxWaterBallast[liters], Speed1[km/h], Sink1[m/s], Speed2, Sink2, Speed3, Sink3, WingArea[m2] * 351, 90, 90, -0.63, 105, -0.72, 157, -2.00, 11.5 // BestLD40@105 * */ bool GliderEditorNumPad::readLK8000PolarFile( const QString& fileName, Polar& polar ) { QFile polarFile( fileName ); if( polarFile.exists() == false ) { qWarning() << "readLK8000PolarFile:" << fileName << "does not exists!"; return false; } if( polarFile.open(QIODevice::ReadOnly) == false ) { qWarning() << "readLK8000PolarFile:" << fileName << "is not readable!"; return false; } // We take the polar file name as gilder type name. The type description // is sometimes missing in the file. QString name = QFileInfo(fileName).completeBaseName(); polar.setName( name ); if( name.contains( "PAS") ) { // Polar of a double seater was selected polar.setSeats( 2 ); } QTextStream stream( &polarFile ); int lineNo = 0; while( !stream.atEnd() ) { QString line = stream.readLine().trimmed(); lineNo++; if( line.isEmpty() || line.startsWith("*") || line.startsWith("//") ) { continue; } // Lines can contain at their right end C++ comments. This part must be // removed first. QStringList items = line.split( "//" ); items = items.at(0).split( ",", QString::SkipEmptyParts ); if( items.size() < 9 ) { qWarning() << "Polar file" << QFileInfo(fileName).fileName() << "line" << lineNo << "contains to less items:" << line; polarFile.close(); return false; } // Extract data, Example is from Spped Astir. // MassDryGross[kg], MaxWaterBallast[liters], Speed1[km/h], Sink1[m/s], Speed2, Sink2, Speed3, Sink3, WingArea[m2] // 351, 90, 90, -0.63, 105, -0.72, 157, -2.00, 11.5 // BestLD40@105 for( int i = 0; i < 9; i++ ) { bool ok; double dv = items.at(i).trimmed().toDouble(&ok); Speed speed; if( ! ok ) { polarFile.close(); return false; } switch(i) { case 0: polar.setGrossWeight( dv ); break; case 1: polar.setMaxWater( rint(dv) ); break; case 2: speed.setKph( dv ); polar.setV1( speed ); break; case 3: speed.setMps( dv ); polar.setW1( speed ); break; case 4: speed.setKph( dv ); polar.setV2( speed ); break; case 5: speed.setMps( dv ); polar.setW2( speed ); break; case 6: speed.setKph( dv ); polar.setV3( speed ); break; case 7: speed.setMps( dv ); polar.setW3( speed ); break; case 8: polar.setWingArea( dv ); break; default: break; } } polar.recalculatePolarData(); polarFile.close(); return true; } polarFile.close(); qWarning() << "readLK8000PolarFile:" << fileName << "contains no polar data!"; return false; }
Vector2::Vector2( const Polar& p ) : Tuple2<real_t>(p.radius * cos(p.theta), p.radius * sin(p.theta)) { GEOM_ASSERT(p.isValid()); GEOM_ASSERT(isValid()); }