view python/traffic_engineering.py @ 33:4bd7cc69b6cd

added traffic engineering utilities with first version of LaneGroups
author Nicolas Saunier <nico@confins.net>
date Sat, 10 Apr 2010 20:46:33 -0400
parents
children 388a5a25fe92
line wrap: on
line source

#! /usr/bin/env python
''' Traffic Engineering Tools.'''

from math import ceil

__metaclass__ = type

#########################
# traffic signals
#########################

class Volume:
    '''Class to represent volumes with varied vehicule types '''
    def __init__(self, volume, types = ['pc'], proportions = [1], equivalents = [1], nLanes = 1):
        '''mvtEquivalent is the equivalent if the movement is right of left turn'''

        # check the sizes of the lists
        if sum(proportions) == 1:
            self.volume = volume
            self.types = types
            self.proportions = proportions
            self.equivalents = equivalents
            self.nLanes = nLanes
        else:
            pass

    def getPCEVolume(self):
        '''Returns the passenger-car equivalent for the input volume'''
        v = 0
        for p, e in zip(self.proportions, self.equivalents):
            v += p*e
        return v*self.volume

class IntersectionMouvement:
    '''Represents an intersection movement
    with a volume, a type (through, left or right)
    and an equivalent for movement type'''
    def __init__(self, volume,  type, mvtEquivalent = 1):
        self.volume = volume
        self.type = type
        self.mvtEquivalent = mvtEquivalent

    def getTVUVolume(self):
        return self.mvtEquivalent*self.volume.getPCEVolume()    

class IntersectionApproach:
    def __init__(self, leftTurnVolume, throughVolume, rightTurnVolume):
        self.leftTurnVolume = leftTurnVolume
        self.throughVolume = throughVolume
        self.rightTurnVolume = rightTurnVolume

    def getTVUVolume(self, leftTurnEquivalent = 1, throughEquivalent = 1, rightTurnEquivalent = 1):
        return self.leftTurnVolume.getPCEVolume()*leftTurnEquivalent+self.throughVolume.getPCEVolume()*throughEquivalent+self.rightTurnVolume.getPCEVolume()*rightTurnEquivalent

class LaneGroup:
    '''Class that represents a group of mouvements'''

    def __init__(self):
        self.mouvements = {'left': [],
                           'through': [],
                           'right': []}

    # all the add*Mvt should add a IntersectionMovement instance
    def addLeftMvt(self, vol):
        self.mouvements['left'].append(vol)

    def addRightMvt(self, vol):
        self.mouvements['right'].append(vol)

    def addThroughMvt(self, vol):
        self.mouvements['through'].append(vol)

    def getTVUVolume(self, leftTurnEquivalent = 1, throughEquivalent = 1, rightTurnEquivalent = 1):
        return leftTurnEquivalent*sum([m.getPCEVolume() for m in mouvements['left']])\
            +rightTurnEquivalent*sum([m.getPCEVolume() for m in mouvements['right']])\
            +throughTurnEquivalent*sum([m.getPCEVolume() for m in mouvements['through']])

def checkProtectedLeftTurn(leftMvt, opposedThroughMvt):
    '''Checks if one of the main two conditions on left turn is verified
    The lane groups should contain left and through movement'''
    return leftMvt.volume >= 200 or leftMvt.volume*opposedMvt.volume/opposedMvt.nLanes > 50000

def optimalCycle(lostTime, criticalCharge):
    return ceil((1.5*lostTime+5)/(1-criticalCharge))

def computeInterGreen(perceptionReactionTime, initialSpeed, intersectionLength, vehicleAverageLength = 6, deceleration = 3):
    '''Computes the intergreen time (yellow/amber plus all red time)
    Deceleration is positive
    All variables should be in the same units'''
    if deceleration > 0:
        return [perceptionReactionTime+initialSpeed/(2*deceleration), (intersectionLength+vehicleAverageLength)/initialSpeed]
    else:
        print 'Issue deceleration should be strictly positive'
        return None