[Marble-commits] KDE/kdeedu/marble/src/plugins/runner
Dennis Nienhüser
earthwings at gentoo.org
Mon Sep 6 20:20:16 CEST 2010
SVN commit 1172217 by nienhueser:
Use the new monav daemon to retrieve routes. It will run out of the box, given that
- MoNavD, the monav daemon, r225 or later is available in PATH
- A compatible monav map lies in ~/.local/share/marble/maps/earth/monav. Version 0.0.1 is not compatible. You only need the contraction hierarchies and gps grid files.
- A plugins.ini file with the content
[General]
router=Contraction Hierarchies
gpsLookup=GPS Grid
lies in the same dir.
signals.h (daemon socket interface) is taken from monav. It has a dual license for that purpose.
Note that the daemon uses little resources (map is not held in RAM) and can be left running in the background fine.
M +1 -1 CMakeLists.txt
M +57 -41 monav/MonavPlugin.cpp
M +0 -3 monav/MonavPlugin.h
M +60 -56 monav/MonavRunner.cpp
M +1 -1 monav/MonavRunner.h
A monav/signals.h [License: GPL (v3+) LGPL (v3+)]
--- trunk/KDE/kdeedu/marble/src/plugins/runner/CMakeLists.txt #1172216:1172217
@@ -14,6 +14,6 @@
#add_subdirectory( traveling-salesman )
# monav works, but you need a custom shell client
-#add_subdirectory( monav )
+add_subdirectory( monav )
add_subdirectory( yours )
--- trunk/KDE/kdeedu/marble/src/plugins/runner/monav/MonavPlugin.cpp #1172216:1172217
@@ -8,6 +8,7 @@
// Copyright 2010 Dennis Nienhüser <earthwings at gentoo.org>
//
+#include "signals.h"
#include "MonavPlugin.h"
#include "MonavRunner.h"
#include "MarbleDirs.h"
@@ -15,8 +16,8 @@
#include <QtCore/QProcess>
#include <QtCore/QDir>
-#include <QtCore/QMutexLocker>
#include <QtCore/QTimer>
+#include <QtNetwork/QLocalSocket>
namespace Marble
{
@@ -24,23 +25,66 @@
class MonavPluginPrivate
{
public:
- QProcess* m_monavProcess;
-
QDir m_mapDir;
- QMutex m_processMutex;
+ bool m_ownsServer;
- QTimer m_shutdownTimer;
+ MonavPluginPrivate();
- MonavPluginPrivate();
+ bool startDaemon();
+
+ void stopDaemon();
+
+ bool isDaemonRunning() const;
};
-MonavPluginPrivate::MonavPluginPrivate() : m_monavProcess( 0 )
+MonavPluginPrivate::MonavPluginPrivate() : m_ownsServer( false )
{
- m_shutdownTimer.setInterval( 30 * 1000 );
- m_shutdownTimer.setSingleShot( true );
+ // nothing to do
}
+bool MonavPluginPrivate::isDaemonRunning() const
+{
+ QLocalSocket socket;
+ socket.connectToServer( "MoNavD" );
+ return socket.waitForConnected();
+}
+
+bool MonavPluginPrivate::startDaemon()
+{
+ if ( !isDaemonRunning() ) {
+ QProcess process;
+ if ( process.startDetached( "MoNavD" ) ) {
+ m_ownsServer = true;
+
+ // Give MoNavD up to one second to set up its server
+ // Without that, the first route request would fail
+ for ( int i=0; i<10; ++i )
+ {
+ if ( isDaemonRunning() ) {
+ break;
+ }
+ usleep(100 * 1000);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ return true;
+}
+
+void MonavPluginPrivate::stopDaemon()
+{
+ if ( m_ownsServer ) {
+ m_ownsServer = false;
+ QProcess process;
+ process.startDetached( "MoNavD", QStringList() << "-t" );
+ }
+}
+
MonavPlugin::MonavPlugin( QObject *parent ) : RunnerPlugin( parent ), d( new MonavPluginPrivate )
{
setSupportedCelestialBodies( QStringList() << "earth" );
@@ -52,54 +96,26 @@
// Check installation
d->m_mapDir = QDir( MarbleDirs::localPath() + "/maps/earth/monav/" );
- bool haveMap = QFileInfo( d->m_mapDir, "Contraction Hierarchies" ).exists();
+ bool haveMap = QFileInfo( d->m_mapDir, "plugins.ini" ).exists();
setCapabilities( haveMap ? Routing : None );
-
- connect( &d->m_shutdownTimer, SIGNAL( timeout() ), this, SLOT( killProcess( ) ) );
}
MonavPlugin::~MonavPlugin()
{
- killProcess();
delete d;
}
MarbleAbstractRunner* MonavPlugin::newRunner() const
{
- QMutexLocker locker( &d->m_processMutex );
- if ( !d->m_monavProcess ) {
- d->m_monavProcess = new QProcess;
- d->m_monavProcess->start( "monav", QStringList() << "--pipe" << d->m_mapDir.absolutePath() );
-
- if ( !d->m_monavProcess->waitForStarted( 5000 ) )
- {
- mDebug() << "Couldn't start monav from the current PATH. Install it to retrieve routing results from monav.";
+ if ( !d->startDaemon() ) {
+ mDebug() << "Failed to connect to MoNavD daemon";
}
- }
- d->m_shutdownTimer.start();
- return new MonavRunner( d->m_monavProcess );
+ return new MonavRunner;
}
-void MonavPlugin::killProcess()
-{
- QMutexLocker locker( &d->m_processMutex );
-
- if ( d->m_monavProcess ) {
- QProcess* dying = d->m_monavProcess;
- d->m_monavProcess = 0;
- dying->closeWriteChannel();
- if ( !dying->waitForFinished( 1000 ) ) {
- dying->terminate();
- if ( !dying->waitForFinished( 1000 ) ) {
- mDebug() << "monav process did not terminate properly.";
}
- }
- }
-}
-}
-
Q_EXPORT_PLUGIN2( MonavPlugin, Marble::MonavPlugin )
#include "MonavPlugin.moc"
--- trunk/KDE/kdeedu/marble/src/plugins/runner/monav/MonavPlugin.h #1172216:1172217
@@ -30,9 +30,6 @@
virtual MarbleAbstractRunner* newRunner() const;
-private Q_SLOTS:
- void killProcess();
-
private:
MonavPluginPrivate* const d;
};
--- trunk/KDE/kdeedu/marble/src/plugins/runner/monav/MonavRunner.cpp #1172216:1172217
@@ -9,12 +9,16 @@
//
#include "MonavRunner.h"
+#include "signals.h"
+#include "MarbleDebug.h"
#include "MarbleDirs.h"
#include "routing/RouteRequest.h"
#include "GeoDataDocument.h"
#include <QtCore/QProcess>
+#include <QtCore/QTime>
+#include <QtNetwork/QLocalSocket>
namespace Marble
{
@@ -22,80 +26,88 @@
class MonavRunnerPrivate
{
public:
- QProcess* m_monavProcess;
+ QDir m_mapDir;
- MonavRunnerPrivate( QProcess* monav );
+ MonavRunnerPrivate();
- GeoDataLineString* retrieveWaypoints( const QString ¶ms );
+ GeoDataLineString* retrieveRoute( RouteRequest *route ) const;
- GeoDataDocument* createDocument( GeoDataLineString* routeWaypoints ) const;
-
- GeoDataLineString* parseMonavOutput( const QByteArray &content ) const;
+ GeoDataDocument* createDocument( GeoDataLineString* geometry ) const;
};
-MonavRunnerPrivate::MonavRunnerPrivate( QProcess* monav ) :
- m_monavProcess( monav )
+MonavRunnerPrivate::MonavRunnerPrivate() :
+ m_mapDir( MarbleDirs::localPath() + "/maps/earth/monav/" )
{
// nothing to do
}
-GeoDataLineString* MonavRunnerPrivate::retrieveWaypoints( const QString ¶ms )
+GeoDataLineString* MonavRunnerPrivate::retrieveRoute( RouteRequest *route ) const
{
- Q_ASSERT( m_monavProcess );
- m_monavProcess->write( params.toAscii() );
- QByteArray data;
- for ( int i=1; i<15; ++i ) {
- if ( m_monavProcess->bytesAvailable() ) {
- data += m_monavProcess->readAllStandardOutput();
- bool haveRoute = data.endsWith("\n\n");
- if ( haveRoute ) {
- return parseMonavOutput( data );
- }
- } else {
- ++i;
- usleep( 1000 * pow( 2, i ) );
- }
- }
+ GeoDataLineString* geometry = new GeoDataLineString;
- return 0;
-}
+ QLocalSocket socket;
+ socket.connectToServer( "MoNavD" );
+ if ( socket.waitForConnected() ) {
+ RoutingDaemonCommand command;
+ QVector<RoutingDaemonCoordinate> waypoints;
-GeoDataLineString* MonavRunnerPrivate::parseMonavOutput( const QByteArray &content ) const
+ for ( int i = 0; i < route->size(); ++i )
{
- GeoDataLineString* routeWaypoints = new GeoDataLineString;
+ RoutingDaemonCoordinate coordinate;
+ coordinate.longitude = route->at( i ).longitude( GeoDataCoordinates::Degree );
+ coordinate.latitude = route->at( i ).latitude( GeoDataCoordinates::Degree );
+ waypoints << coordinate;
+ }
- QStringList lines = QString::fromUtf8( content ).split( '\n' );
- foreach( const QString &line, lines )
+ command.dataDirectory = m_mapDir.absolutePath();
+ command.lookupRadius = 1500;
+ command.waypoints = waypoints;
+
+ command.post( &socket );
+ socket.flush();
+
+ RoutingDaemonResult reply;
+ if ( reply.read( &socket ) )
{
- QStringList fields = line.split( ';' );
- if ( fields.size() >= 2 )
+ switch (reply.type)
{
- qreal lat = fields.at( 0 ).trimmed().toDouble();
- qreal lon = fields.at( 1 ).trimmed().toDouble();
- GeoDataCoordinates coordinates( lon, lat, 0.0, GeoDataCoordinates::Degree );
- routeWaypoints->append( coordinates );
+ case RoutingDaemonResult::LoadFail:
+ mDebug() << "failed to load monav map from " << m_mapDir.absolutePath();
+ break;
+ case RoutingDaemonResult::RouteFail:
+ mDebug() << "failed to retrieve route from monav daemon";
+ break;
+ case RoutingDaemonResult::Success:
+ /** @todo: make use of reply.seconds, the estimated travel time */
+ for ( int i = 0; i < reply.path.size(); i++ ) {
+ qreal lon = reply.path[i].longitude;
+ qreal lat = reply.path[i].latitude;
+ GeoDataCoordinates coordinates( lon, lat, 0, GeoDataCoordinates::Degree );
+ geometry->append( coordinates );
}
+ break;
}
+ }
+ }
- return routeWaypoints;
+ return geometry;
}
-GeoDataDocument* MonavRunnerPrivate::createDocument( GeoDataLineString* routeWaypoints ) const
+GeoDataDocument* MonavRunnerPrivate::createDocument( GeoDataLineString *geometry ) const
{
- if ( !routeWaypoints || routeWaypoints->isEmpty() )
- {
+ if ( !geometry || geometry->isEmpty() ) {
return 0;
}
- GeoDataDocument* result = new GeoDataDocument();
+ GeoDataDocument* result = new GeoDataDocument;
GeoDataPlacemark* routePlacemark = new GeoDataPlacemark;
routePlacemark->setName( "Route" );
- routePlacemark->setGeometry( routeWaypoints );
+ routePlacemark->setGeometry( geometry );
result->append( routePlacemark );
QString name = "%1 %2 (Monav)";
QString unit = "m";
- qreal length = routeWaypoints->length( EARTH_RADIUS );
+ qreal length = geometry->length( EARTH_RADIUS );
if ( length >= 1000 )
{
length /= 1000.0;
@@ -105,10 +117,11 @@
return result;
}
-MonavRunner::MonavRunner( QProcess* monav, QObject *parent ) :
+MonavRunner::MonavRunner( QObject *parent ) :
MarbleAbstractRunner( parent ),
- d( new MonavRunnerPrivate( monav ) )
+ d( new MonavRunnerPrivate )
{
+ // nothing to do
}
MonavRunner::~MonavRunner()
@@ -123,17 +136,8 @@
void MonavRunner::retrieveRoute( RouteRequest *route )
{
- QString params;
- for ( int i = 0; i < route->size(); ++i )
- {
- double lon = route->at( i ).longitude( GeoDataCoordinates::Degree );
- double lat = route->at( i ).latitude( GeoDataCoordinates::Degree );
- params += QString( " --lat%1=%2" ).arg( i + 1 ).arg( lat, 0, 'f', 8 );
- params += QString( " --lon%1=%2" ).arg( i + 1 ).arg( lon, 0, 'f', 8 );
- }
-
- GeoDataLineString* wayPoints = d->retrieveWaypoints( params.trimmed() + "\n" );
- GeoDataDocument* result = d->createDocument( wayPoints );
+ GeoDataLineString* waypoints = d->retrieveRoute( route );
+ GeoDataDocument* result = d->createDocument( waypoints );
emit routeCalculated( result );
}
--- trunk/KDE/kdeedu/marble/src/plugins/runner/monav/MonavRunner.h #1172216:1172217
@@ -25,7 +25,7 @@
{
Q_OBJECT
public:
- explicit MonavRunner( QProcess* monav, QObject *parent = 0 );
+ explicit MonavRunner( QObject *parent = 0 );
~MonavRunner();
More information about the Marble-commits
mailing list