2010-07-09 05:05:40 -04:00
|
|
|
/*
|
|
|
|
open source routing machine
|
|
|
|
Copyright (C) Dennis Luxen, 2010
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU AFFERO General Public License as published by
|
|
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
This program 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 Affero General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
or see http://www.gnu.org/licenses/agpl.txt.
|
2010-08-31 10:00:40 -04:00
|
|
|
*/
|
2010-07-09 05:05:40 -04:00
|
|
|
|
|
|
|
#define VERBOSE(x) x
|
|
|
|
#define VERBOSE2(x)
|
|
|
|
|
2010-08-31 10:00:40 -04:00
|
|
|
#ifdef NDEBUG
|
|
|
|
#undef VERBOSE
|
|
|
|
#undef VERBOSE2
|
|
|
|
#endif
|
|
|
|
|
2011-11-30 13:48:01 -05:00
|
|
|
#include <boost/foreach.hpp>
|
2012-02-28 10:25:01 -05:00
|
|
|
#include <boost/property_tree/ptree.hpp>
|
|
|
|
#include <boost/property_tree/ini_parser.hpp>
|
2011-11-30 13:48:01 -05:00
|
|
|
|
2010-07-09 05:05:40 -04:00
|
|
|
#include <fstream>
|
|
|
|
#include <istream>
|
|
|
|
#include <iostream>
|
|
|
|
#include <cstring>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
2012-02-17 02:15:33 -05:00
|
|
|
#include "Algorithms/CRC32.h"
|
2011-11-25 15:54:19 -05:00
|
|
|
#include "Util/OpenMPReplacement.h"
|
2010-07-09 05:05:40 -04:00
|
|
|
#include "typedefs.h"
|
|
|
|
#include "Contractor/Contractor.h"
|
2011-11-09 10:12:05 -05:00
|
|
|
#include "Contractor/EdgeBasedGraphFactory.h"
|
2011-01-09 16:42:27 -05:00
|
|
|
#include "DataStructures/BinaryHeap.h"
|
2011-11-09 10:12:05 -05:00
|
|
|
#include "DataStructures/ExtractorStructs.h"
|
2010-08-31 10:00:40 -04:00
|
|
|
#include "DataStructures/NNGrid.h"
|
2012-04-25 04:51:16 -04:00
|
|
|
#include "DataStructures/QueryEdge.h"
|
2011-01-09 16:42:27 -05:00
|
|
|
#include "Util/BaseConfiguration.h"
|
|
|
|
#include "Util/InputFileUtil.h"
|
|
|
|
#include "Util/GraphLoader.h"
|
2011-11-26 10:42:15 -05:00
|
|
|
#include "Util/OpenMPReplacement.h"
|
2010-08-31 10:00:40 -04:00
|
|
|
|
2010-07-09 05:05:40 -04:00
|
|
|
using namespace std;
|
|
|
|
|
2012-04-25 04:51:16 -04:00
|
|
|
typedef QueryEdge::EdgeData EdgeData;
|
2011-01-14 11:54:42 -05:00
|
|
|
typedef DynamicGraph<EdgeData>::InputEdge InputEdge;
|
2010-10-01 12:30:35 -04:00
|
|
|
typedef StaticGraph<EdgeData>::InputEdge StaticEdge;
|
2011-01-09 16:42:27 -05:00
|
|
|
typedef BaseConfiguration ContractorConfiguration;
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2012-04-14 08:38:13 -04:00
|
|
|
std::vector<NodeInfo> internalToExternalNodeMapping;
|
2011-11-25 06:02:52 -05:00
|
|
|
std::vector<_Restriction> inputRestrictions;
|
2012-01-02 07:09:20 -05:00
|
|
|
std::vector<NodeID> bollardNodes;
|
|
|
|
std::vector<NodeID> trafficLightNodes;
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2011-01-14 11:54:42 -05:00
|
|
|
int main (int argc, char *argv[]) {
|
2011-11-14 13:36:31 -05:00
|
|
|
if(argc < 3) {
|
2011-11-30 13:48:01 -05:00
|
|
|
ERR("usage: " << std::endl << argv[0] << " <osrm-data> <osrm-restrictions>");
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
2011-01-09 16:42:27 -05:00
|
|
|
|
2012-02-13 09:21:51 -05:00
|
|
|
double startupTime = get_timestamp();
|
2011-03-18 06:55:18 -04:00
|
|
|
unsigned numberOfThreads = omp_get_num_procs();
|
2011-12-13 09:30:52 -05:00
|
|
|
std::string SRTM_ROOT;
|
2011-03-18 06:55:18 -04:00
|
|
|
if(testDataFile("contractor.ini")) {
|
|
|
|
ContractorConfiguration contractorConfig("contractor.ini");
|
|
|
|
if(atoi(contractorConfig.GetParameter("Threads").c_str()) != 0 && (unsigned)atoi(contractorConfig.GetParameter("Threads").c_str()) <= numberOfThreads)
|
|
|
|
numberOfThreads = (unsigned)atoi( contractorConfig.GetParameter("Threads").c_str() );
|
2011-12-13 09:30:52 -05:00
|
|
|
if(0 < contractorConfig.GetParameter("SRTM").size() )
|
|
|
|
SRTM_ROOT = contractorConfig.GetParameter("SRTM");
|
2011-03-18 06:55:18 -04:00
|
|
|
}
|
2011-12-13 09:30:52 -05:00
|
|
|
if(0 != SRTM_ROOT.size())
|
|
|
|
INFO("Loading SRTM from/to " << SRTM_ROOT);
|
2011-03-18 06:55:18 -04:00
|
|
|
omp_set_num_threads(numberOfThreads);
|
2011-01-09 16:42:27 -05:00
|
|
|
|
2012-01-02 07:09:20 -05:00
|
|
|
INFO("Using restrictions from file: " << argv[2]);
|
|
|
|
std::ifstream restrictionsInstream(argv[2], ios::binary);
|
2012-03-01 09:58:10 -05:00
|
|
|
if(!restrictionsInstream.good()) {
|
|
|
|
ERR("Could not access <osrm-restrictions> files");
|
|
|
|
}
|
2012-01-02 07:09:20 -05:00
|
|
|
_Restriction restriction;
|
|
|
|
unsigned usableRestrictionsCounter(0);
|
|
|
|
restrictionsInstream.read((char*)&usableRestrictionsCounter, sizeof(unsigned));
|
|
|
|
for(unsigned i = 0; i < usableRestrictionsCounter; ++i) {
|
|
|
|
restrictionsInstream.read((char *)&(restriction), sizeof(_Restriction));
|
|
|
|
inputRestrictions.push_back(restriction);
|
|
|
|
}
|
|
|
|
restrictionsInstream.close();
|
|
|
|
|
|
|
|
|
2012-04-25 10:07:43 -04:00
|
|
|
std::ifstream in;
|
|
|
|
in.open (argv[1], std::ifstream::in | std::ifstream::binary);
|
2010-07-09 05:05:40 -04:00
|
|
|
if (!in.is_open()) {
|
2011-11-30 13:48:01 -05:00
|
|
|
ERR("Cannot open " << argv[1]);
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
2011-11-09 10:12:05 -05:00
|
|
|
|
2012-04-25 04:51:16 -04:00
|
|
|
char nodeOut[1024]; strcpy(nodeOut, argv[1]); strcat(nodeOut, ".nodes");
|
|
|
|
char edgeOut[1024]; strcpy(edgeOut, argv[1]); strcat(edgeOut, ".edges");
|
|
|
|
char graphOut[1024]; strcpy(graphOut, argv[1]); strcat(graphOut, ".hsgr");
|
2011-11-30 14:00:05 -05:00
|
|
|
char ramIndexOut[1024]; strcpy(ramIndexOut, argv[1]); strcat(ramIndexOut, ".ramIndex");
|
|
|
|
char fileIndexOut[1024]; strcpy(fileIndexOut, argv[1]); strcat(fileIndexOut, ".fileIndex");
|
|
|
|
char levelInfoOut[1024]; strcpy(levelInfoOut, argv[1]); strcat(levelInfoOut, ".levels");
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2011-11-25 06:02:52 -05:00
|
|
|
std::vector<ImportEdge> edgeList;
|
2012-04-14 08:38:13 -04:00
|
|
|
NodeID nodeBasedNodeNumber = readBinaryOSRMGraphFromStream(in, edgeList, bollardNodes, trafficLightNodes, &internalToExternalNodeMapping, inputRestrictions);
|
2011-11-14 13:36:31 -05:00
|
|
|
in.close();
|
2012-01-02 07:09:20 -05:00
|
|
|
INFO("Loaded " << inputRestrictions.size() << " restrictions, " << bollardNodes.size() << " bollard nodes, " << trafficLightNodes.size() << " traffic lights");
|
2011-11-14 13:36:31 -05:00
|
|
|
|
2012-02-28 10:25:01 -05:00
|
|
|
if(!testDataFile("speedprofile.ini")) {
|
|
|
|
ERR("Need speedprofile.ini to apply traffic signal penalty");
|
|
|
|
}
|
|
|
|
boost::property_tree::ptree speedProfile;
|
|
|
|
boost::property_tree::ini_parser::read_ini("speedprofile.ini", speedProfile);
|
2012-04-25 10:07:43 -04:00
|
|
|
|
|
|
|
/***
|
|
|
|
* Building an edge-expanded graph from node-based input an turn restrictions
|
|
|
|
*/
|
|
|
|
|
2012-04-14 08:38:13 -04:00
|
|
|
EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile, SRTM_ROOT);
|
2011-11-25 06:02:52 -05:00
|
|
|
std::vector<ImportEdge>().swap(edgeList);
|
|
|
|
|
2011-11-14 13:36:31 -05:00
|
|
|
edgeBasedGraphFactory->Run();
|
2012-04-14 08:50:25 -04:00
|
|
|
std::vector<_Restriction>().swap(inputRestrictions);
|
2012-04-25 10:07:43 -04:00
|
|
|
std::vector<NodeID>().swap(bollardNodes);
|
|
|
|
std::vector<NodeID>().swap(trafficLightNodes);
|
2012-02-13 09:21:51 -05:00
|
|
|
NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes();
|
2011-11-14 13:36:31 -05:00
|
|
|
std::vector<EdgeBasedEdge> edgeBasedEdgeList;
|
|
|
|
edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList);
|
|
|
|
|
2012-04-25 10:07:43 -04:00
|
|
|
stxxl::vector<EdgeBasedEdge> externalEdgeBasedEdgeList;
|
|
|
|
BOOST_FOREACH(EdgeBasedEdge & edge, edgeBasedEdgeList) {
|
|
|
|
externalEdgeBasedEdgeList.push_back(edge);
|
|
|
|
}
|
|
|
|
std::vector<EdgeBasedEdge>().swap(edgeBasedEdgeList);
|
|
|
|
|
|
|
|
/***
|
|
|
|
* Writing info on original (node-based) nodes
|
|
|
|
*/
|
|
|
|
|
|
|
|
INFO("writing node map ...");
|
|
|
|
std::ofstream mapOutFile(nodeOut, std::ios::binary);
|
|
|
|
mapOutFile.write((char *)&(internalToExternalNodeMapping[0]), internalToExternalNodeMapping.size()*sizeof(NodeInfo));
|
|
|
|
mapOutFile.close();
|
|
|
|
std::vector<NodeInfo>().swap(internalToExternalNodeMapping);
|
|
|
|
|
|
|
|
/***
|
|
|
|
* Writing info on original (node-based) edges
|
|
|
|
*/
|
|
|
|
INFO("writing info on original edges");
|
2012-04-25 04:51:16 -04:00
|
|
|
std::vector<OriginalEdgeData> originalEdgeData;
|
|
|
|
edgeBasedGraphFactory->GetOriginalEdgeData(originalEdgeData);
|
|
|
|
|
|
|
|
std::ofstream oedOutFile(edgeOut, std::ios::binary);
|
|
|
|
unsigned numberOfOrigEdges = originalEdgeData.size();
|
|
|
|
oedOutFile.write((char*)&numberOfOrigEdges, sizeof(unsigned));
|
|
|
|
oedOutFile.write((char*)&(originalEdgeData[0]), originalEdgeData.size()*sizeof(OriginalEdgeData));
|
|
|
|
oedOutFile.close();
|
|
|
|
std::vector<OriginalEdgeData>().swap(originalEdgeData);
|
|
|
|
|
2011-11-14 13:36:31 -05:00
|
|
|
std::vector<EdgeBasedGraphFactory::EdgeBasedNode> nodeBasedEdgeList;
|
|
|
|
edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList);
|
2012-04-12 13:35:47 -04:00
|
|
|
delete edgeBasedGraphFactory;
|
2012-02-13 09:21:51 -05:00
|
|
|
double expansionHasFinishedTime = get_timestamp() - startupTime;
|
|
|
|
|
2012-04-25 10:07:43 -04:00
|
|
|
/***
|
|
|
|
* Building grid-like nearest-neighbor data structure
|
|
|
|
*/
|
|
|
|
|
2011-11-30 13:48:01 -05:00
|
|
|
INFO("building grid ...");
|
2012-04-25 10:07:43 -04:00
|
|
|
WritableGrid * writeableGrid = new WritableGrid();
|
2011-12-16 08:05:30 -05:00
|
|
|
writeableGrid->ConstructGrid(nodeBasedEdgeList, ramIndexOut, fileIndexOut);
|
2012-04-12 13:35:47 -04:00
|
|
|
delete writeableGrid;
|
2012-02-17 02:15:33 -05:00
|
|
|
CRC32 crc32;
|
|
|
|
unsigned crc32OfNodeBasedEdgeList = crc32((char *)&(nodeBasedEdgeList[0]), nodeBasedEdgeList.size()*sizeof(EdgeBasedGraphFactory::EdgeBasedNode));
|
2011-11-30 14:00:05 -05:00
|
|
|
std::vector<EdgeBasedGraphFactory::EdgeBasedNode>().swap(nodeBasedEdgeList);
|
2011-11-14 13:36:31 -05:00
|
|
|
|
2012-04-25 10:07:43 -04:00
|
|
|
/***
|
|
|
|
* Contracting the edge-expanded graph
|
|
|
|
*/
|
2011-11-14 13:36:31 -05:00
|
|
|
|
2011-11-30 13:48:01 -05:00
|
|
|
INFO("initializing contractor");
|
2012-04-25 10:07:43 -04:00
|
|
|
Contractor* contractor = new Contractor( edgeBasedNodeNumber, externalEdgeBasedEdgeList );
|
2011-11-09 10:12:05 -05:00
|
|
|
double contractionStartedTimestamp(get_timestamp());
|
2010-07-09 05:05:40 -04:00
|
|
|
contractor->Run();
|
2011-11-09 10:12:05 -05:00
|
|
|
INFO("Contraction took " << get_timestamp() - contractionStartedTimestamp << " sec");
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2012-04-25 04:51:16 -04:00
|
|
|
std::vector< QueryEdge > contractedEdgeList;
|
2012-04-12 13:35:47 -04:00
|
|
|
contractor->GetEdges( contractedEdgeList );
|
2012-01-25 18:53:53 -05:00
|
|
|
delete contractor;
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2012-04-25 10:07:43 -04:00
|
|
|
/***
|
|
|
|
* Sorting contracted edges in a way that the static query graph can read some in in-place.
|
|
|
|
*/
|
|
|
|
|
2011-12-15 11:48:00 -05:00
|
|
|
INFO("Building Node Array");
|
2012-04-12 13:35:47 -04:00
|
|
|
sort(contractedEdgeList.begin(), contractedEdgeList.end());
|
2011-12-15 11:48:00 -05:00
|
|
|
unsigned numberOfNodes = 0;
|
2012-04-12 13:35:47 -04:00
|
|
|
unsigned numberOfEdges = contractedEdgeList.size();
|
2011-12-15 11:48:00 -05:00
|
|
|
INFO("Serializing compacted graph");
|
2012-04-25 04:51:16 -04:00
|
|
|
ofstream edgeOutFile(graphOut, ios::binary);
|
2011-12-15 11:48:00 -05:00
|
|
|
|
2012-04-25 04:51:16 -04:00
|
|
|
BOOST_FOREACH(QueryEdge & edge, contractedEdgeList) {
|
2011-12-15 11:48:00 -05:00
|
|
|
if(edge.source > numberOfNodes) {
|
|
|
|
numberOfNodes = edge.source;
|
|
|
|
}
|
|
|
|
if(edge.target > numberOfNodes) {
|
|
|
|
numberOfNodes = edge.target;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
numberOfNodes+=1;
|
|
|
|
|
|
|
|
std::vector< StaticGraph<EdgeData>::_StrNode > _nodes;
|
2012-01-26 17:03:39 -05:00
|
|
|
_nodes.resize( numberOfNodes + 1 );
|
2011-12-15 11:48:00 -05:00
|
|
|
|
|
|
|
StaticGraph<EdgeData>::EdgeIterator edge = 0;
|
|
|
|
StaticGraph<EdgeData>::EdgeIterator position = 0;
|
|
|
|
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node <= numberOfNodes; ++node ) {
|
|
|
|
StaticGraph<EdgeData>::EdgeIterator lastEdge = edge;
|
2012-04-12 13:35:47 -04:00
|
|
|
while ( edge < numberOfEdges && contractedEdgeList[edge].source == node )
|
2011-12-15 11:48:00 -05:00
|
|
|
++edge;
|
|
|
|
_nodes[node].firstEdge = position; //=edge
|
|
|
|
position += edge - lastEdge; //remove
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
2012-03-05 08:48:59 -05:00
|
|
|
++numberOfNodes;
|
2011-12-15 11:48:00 -05:00
|
|
|
//Serialize numberOfNodes, nodes
|
2012-02-17 02:15:33 -05:00
|
|
|
edgeOutFile.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned));
|
2011-12-15 11:48:00 -05:00
|
|
|
edgeOutFile.write((char*) &numberOfNodes, sizeof(unsigned));
|
2012-03-05 08:48:59 -05:00
|
|
|
edgeOutFile.write((char*) &_nodes[0], sizeof(StaticGraph<EdgeData>::_StrNode)*(numberOfNodes));
|
2011-12-15 11:48:00 -05:00
|
|
|
//Serialize number of Edges
|
|
|
|
edgeOutFile.write((char*) &position, sizeof(unsigned));
|
2012-03-05 08:48:59 -05:00
|
|
|
--numberOfNodes;
|
2011-12-15 11:48:00 -05:00
|
|
|
edge = 0;
|
2012-02-13 09:21:51 -05:00
|
|
|
int usedEdgeCounter = 0;
|
2011-12-15 11:48:00 -05:00
|
|
|
StaticGraph<EdgeData>::_StrEdge currentEdge;
|
|
|
|
for ( StaticGraph<EdgeData>::NodeIterator node = 0; node < numberOfNodes; ++node ) {
|
|
|
|
for ( StaticGraph<EdgeData>::EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) {
|
2012-04-12 13:35:47 -04:00
|
|
|
assert(node != contractedEdgeList[edge].target);
|
|
|
|
currentEdge.target = contractedEdgeList[edge].target;
|
|
|
|
currentEdge.data = contractedEdgeList[edge].data;
|
2011-12-15 11:48:00 -05:00
|
|
|
if(currentEdge.data.distance <= 0) {
|
2012-04-12 13:35:47 -04:00
|
|
|
INFO("Edge: " << i << ",source: " << contractedEdgeList[edge].source << ", target: " << contractedEdgeList[edge].target << ", dist: " << currentEdge.data.distance);
|
2011-12-15 11:48:00 -05:00
|
|
|
ERR("Failed at edges of node " << node << " of " << numberOfNodes);
|
|
|
|
}
|
|
|
|
//Serialize edges
|
|
|
|
edgeOutFile.write((char*) ¤tEdge, sizeof(StaticGraph<EdgeData>::_StrEdge));
|
|
|
|
++edge;
|
2012-02-13 09:21:51 -05:00
|
|
|
++usedEdgeCounter;
|
2011-12-15 11:48:00 -05:00
|
|
|
}
|
|
|
|
}
|
2012-02-13 09:21:51 -05:00
|
|
|
double endTime = (get_timestamp() - startupTime);
|
|
|
|
INFO("Expansion : " << (nodeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< (edgeBasedNodeNumber/expansionHasFinishedTime) << " edges/sec");
|
|
|
|
INFO("Contraction: " << (edgeBasedNodeNumber/expansionHasFinishedTime) << " nodes/sec and "<< usedEdgeCounter/endTime << " edges/sec");
|
|
|
|
|
2010-07-09 05:05:40 -04:00
|
|
|
edgeOutFile.close();
|
2012-04-12 13:35:47 -04:00
|
|
|
//cleanedEdgeList.clear();
|
2011-12-15 11:48:00 -05:00
|
|
|
_nodes.clear();
|
2011-11-30 13:48:01 -05:00
|
|
|
INFO("finished preprocessing");
|
2011-07-21 10:30:36 -04:00
|
|
|
return 0;
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|