Пример #1
0
def calcDistAndLoops(rInfo, net, options):
    if net.hasInternal:
        rInfo.airDist = euclidean(
            net.getEdge(rInfo.edges[0]).getShape()[0],
            net.getEdge(rInfo.edges[-1]).getShape()[-1])
    else:
        rInfo.airDist = euclidean(
            net.getEdge(rInfo.edges[0]).getFromNode().getCoord(),
            net.getEdge(rInfo.edges[-1]).getToNode().getCoord())
    rInfo.length = sumolib.route.getLength(net, rInfo.edges)
    rInfo.airDistRatio = rInfo.length / rInfo.airDist
    rInfo.edgeLoop = False
    rInfo.nodeLoop = False
    if options.edge_loops:
        seen = set()
        for e in rInfo.edges:
            if e in seen:
                rInfo.edgeLoop = True
                rInfo.nodeLoop = True
                break
            seen.add(e)
    if options.node_loops and not rInfo.nodeLoop:
        seen = set()
        for e in rInfo.edges:
            t = net.getEdge(e).getToNode()
            if t in seen:
                rInfo.nodeLoop = True
                break
            seen.add(t)
Пример #2
0
def mapTrace(trace, net, delta, verbose=False, airDistFactor=2):
    """
    matching a list of 2D positions to consecutive edges in a network.
    The positions are assumed to be dense (i.e. covering each edge of the route) and in the correct order.
    """
    result = ()
    paths = {}
    lastPos = None
    if verbose:
        print("mapping trace with %s points" % len(trace))
    for pos in trace:
        newPaths = {}
        candidates = net.getNeighboringEdges(pos[0], pos[1], delta)
        if len(candidates) == 0 and verbose:
            print("Found no candidate edges for %s,%s" % pos)
        for edge, d in candidates:
            base = polygonOffsetWithMinimumDistanceToPoint(
                pos, edge.getShape())
            if paths:
                advance = euclidean(lastPos, pos)
                minDist = 1e400
                minPath = None
                for path, (dist, lastBase) in paths.items():
                    if dist < minDist:
                        if edge == path[-1]:
                            baseDiff = lastBase + advance - base
                            extension = ()
                        elif edge in path[-1].getOutgoing():
                            baseDiff = lastBase + advance - path[-1].getLength(
                            ) - base
                            extension = (edge, )
                        else:
                            extension, cost = net.getShortestPath(
                                path[-1], edge, airDistFactor * advance)
                            if extension is None:
                                airLineDist = euclidean(
                                    path[-1].getToNode().getCoord(),
                                    edge.getFromNode().getCoord())
                                baseDiff = lastBase + advance - path[
                                    -1].getLength() - base - airLineDist
                                extension = (edge, )
                            else:
                                baseDiff = lastBase + advance - base - cost + path[
                                    -1].getLength()
                                extension = extension[1:]
                        if dist + baseDiff * baseDiff < minDist:
                            minDist = dist + baseDiff * baseDiff
                            minPath = path + extension
                if minPath:
                    newPaths[minPath] = (minDist, base)
            else:
                newPaths[(edge, )] = (d * d, base)
        if not newPaths:
            if paths:
                result += _getMinPath(paths)
        paths = newPaths
        lastPos = pos
    if paths:
        return result + _getMinPath(paths)
    return result
Пример #3
0
def mapTrace(trace, net, delta, verbose=False, airDistFactor=2, fillGaps=False, gapPenalty=-1):
    """
    matching a list of 2D positions to consecutive edges in a network.
    The positions are assumed to be dense (i.e. covering each edge of the route) and in the correct order.
    """
    result = ()
    paths = {}
    lastPos = None
    if verbose:
        print("mapping trace with %s points" % len(trace))
    for pos in trace:
        newPaths = {}
        candidates = net.getNeighboringEdges(pos[0], pos[1], delta)
        if len(candidates) == 0 and verbose:
            print("Found no candidate edges for %s,%s" % pos)
        for edge, d in candidates:
            base = polygonOffsetWithMinimumDistanceToPoint(pos, edge.getShape())
            if paths:
                advance = euclidean(lastPos, pos)
                minDist = 1e400
                minPath = None
                for path, (dist, lastBase) in paths.items():
                    if dist < minDist:
                        if edge == path[-1]:
                            baseDiff = lastBase + advance - base
                            extension = ()
                        elif edge in path[-1].getOutgoing():
                            baseDiff = lastBase + advance - path[-1].getLength() - base
                            extension = (edge,)
                        else:
                            extension = None
                            if fillGaps:
                                extension, cost = net.getShortestPath(path[-1], edge, airDistFactor * advance)
                            if extension is None:
                                airLineDist = euclidean(
                                    path[-1].getToNode().getCoord(),
                                    edge.getFromNode().getCoord())
                                if gapPenalty < 0:
                                    gapPenalty = airLineDist
                                baseDiff = abs(lastBase + advance -
                                               path[-1].getLength() - base - airLineDist) + gapPenalty
                                extension = (edge,)
                            else:
                                baseDiff = lastBase + advance - base - cost + path[-1].getLength()
                                extension = extension[1:]
                        if dist + baseDiff * baseDiff < minDist:
                            minDist = dist + baseDiff * baseDiff
                            minPath = path + extension
                if minPath:
                    newPaths[minPath] = (minDist, base)
            else:
                newPaths[(edge,)] = (d * d, base)
        if not newPaths:
            if paths:
                result += _getMinPath(paths)
        paths = newPaths
        lastPos = pos
    if paths:
        return result + _getMinPath(paths)
    return result
Пример #4
0
def mapTrace(trace, net, delta, verbose=False):
    """
    matching a list of 2D positions to consecutive edges in a network
    """
    result = ()
    paths = {}
    if verbose:
        print("mapping trace with %s points" % len(trace))
    for pos in trace:
        newPaths = {}
        candidates = net.getNeighboringEdges(pos[0], pos[1], delta)
        if len(candidates) == 0 and verbose:
            print("Found no candidate edges for %s" % pos)
        for edge, d in candidates:
            base = polygonOffsetWithMinimumDistanceToPoint(
                pos, edge.getShape())
            if paths:
                advance = euclidean(lastPos, pos)
                minDist = 1e400
                minPath = None
                for path, (dist, lastBase) in paths.items():
                    if dist < minDist:
                        if edge == path[-1]:
                            baseDiff = lastBase + advance - base
                        elif edge in path[-1].getOutgoing():
                            baseDiff = lastBase + advance - path[-1].getLength(
                            ) - base
                        else:
                            airLineDist = euclidean(
                                path[-1].getToNode().getCoord(),
                                edge.getFromNode().getCoord())
                            baseDiff = lastBase + advance - path[-1].getLength(
                            ) - base - airLineDist
                        if dist + baseDiff * baseDiff < minDist:
                            minDist = dist + baseDiff * baseDiff
                            minPath = path if edge == path[-1] else path + (
                                edge, )
                if minPath:
                    newPaths[minPath] = (minDist, base)
            else:
                newPaths[(edge, )] = (d * d, base)
        if not newPaths:
            if paths:
                result += _getMinPath(paths)
        paths = newPaths
        lastPos = pos
    if paths:
        return result + _getMinPath(paths)
    return result
Пример #5
0
    def get_trip(self,
                 min_distance,
                 max_distance,
                 maxtries=100,
                 junctionTaz=False):
        for _ in range(maxtries):
            source_edge = self.source_generator.get()
            intermediate = [
                self.via_generator.get() for i in range(self.intermediate)
            ]
            sink_edge = self.sink_generator.get()
            if self.pedestrians:
                destCoord = sink_edge.getFromNode().getCoord()
            else:
                destCoord = sink_edge.getToNode().getCoord()

            coords = ([source_edge.getFromNode().getCoord()] +
                      [e.getFromNode().getCoord()
                       for e in intermediate] + [destCoord])
            distance = sum(
                [euclidean(p, q) for p, q in zip(coords[:-1], coords[1:])])
            if (distance >= min_distance
                    and (not junctionTaz
                         or source_edge.getFromNode() != sink_edge.getToNode())
                    and (max_distance is None or distance < max_distance)):
                return source_edge, sink_edge, intermediate
        raise Exception("no trip found after %s tries" % maxtries)
Пример #6
0
    def _parking_to_edge(self, parking):
        """ Given a parking lot, return the closest edge (lane_0) and all the other info
            required by SUMO for the parking areas:
            (edge_info, lane_info, location, parking.coords, parking.capacity)
        """

        edge_info = None
        lane_info = None
        dist_edge = sys.float_info.max  # distance.euclidean(a,b)
        location = None

        for edge in self._net.getEdges():
            if not (edge.allows('passenger') and edge.allows('pedestrian')):
                continue

            if self._is_too_short(edge.getLength()):
                continue

            stop_lane = None
            index = 0
            while not stop_lane:
                try:
                    stop_lane = edge.getLane(index)
                    if not stop_lane.allows('passenger'):
                        stop_lane = None
                        index += 1
                except IndexError:
                    stop_lane = None
                    break

            if stop_lane:
                # compute all the distances
                counter = 0
                for point in stop_lane.getShape():
                    dist = euclidean(
                        (float(parking['x']), float(parking['y'])), point)
                    if dist < dist_edge:
                        edge_info = edge
                        lane_info = stop_lane
                        dist_edge = dist
                        location = counter
                    counter += 1

        if dist_edge > 50.0:
            logging.info("Alert: parking lots %s is %d meters from edge %s.",
                         parking['id'], dist_edge, edge_info.getID())

        return (edge_info, lane_info, location)
Пример #7
0
    def _parkings_sumo(self):
        """ Compute the parking lots stops location for SUMO. """
        for plid, (_, lane, location) in self._parkings_edges_dict.items():
            new_pl = {
                'id':
                plid,
                'lane':
                lane.getID(),
                'start':
                -self._PARKING_LEN / 2,
                'end':
                self._PARKING_LEN / 2,
                'capacity':
                self._get_capacity(plid),
                'coords': (float(self._osm_parkings[plid]['x']),
                           float(self._osm_parkings[plid]['y'])),
            }

            _prec = None
            _counter = 0

            for point in lane.getShape():
                if _prec is None:
                    _prec = point
                    _counter += 1
                    continue
                if _counter <= location:
                    dist = euclidean(_prec, point)
                    new_pl['start'] += dist
                    new_pl['end'] += dist
                    _prec = point
                    _counter += 1
                else:
                    break

            if new_pl['start'] < self._BUFFER:
                new_pl['start'] = self._BUFFER
                new_pl['end'] = new_pl['start'] + self._PARKING_LEN

            if new_pl['end'] > lane.getLength() - self._BUFFER:
                new_pl['end'] = lane.getLength() - self._BUFFER
                new_pl['start'] = new_pl['end'] - self._PARKING_LEN

            self._sumo_parkings[plid] = new_pl
Пример #8
0
    def get_trip(self, min_distance, max_distance, maxtries=100):
        for i in range(maxtries):
            source_edge = self.source_generator.get()
            intermediate = [self.via_generator.get()
                            for i in range(self.intermediate)]
            sink_edge = self.sink_generator.get()
            if self.pedestrians:
                destCoord = sink_edge.getFromNode().getCoord()
            else:
                destCoord = sink_edge.getToNode().getCoord()

            coords = ([source_edge.getFromNode().getCoord()] +
                      [e.getFromNode().getCoord() for e in intermediate] +
                      [destCoord])
            distance = sum([euclidean(p, q)
                            for p, q in zip(coords[:-1], coords[1:])])
            if distance >= min_distance and (max_distance is None or distance < max_distance):
                return source_edge, sink_edge, intermediate
        raise Exception("no trip found after %s tries" % maxtries)
Пример #9
0
def mapTrace(trace, net, delta, verbose=False):
    """
    matching a list of 2D positions to consecutive edges in a network
    """
    result = []
    paths = {}
    if verbose:
        print("mapping trace with %s points" % len(trace))
    for pos in trace:
        newPaths = {}
        candidates = net.getNeighboringEdges(pos[0], pos[1], delta)
        if len(candidates) == 0 and verbose:
            print("Found no candidate edges for %s,%s" % pos)
        for edge, d in candidates:
            if paths:
                minDist = 1e400
                minPath = None
                for path, dist in paths.iteritems():
                    if dist < minDist:
                        if edge == path[-1]:
                            minPath = path
                            minDist = dist
                        elif edge in path[-1].getOutgoing():
                            minPath = path + (edge, )
                            minDist = dist
                        else:
                            minPath = path + (edge, )
                            minDist = dist + euclidean(
                                path[-1].getToNode().getCoord(),
                                edge.getFromNode().getCoord())
                if minPath:
                    newPaths[minPath] = minDist + d * d
            else:
                newPaths[(edge, )] = d * d
        if not newPaths:
            if paths:
                result += [e.getID() for e in _getMinPath(paths)]
        paths = newPaths
    if paths:
        return result + [e.getID() for e in _getMinPath(paths)]
    return result
Пример #10
0
    def _bus_stops_for_sumo(self, stops_to_edges):
        """ Compute the bus stops location for SUMO. """
        for ptid, (lane, location) in tqdm(stops_to_edges.items()):
            new_pt = {
                'id': ptid,
                'name': self._get_stop_name(self._osm_bus_stops[ptid]),
                'pt_type': self._osm_bus_stops[ptid]['pt_type'],
                'lane': lane.getID(),
            }

            _start = -BUS_PLATFORM_LEN / 2
            _end = BUS_PLATFORM_LEN / 2

            _prec = None
            _counter = 0

            for point in lane.getShape():
                if _prec is None:
                    _prec = point
                    _counter += 1
                    continue
                if _counter <= location:
                    dist = euclidean(_prec, point)
                    _start += dist
                    _end += dist
                    _prec = point
                    _counter += 1
                else:
                    break

            if _start < 5.0:
                _start = 5.0
                _end = _start + BUS_PLATFORM_LEN
            if _end > lane.getLength() - 5.0:
                _end = lane.getLength() - 5.0
                _start = _end - BUS_PLATFORM_LEN

            new_pt['start'] = _start
            new_pt['end'] = _end

            self._sumo_bus_stops[ptid] = new_pt
Пример #11
0
    def _bus_stop_to_lane(self, stop):
        """ Given the coords of a bus stop, return te closest lane_0. """

        lane_info = None
        dist_edge = sys.float_info.max  # distance.euclidean(a,b)
        location = None

        for edge in self._net.getEdges():
            if not (edge.allows('bus') and edge.allows('pedestrian')):
                continue

            if edge.getLength() < (BUS_PLATFORM_LEN * 1.5):
                continue

            stop_lane = None
            try:
                stop_lane = edge.getLane(1)
            except IndexError:
                stop_lane = edge.getLane(0)

            # compute all the distances
            counter = 0
            for point in stop_lane.getShape():
                dist = euclidean((float(stop['x']), float(stop['y'])), point)
                if dist < dist_edge:
                    lane_info = stop_lane
                    dist_edge = dist
                    location = counter
                counter += 1

        if dist_edge > 50.0:
            logging.info("Alert: stop %s [%s] is %d meters from lane %s.",
                         stop['id'], stop['pt_type'], dist_edge,
                         lane_info.getID())

        return (lane_info, location)
Пример #12
0
    def _train_stop_to_lane(self, stop):
        """ Given the coords of a stop, return te closest lane_0 """

        lane_info = None
        dist_edge = None
        location = None

        railway_lane_info = None
        railway_dist_edge = sys.float_info.max  # distance.euclidean(a,b)
        railway_location = None

        street_lane_info = None
        street_dist_edge = sys.float_info.max  # distance.euclidean(a,b)
        street_location = None

        for edge in self._net.getEdges():
            if edge.allows('rail'):
                if edge.getLength() < (TRAIN_PLATFORM_LEN * 1.5):
                    continue
                lane_info = railway_lane_info
                dist_edge = railway_dist_edge
                location = railway_location
            elif edge.allows('pedestrian'):
                lane_info = street_lane_info
                dist_edge = street_dist_edge
                location = street_location
            else:
                continue

            stop_lane = None
            try:
                stop_lane = edge.getLane(1)
            except IndexError:
                stop_lane = edge.getLane(0)

            # compute all the distances
            counter = 0
            for point in stop_lane.getShape():
                dist = euclidean((float(stop['x']), float(stop['y'])), point)
                if dist < dist_edge:
                    lane_info = stop_lane
                    dist_edge = dist
                    location = counter
                counter += 1

            if edge.allows('rail'):
                railway_lane_info = lane_info
                railway_dist_edge = dist_edge
                railway_location = location
            else:
                street_lane_info = lane_info
                street_dist_edge = dist_edge
                street_location = location

        railway_access = (railway_lane_info, railway_location)

        if railway_dist_edge > 50.0:
            logging.info("Alert: stop %s [%s] is %d meters from lane %s.",
                         stop['id'], stop['pt_type'], railway_dist_edge,
                         railway_lane_info.getID())

        street_access = (street_lane_info, street_location)
        logging.info(
            "Alert: Street access for stop %s [%s] is %d meters from edge %s.",
            stop['id'], stop['pt_type'], street_dist_edge,
            street_lane_info.getID())

        if street_dist_edge > 500.0:
            street_access = None
            logging.info(
                "Alert: Street access for stop %s too far and it will be removed.",
                stop['id'])

        return (railway_access, street_access)
Пример #13
0
def main():
    DUAROUTER = sumolib.checkBinary('duarouter')
    options = get_options()
    net = readNet(options.network)

    routeInfos = {}  # id-> RouteInfo
    if options.standalone:
        for route in parse(options.routeFile, 'route'):
            ri = RouteInfo()
            ri.edges = route.edges.split()
            routeInfos[route.id] = ri
    else:
        for vehicle in parse(options.routeFile, 'vehicle'):
            ri = RouteInfo()
            ri.edges = vehicle.route[0].edges.split()
            routeInfos[vehicle.id] = ri

    for rInfo in routeInfos.values():
        rInfo.airDist = euclidean(
            net.getEdge(rInfo.edges[0]).getShape()[0],
            net.getEdge(rInfo.edges[-1]).getShape()[-1])
        rInfo.length = getRouteLength(net, rInfo.edges)
        rInfo.airDistRatio = rInfo.length / rInfo.airDist

    duarouterInput = options.routeFile
    if options.standalone:
        # generate suitable input file for duarouter
        duarouterInput += ".vehRoutes.xml"
        with open(duarouterInput, 'w') as outf:
            outf.write('<routes>\n')
            for rID, rInfo in routeInfos.items():
                outf.write('    <vehicle id="%s" depart="0">\n' % rID)
                outf.write('        <route edges="%s"/>\n' %
                           ' '.join(rInfo.edges))
                outf.write('    </vehicle>\n')
            outf.write('</routes>\n')

    duarouterOutput = options.routeFile + '.rerouted.rou.xml'
    duarouterAltOutput = options.routeFile + '.rerouted.rou.alt.xml'

    subprocess.call([
        DUAROUTER, '-n', options.network, '-r', duarouterInput, '-o',
        duarouterOutput, '--no-step-log'
    ])

    for vehicle in parse(duarouterAltOutput, 'vehicle'):
        routeAlts = vehicle.routeDistribution[0].route
        if len(routeAlts) == 1:
            routeInfos[vehicle.id].detour = 0
            routeInfos[vehicle.id].detourRatio = 1
            routeInfos[vehicle.id].shortest_path_distance = routeInfos[
                vehicle.id].length
        else:
            oldCosts = float(routeAlts[0].cost)
            newCosts = float(routeAlts[1].cost)
            assert (routeAlts[0].edges.split() == routeInfos[vehicle.id].edges)
            routeInfos[vehicle.id].shortest_path_distance = getRouteLength(
                net, routeAlts[1].edges.split())
            if oldCosts <= newCosts:
                routeInfos[vehicle.id].detour = 0
                routeInfos[vehicle.id].detourRatio = 1
                if oldCosts < newCosts:
                    sys.stderr.write((
                        "Warning: fastest route for '%s' is slower than original route "
                        + "(old=%s, new=%s). Check vehicle types\n") %
                                     (vehicle.id, oldCosts, newCosts))
            else:
                routeInfos[vehicle.id].detour = oldCosts - newCosts
                routeInfos[vehicle.id].detourRatio = oldCosts / newCosts

    implausible = []
    allRoutesStats = Statistics("overal implausiblity")
    implausibleRoutesStats = Statistics("implausiblity above threshold")
    for rID in sorted(routeInfos.keys()):
        ri = routeInfos[rID]
        ri.implausibility = (
            options.airdist_ratio_factor * ri.airDistRatio +
            options.detour_factor * ri.detour +
            options.detour_ratio_factor * ri.detourRatio +
            max(0, options.min_dist / ri.shortest_path_distance - 1) +
            max(0, options.min_air_dist / ri.airDist - 1))
        allRoutesStats.add(ri.implausibility, rID)
        if ri.implausibility > options.threshold:
            implausible.append((ri.implausibility, rID, ri))
            implausibleRoutesStats.add(ri.implausibility, rID)

    # generate restrictions
    if options.restrictions_output is not None:
        with open(options.restrictions_output, 'w') as outf:
            for score, rID, ri in sorted(implausible):
                edges = ri.edges
                if options.odrestrictions and len(edges) > 2:
                    edges = [edges[0], edges[-1]]
                outf.write("0 %s\n" % " ".join(edges))

    if options.ignore_routes is not None:
        numImplausible = len(implausible)
        ignored = set([r.strip() for r in open(options.ignore_routes)])
        implausible = [r for r in implausible if r not in ignored]
        print(
            "Loaded %s routes to ignore. Reducing implausible from %s to %s" %
            (len(ignored), numImplausible, len(implausible)))

    # generate polygons
    polyOutput = options.routeFile + '.implausible.add.xml'
    colorgen = Colorgen(("random", 1, 1))
    with open(polyOutput, 'w') as outf:
        outf.write('<additional>\n')
        for score, rID, ri in sorted(implausible):
            generate_poly(options, net, rID, colorgen(), ri.edges, outf, score)
        outf.write('</additional>\n')

    sys.stdout.write(
        'score\troute\t(airDistRatio, detourRatio, detour, shortestDist, airDist)\n'
    )
    for score, rID, ri in sorted(implausible):
        # , ' '.join(ri.edges)))
        sys.stdout.write('%.7f\t%s\t%s\n' %
                         (score, rID,
                          (ri.airDistRatio, ri.detourRatio, ri.detour,
                           ri.shortest_path_distance, ri.airDist)))

    print(allRoutesStats)
    print(implausibleRoutesStats)
Пример #14
0
def mapTrace(trace,
             net,
             delta,
             verbose=False,
             airDistFactor=2,
             fillGaps=False,
             gapPenalty=-1,
             debug=False):
    """
    matching a list of 2D positions to consecutive edges in a network.
    The positions are assumed to be dense (i.e. covering each edge of the route) and in the correct order.
    """
    result = ()
    paths = {}
    lastPos = None
    if verbose:
        print("mapping trace with %s points" % len(trace))
    for pos in trace:
        newPaths = {}
        candidates = net.getNeighboringEdges(pos[0], pos[1], delta,
                                             not net.hasInternal)
        if debug:
            print("\n\npos:%s, %s" % (pos[0], pos[1]))
            print("candidates:%s\n" % candidates)
        if len(candidates) == 0 and verbose:
            print("Found no candidate edges for %s,%s" % pos)

        for edge, d in candidates:
            base = polygonOffsetWithMinimumDistanceToPoint(
                pos, edge.getShape())
            if paths:
                advance = euclidean(lastPos, pos)  # should become a vector
                minDist = 1e400
                minPath = None
                for path, (dist, lastBase) in paths.items():
                    if debug:
                        print("*** extending path %s by edge '%s'" %
                              ([e.getID() for e in path], edge.getID()))
                        print(
                            "              lastBase: %s, base: %s, advance: %s, old dist: %s, minDist: %s"
                            % (lastBase, base, advance, dist, minDist))
                    if dist < minDist:
                        if edge == path[-1]:
                            baseDiff = lastBase + advance - base
                            extension = ()
                            if debug:
                                print("---------- same edge")
                        else:
                            extension, cost = net.getShortestPath(
                                path[-1], edge, airDistFactor * advance +
                                edge.getLength() + path[-1].getLength())
                            if extension is not None and not fillGaps and len(
                                    extension) > 2:
                                extension = None
                            if extension is None:
                                airLineDist = euclidean(
                                    path[-1].getToNode().getCoord(),
                                    edge.getFromNode().getCoord())
                                if gapPenalty < 0:
                                    gapPenalty = airDistFactor * advance
                                baseDiff = abs(lastBase + advance -
                                               path[-1].getLength() - base -
                                               airLineDist) + gapPenalty
                                extension = (edge, )
                            else:
                                baseDiff = lastBase + advance - (
                                    cost - edge.getLength()) - base
                                extension = extension[1:]
                            if debug:
                                print(
                                    "---------- extension path: %s, cost: %s, baseDiff: %s"
                                    % (extension, cost, baseDiff))
                        dist += baseDiff * baseDiff
                        if dist < minDist:
                            minDist = dist
                            minPath = path + extension
                        if debug:
                            print("*** new dist: %s baseDiff: %s minDist: %s" %
                                  (dist, baseDiff, minDist))
                if minPath:
                    newPaths[minPath] = (minDist, base)
            else:
                newPaths[(edge, )] = (d * d, base)
        if not newPaths:
            if paths:
                result += _getMinPath(paths)
        paths = newPaths
        lastPos = pos
    if paths:
        if debug:
            print("**************** result:")
            for i in result + _getMinPath(paths):
                print("path:%s" % i.getID())
        return result + _getMinPath(paths)
    return result
Пример #15
0
def main():
    DUAROUTER = sumolib.checkBinary('duarouter')
    options = get_options()
    net = readNet(options.network)

    routeInfos = {}  # id-> RouteInfo
    if options.standalone:
        for route in parse(options.routeFile, 'route'):
            ri = RouteInfo()
            ri.edges = route.edges.split()
            routeInfos[route.id] = ri
    else:
        for vehicle in parse(options.routeFile, 'vehicle'):
            ri = RouteInfo()
            ri.edges = vehicle.route[0].edges.split()
            routeInfos[vehicle.id] = ri

    for rInfo in routeInfos.values():
        rInfo.airDist = euclidean(
            net.getEdge(rInfo.edges[0]).getShape()[0],
            net.getEdge(rInfo.edges[-1]).getShape()[-1])
        rInfo.length = getRouteLength(net, rInfo.edges)
        rInfo.airDistRatio = rInfo.length / rInfo.airDist

    duarouterInput = options.routeFile
    if options.standalone:
        # generate suitable input file for duarouter
        duarouterInput += ".vehRoutes.xml"
        with open(duarouterInput, 'w') as outf:
            outf.write('<routes>\n')
            for rID, rInfo in routeInfos.items():
                outf.write('    <vehicle id="%s" depart="0">\n' % rID)
                outf.write('        <route edges="%s"/>\n' % ' '.join(rInfo.edges))
                outf.write('    </vehicle>\n')
            outf.write('</routes>\n')

    duarouterOutput = options.routeFile + '.rerouted.rou.xml'
    duarouterAltOutput = options.routeFile + '.rerouted.rou.alt.xml'

    subprocess.call([DUAROUTER,
                     '-n', options.network,
                     '-r', duarouterInput,
                     '-o', duarouterOutput,
                     '--no-step-log'])

    for vehicle in parse(duarouterAltOutput, 'vehicle'):
        routeAlts = vehicle.routeDistribution[0].route
        if len(routeAlts) == 1:
            routeInfos[vehicle.id].detour = 0
            routeInfos[vehicle.id].detourRatio = 1
            routeInfos[vehicle.id].shortest_path_distance = routeInfos[vehicle.id].length
        else:
            oldCosts = float(routeAlts[0].cost)
            newCosts = float(routeAlts[1].cost)
            assert(routeAlts[0].edges.split() == routeInfos[vehicle.id].edges)
            routeInfos[vehicle.id].shortest_path_distance = getRouteLength(net, routeAlts[1].edges.split())
            if oldCosts <= newCosts:
                routeInfos[vehicle.id].detour = 0
                routeInfos[vehicle.id].detourRatio = 1
                if oldCosts < newCosts:
                    sys.stderr.write(("Warning: fastest route for '%s' is slower than original route " +
                                      "(old=%s, new=%s). Check vehicle types\n") % (
                                      vehicle.id, oldCosts, newCosts))
            else:
                routeInfos[vehicle.id].detour = oldCosts - newCosts
                routeInfos[vehicle.id].detourRatio = oldCosts / newCosts

    implausible = []
    allRoutesStats = Statistics("overal implausiblity")
    implausibleRoutesStats = Statistics("implausiblity above threshold")
    for rID in sorted(routeInfos.keys()):
        ri = routeInfos[rID]
        ri.implausibility = (options.airdist_ratio_factor * ri.airDistRatio +
                             options.detour_factor * ri.detour +
                             options.detour_ratio_factor * ri.detourRatio +
                             max(0, options.min_dist / ri.shortest_path_distance - 1) +
                             max(0, options.min_air_dist / ri.airDist - 1))
        allRoutesStats.add(ri.implausibility, rID)
        if ri.implausibility > options.threshold:
            implausible.append((ri.implausibility, rID, ri))
            implausibleRoutesStats.add(ri.implausibility, rID)

    # generate restrictions
    if options.restrictions_output is not None:
        with open(options.restrictions_output, 'w') as outf:
            for score, rID, ri in sorted(implausible):
                edges = ri.edges
                if options.odrestrictions and len(edges) > 2:
                    edges = [edges[0], edges[-1]]
                outf.write("0 %s\n" % " ".join(edges))

    if options.ignore_routes is not None:
        numImplausible = len(implausible)
        ignored = set([r.strip() for r in open(options.ignore_routes)])
        implausible = [r for r in implausible if r not in ignored]
        print("Loaded %s routes to ignore. Reducing implausible from %s to %s" % (
            len(ignored), numImplausible, len(implausible)))

    # generate polygons
    polyOutput = options.routeFile + '.implausible.add.xml'
    colorgen = Colorgen(("random", 1, 1))
    with open(polyOutput, 'w') as outf:
        outf.write('<additional>\n')
        for score, rID, ri in sorted(implausible):
            generate_poly(net, rID, colorgen(), 100, False, ri.edges, options.blur, outf, score)
        outf.write('</additional>\n')

    sys.stdout.write('score\troute\t(airDistRatio, detourRatio, detour, shortestDist, airDist)\n')
    for score, rID, ri in sorted(implausible):
        # , ' '.join(ri.edges)))
        sys.stdout.write('%.7f\t%s\t%s\n' % (score, rID, (ri.airDistRatio, ri.detourRatio,
                                                          ri.detour, ri.shortest_path_distance, ri.airDist)))

    print(allRoutesStats)
    print(implausibleRoutesStats)
Пример #16
0
    def _train_stops_for_sumo(self, stops_to_edges):
        """ Compute the train stops location for SUMO. """
        for ptid, values in tqdm(stops_to_edges.items()):

            railway_access, street_access = values

            railway_lane_info, railway_location = railway_access

            new_pt = {
                'id': ptid,
                'name': self._get_stop_name(self._osm_train_stops[ptid]),
                'pt_type': self._osm_train_stops[ptid]['pt_type'],
                'lane': railway_lane_info.getID(),
            }

            ### Compute the position for the railway
            _start = -TRAIN_PLATFORM_LEN / 2
            _end = TRAIN_PLATFORM_LEN / 2

            _prec = None
            _counter = 0
            for point in railway_lane_info.getShape():
                if _prec is None:
                    _prec = point
                    _counter += 1
                    continue
                if _counter <= railway_location:
                    dist = euclidean(_prec, point)
                    _start += dist
                    _end += dist
                    _prec = point
                    _counter += 1
                else:
                    break

            if _start < 5.0:
                _start = 5.0
                _end = _start + TRAIN_PLATFORM_LEN
            if _end > railway_lane_info.getLength() - 5.0:
                _end = railway_lane_info.getLength() - 5.0
                _start = _end - TRAIN_PLATFORM_LEN
            if railway_lane_info.getLength() <= TRAIN_PLATFORM_LEN:
                _start = 5.0
                _end = railway_lane_info.getLength() - 5.0

            new_pt['start'] = _start
            new_pt['end'] = _end

            street_lane_info, street_location = (None, None)

            if street_access:
                street_lane_info, street_location = street_access
                new_pt['access'] = {'lane': street_lane_info.getID()}

                ### Compute the position for the street
                _start = -TRAIN_PLATFORM_LEN / 2
                _end = TRAIN_PLATFORM_LEN / 2

                _prec = None
                _counter = 0
                for point in street_lane_info.getShape():
                    if _prec is None:
                        _prec = point
                        _counter += 1
                        continue
                    if _counter <= street_location:
                        dist = euclidean(_prec, point)
                        _start += dist
                        _end += dist
                        _prec = point
                        _counter += 1
                    else:
                        break

                if _start < 5.0:
                    _start = 5.0
                    _end = _start + TRAIN_PLATFORM_LEN
                if _end > street_lane_info.getLength() - 5.0:
                    _end = street_lane_info.getLength() - 5.0
                    _start = _end - TRAIN_PLATFORM_LEN
                if street_lane_info.getLength() <= TRAIN_PLATFORM_LEN:
                    _start = 5.0
                    _end = street_lane_info.getLength() - 5.0

                new_pt['access']['pos'] = (_start + _end) / 2

            self._sumo_train_stops[ptid] = new_pt
Пример #17
0
def rectify_input(options):
    # convert depart-time to seconds
    #   add random seconds from [-options.diffuse/2, options.diffuse/2] to reduce traffic bursts
    #   (right now the most important trip for each person is aligned to 5min slot
    #    and some of these slots are very crowded)
    # gaps
    # NaN
    # ordering assumptions
    #   every "person" appears only once. A person is defined by (person_id, household_id)
    #   trips for each person are sorted by departure
    # report overlapping times
    # filter trips wich start on the next day
    # filter trips by mode (optional)
    # diffuse geoCoordinates with a gausian (mu = 0, sigma = spatialDiffuse meters)
    # since tapas inputs tends to show strong spatial clustering (call it
    # parking related diffusion)
    diffusion_map = {}
    modes = options.modes.split(",")
    if options.max_spatial_diffusion > 0:
        loc_count = collections.defaultdict(int)
        for row in csv.DictReader(open(options.tapas_trips)):
            if row[TH.mode] in modes:
                loc_count[(row[TH.source_long], row[TH.source_lat])] += 1
                loc_count[(row[TH.dest_long], row[TH.dest_lat])] += 1
        for coord, count in loc_count.items():
            if count >= options.spatial_diffusion_bounds[0]:
                scale = float(count - options.spatial_diffusion_bounds[0]) / (
                    options.spatial_diffusion_bounds[1] -
                    options.spatial_diffusion_bounds[0])
                diffusion = scale * (
                    options.max_spatial_diffusion -
                    options.spatial_diffusion) + options.spatial_diffusion
                if diffusion < options.max_spatial_diffusion:
                    diffusion_map[coord] = diffusion
    if os.path.exists(options.location_priority_file):
        for loc in sumolib.xml.parse(options.location_priority_file, "poi"):
            diffusion_map[(loc.lon, loc.lat)] = 0
    with open(options.rectified_log, 'w') as logfile:
        log = get_logger(logfile)
        writer = csv.DictWriter(open(options.rectified, 'w'),
                                THX.fieldnames,
                                extrasaction='ignore',
                                lineterminator='\n')
        writer.writeheader()

        persons = 0
        rows = 0
        gaps = 0
        gap_sum = 0
        max_gap = 0
        max_gap_uid = None
        max_depart = 0
        max_depart_uid = None
        inconsistent = 0
        skipped_wrong_mode = 0
        skipped_wrong_depart = 0

        # asserts that each person appears only in one consecutive sequence of
        # # entries
        gen = csv_sequence_generator(options.tapas_trips,
                                     (TH.person_id, TH.household_id),
                                     assertUniqe=True)
        for (pid, hid), trip_sequence in gen:
            persons += 1
            previous_row = None
            previous_dest = None
            previous_end = None
            previous_depart = None
            spatial_offset = None
            # smooth bursts due to low resolution
            smoothing_offset = int(
                random.random() *
                (options.time_diffusion + 1)) - options.time_diffusion // 2
            for row in trip_sequence:
                rows += 1
                uid = build_uid(row)
                source_coord = (row[TH.source_long], row[TH.source_lat])
                source = options.net.convertLonLat2XY(*source_coord)
                if spatial_offset is None:
                    if source_coord in diffusion_map:
                        spatial_offset = [
                            random.gauss(0, diffusion_map[source_coord])
                            for i in range(2)
                        ]
                    elif options.max_spatial_diffusion <= 0 and options.spatial_diffusion > 0:
                        spatial_offset = [
                            random.gauss(0, options.spatial_diffusion)
                            for i in range(2)
                        ]
                dest_coord = (row[TH.dest_long], row[TH.dest_lat])
                dest = options.net.convertLonLat2XY(*dest_coord)
                depart_minute = int(row[TH.depart_minute])
                depart = depart_minute * 60 + smoothing_offset
                duration = float(row[TH.duration])
                activity_duration = int(row[TH.activity_duration_minutes]) * 60

                if depart_minute - 24 * 60 >= TAPAS_DAY_OVERLAP_MINUTES or depart_minute <= -TAPAS_DAY_OVERLAP_MINUTES:
                    log("Warning: dropping trip %s because it starts on the wrong day (minute %s)"
                        % (uid, depart_minute))
                    skipped_wrong_depart += 1
                    if depart_minute > max_depart:
                        max_depart = depart_minute
                        max_depart_uid = uid
                    continue

                row[THX.depart_second] = depart
                if math.isnan(duration):
                    log('Warning: NaN value in duration of trip %s' % uid)
                    duration = 1
                    row[TH.duration] = duration

                if previous_end is not None and depart < previous_end:
                    if (previous_end - depart >= 60):
                        # input data only has minute resolution anyway and may
                        # suffer from rounding
                        inconsistent += 1
                        log("Warning: inconsistent depart time for trip %s (%s seconds)"
                            % (uid, previous_end - depart))
                    depart = previous_end

                previous_end = int(depart + duration + activity_duration)

                if previous_depart is not None and depart < previous_depart:
                    raise MappingError(
                        'Unordered trips for person %s at departure %s' %
                        (pid, depart_minute))
                previous_depart = depart

                # close gaps in trip sequence
                if previous_dest and previous_dest != source and not options.ignore_gaps:
                    gaps += 1
                    gap = euclidean(previous_dest, source)
                    gap_sum += gap
                    max_gap = max(max_gap, gap)
                    max_gap_uid = uid
                    # to many to list them all
                    # print('Warning: gap in edge sequence at trip %s (length %s)' % (uid, gap))
                    # XXX add teleport-trip for closing the gap
                    # row[TH.source_long] = previous_row[TH.dest_long]
                    # row[TH.source_lat] = previous_row[TH.dest_lat]
                    continue
                previous_row = row
                previous_dest = dest

                if spatial_offset is not None:
                    row[TH.source_long], row[
                        TH.source_lat] = options.net.convertXY2LonLat(
                            source[0] + spatial_offset[0],
                            source[1] + spatial_offset[1])
                    if dest_coord in diffusion_map:
                        spatial_offset = [
                            random.gauss(0, diffusion_map[dest_coord])
                            for i in range(2)
                        ]
                    else:
                        spatial_offset = [
                            random.gauss(0, options.spatial_diffusion)
                            for i in range(2)
                        ]
                    row[TH.dest_long], row[
                        TH.dest_lat] = options.net.convertXY2LonLat(
                            dest[0] + spatial_offset[0],
                            dest[1] + spatial_offset[1])

                if row[TH.mode] in modes:
                    writer.writerow(row)
                else:
                    skipped_wrong_mode += 1

        log('Read %s persons with a total of %s trips from input file "%s".' %
            (persons, rows, options.tapas_trips))
        if skipped_wrong_mode > 0:
            log('Dropped %s trips because they have the wrong mode' %
                skipped_wrong_mode)
        log('%s trips have inconsistent depart times.' % inconsistent)
        if gaps > 0:
            log('Dropped %s trips because of gaps, avg: %s, maximum: %s (for trip %s).'
                % (gaps, gap_sum / gaps, max_gap, max_gap_uid))
        if skipped_wrong_depart > 0:
            log('Dropped %d trips because they start on the wrong day (maximum: %s for trip %s).'
                % (skipped_wrong_depart, max_depart, max_depart_uid))