changeset 943:b1e8453c207c

work on motion prediction using motion patterns
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Wed, 19 Jul 2017 18:02:38 -0400
parents ab13aaf41432
children 84ebe1b031f1
files python/events.py python/moving.py python/prediction.py python/storage.py scripts/safety-analysis.py tracking.cfg
diffstat 6 files changed, 92 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/python/events.py	Tue Jul 18 18:01:16 2017 -0400
+++ b/python/events.py	Wed Jul 19 18:02:38 2017 -0400
@@ -216,19 +216,19 @@
                 minDistances[instant] = moving.MovingObject.minDistance(self.roadUser1, self.roadUser2, instant)
             self.addIndicator(indicators.SeverityIndicator(Interaction.indicatorNames[3], minDistances, mostSevereIsMax = False))
 
-    def computeCrossingsCollisions(self, predictionParameters, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False, timeInterval = None, nProcesses = 1, usePrototypes=False, route1= (-1,-1), route2=(-1,-1), prototypes={}, secondStepPrototypes={}, nMatching={}, objects=[], noiseEntryNums=[], noiseExitNums=[], minSimilarity=0.1, mostMatched=None, useDestination=True, useSpeedPrototype=True, acceptPartialLength=30, step=1):
+    def computeCrossingsCollisions(self, predictionParameters, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False, timeInterval = None, nProcesses = 1):#, usePrototypes=False, route1= (-1,-1), route2=(-1,-1), prototypes={}, secondStepPrototypes={}, nMatching={}, objects=[], noiseEntryNums=[], noiseExitNums=[], minSimilarity=0.1, mostMatched=None, useDestination=True, useSpeedPrototype=True, acceptPartialLength=30, step=1):
         '''Computes all crossing and collision points at each common instant for two road users. '''
         TTCs = {}
         collisionProbabilities = {}
-        if usePrototypes:
-            route1= getRoute(self.roadUser1,prototypes,objects,noiseEntryNums,noiseExitNums,useDestination)
-            route2= getRoute(self.roadUser2,prototypes,objects,noiseEntryNums,noiseExitNums,useDestination)
+        # if usePrototypes:
+        #     route1= getRoute(self.roadUser1,prototypes,objects,noiseEntryNums,noiseExitNums,useDestination)
+        #     route2= getRoute(self.roadUser2,prototypes,objects,noiseEntryNums,noiseExitNums,useDestination)
 
         if timeInterval is not None:
             commonTimeInterval = timeInterval
         else:
             commonTimeInterval = self.timeInterval
-        self.collisionPoints, crossingZones = predictionParameters.computeCrossingsCollisions(self.roadUser1, self.roadUser2, collisionDistanceThreshold, timeHorizon, computeCZ, debug, commonTimeInterval, nProcesses,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype,acceptPartialLength, step)
+        self.collisionPoints, crossingZones = predictionParameters.computeCrossingsCollisions(self.roadUser1, self.roadUser2, collisionDistanceThreshold, timeHorizon, computeCZ, debug, commonTimeInterval, nProcesses)#,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype,acceptPartialLength, step)
         for i, cps in self.collisionPoints.iteritems():
             TTCs[i] = prediction.SafetyPoint.computeExpectedIndicator(cps)
             collisionProbabilities[i] = sum([p.probability for p in cps])
--- a/python/moving.py	Tue Jul 18 18:01:16 2017 -0400
+++ b/python/moving.py	Wed Jul 19 18:02:38 2017 -0400
@@ -1231,6 +1231,9 @@
     def getUserType(self):
         return self.userType
 
+    def computeCumulativeDistances(self):
+        self.positions.computeCumulativeDistances()
+
     def getCurvilinearPositions(self):
         if hasattr(self, 'curvilinearPositions'):
             return self.curvilinearPositions
--- a/python/prediction.py	Tue Jul 18 18:01:16 2017 -0400
+++ b/python/prediction.py	Wed Jul 19 18:02:38 2017 -0400
@@ -82,7 +82,6 @@
     def predictPosition(self, nTimeSteps):
         if nTimeSteps > 0 and not nTimeSteps in self.predictedPositions.keys():
             if self.constantSpeed:
-                # calculate cumulative distance
                 traj = self.prototype.getPositions()
                 trajLength = traj.length()
                 traveledDistance = nTimeSteps*self.initialSpeed + traj.getCumulativeDistance(self.closestPointIdx)
@@ -161,8 +160,9 @@
     return collision, t, p1, p2
 
 def savePredictedTrajectoriesFigure(currentInstant, obj1, obj2, predictedTrajectories1, predictedTrajectories2, timeHorizon):
-    from matplotlib.pyplot import figure, axis, title, close, savefig
+    from matplotlib.pyplot import figure, axis, title, clf, savefig
     figure()
+    #clf()
     for et in predictedTrajectories1:
         et.predictPosition(int(np.round(timeHorizon)))
         et.plot('rx')
@@ -170,12 +170,11 @@
     for et in predictedTrajectories2:
         et.predictPosition(int(np.round(timeHorizon)))
         et.plot('bx')
-    obj1.plot('r')
-    obj2.plot('b')
+    obj1.plot('r', withOrigin = True)
+    obj2.plot('b', withOrigin = True)
     title('instant {0}'.format(currentInstant))
     axis('equal')
     savefig('predicted-trajectories-t-{0}.png'.format(currentInstant))
-    close()
 
 def calculateProbability(nMatching,similarity,objects):
     sumFrequencies=sum([nMatching[p] for p in similarity.keys()])
@@ -255,23 +254,22 @@
         prototypeTrajectories=findPrototypes(prototypes,nMatching,objects,route,partialObjPositions,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched)
     return prototypeTrajectories
 
-def computeCrossingsCollisionsAtInstant(predictionParams,currentInstant, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False, usePrototypes = False,route1= (-1,-1),route2=(-1,-1),prototypes={},secondStepPrototypes={},nMatching={},objects=[],noiseEntryNums=[],noiseExitNums=[],minSimilarity=0.1,mostMatched=None,useDestination=True,useSpeedPrototype=True):  
+def computeCrossingsCollisionsAtInstant(predictionParams,currentInstant, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False):#, usePrototypes = False,route1= (-1,-1),route2=(-1,-1),prototypes={},secondStepPrototypes={},nMatching={},objects=[],noiseEntryNums=[],noiseExitNums=[],minSimilarity=0.1,mostMatched=None,useDestination=True,useSpeedPrototype=True):  
     '''returns the lists of collision points and crossing zones'''
-    if usePrototypes:
-        prototypeTrajectories1 = getPrototypeTrajectory(obj1,route1,currentInstant,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)
-        prototypeTrajectories2 = getPrototypeTrajectory(obj2,route2,currentInstant,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)
-        predictedTrajectories1 = predictionParams.generatePredictedTrajectories(obj1, currentInstant,prototypeTrajectories1)
-        predictedTrajectories2 = predictionParams.generatePredictedTrajectories(obj2, currentInstant,prototypeTrajectories2)     
-    else:
-        predictedTrajectories1 = predictionParams.generatePredictedTrajectories(obj1, currentInstant)
-        predictedTrajectories2 = predictionParams.generatePredictedTrajectories(obj2, currentInstant)        
+    # if usePrototypes:
+    #     prototypeTrajectories1 = getPrototypeTrajectory(obj1,route1,currentInstant,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)
+    #     prototypeTrajectories2 = getPrototypeTrajectory(obj2,route2,currentInstant,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)
+    #     predictedTrajectories1 = predictionParams.generatePredictedTrajectories(obj1, currentInstant,prototypeTrajectories1)
+    #     predictedTrajectories2 = predictionParams.generatePredictedTrajectories(obj2, currentInstant,prototypeTrajectories2)     
+    # else:
+    predictedTrajectories1 = predictionParams.generatePredictedTrajectories(obj1, currentInstant)
+    predictedTrajectories2 = predictionParams.generatePredictedTrajectories(obj2, currentInstant)        
 
     collisionPoints = []
     crossingZones = []
     for et1 in predictedTrajectories1:
         for et2 in predictedTrajectories2:
             collision, t, p1, p2 = computeCollisionTime(et1, et2, collisionDistanceThreshold, timeHorizon)
-
             if collision:
                 collisionPoints.append(SafetyPoint((p1+p2)*0.5, et1.probability*et2.probability, t))
             elif computeCZ: # check if there is a crossing zone
@@ -309,10 +307,10 @@
     def generatePredictedTrajectories(self, obj, instant):
         return []
 
-    def computeCrossingsCollisionsAtInstant(self, currentInstant, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False,usePrototypes = False,route1= (-1,-1),route2=(-1,-1),prototypes={},secondStepPrototypes={},nMatching={},objects=[],noiseEntryNums=[],noiseExitNums=[],minSimilarity=0.1,mostMatched=None,useDestination=True,useSpeedPrototype=True):
-        return computeCrossingsCollisionsAtInstant(self, currentInstant, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ, debug,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)
+#    def computeCrossingsCollisionsAtInstant(self, currentInstant, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False):#,usePrototypes = False,route1= (-1,-1),route2=(-1,-1),prototypes={},secondStepPrototypes={},nMatching={},objects=[],noiseEntryNums=[],noiseExitNums=[],minSimilarity=0.1,mostMatched=None,useDestination=True,useSpeedPrototype=True):
+#        return computeCrossingsCollisionsAtInstant(self, currentInstant, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ, debug)#,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)
 
-    def computeCrossingsCollisions(self, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False, timeInterval = None, nProcesses = 1,usePrototypes = False,route1= (-1,-1),route2=(-1,-1),prototypes={},secondStepPrototypes={},nMatching={},objects=[],noiseEntryNums=[],noiseExitNums=[],minSimilarity=0.1,mostMatched=None,useDestination=True,useSpeedPrototype=True,acceptPartialLength=30, step=1):
+    def computeCrossingsCollisions(self, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False, timeInterval = None, nProcesses = 1):#,usePrototypes = False,route1= (-1,-1),route2=(-1,-1),prototypes={},secondStepPrototypes={},nMatching={},objects=[],noiseEntryNums=[],noiseExitNums=[],minSimilarity=0.1,mostMatched=None,useDestination=True,useSpeedPrototype=True,acceptPartialLength=30, step=1):
         #def computeCrossingsCollisions(predictionParams, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ = False, debug = False, timeInterval = None,nProcesses = 1, usePrototypes = False,route1= (-1,-1),route2=(-1,-1),prototypes={},secondStepPrototypes={},nMatching={},objects=[],noiseEntryNums=[],noiseExitNums=[],minSimilarity=0.1,mostMatched=None,useDestination=True,useSpeedPrototype=True,acceptPartialLength=30, step=1):
         '''Computes all crossing and collision points at each common instant for two road users. '''
         collisionPoints={}
@@ -322,34 +320,34 @@
         else:
             commonTimeInterval = obj1.commonTimeInterval(obj2)
         if nProcesses == 1:
-            if usePrototypes:
-                firstInstant= next( (x for x in xrange(commonTimeInterval.first,commonTimeInterval.last) if x-obj1.getFirstInstant() >= acceptPartialLength and x-obj2.getFirstInstant() >= acceptPartialLength), commonTimeInterval.last)
-                commonTimeIntervalList1= range(firstInstant,commonTimeInterval.last-1) # do not look at the 1 last position/velocities, often with errors
-                commonTimeIntervalList2= range(firstInstant,commonTimeInterval.last-1,step) # do not look at the 1 last position/velocities, often with errors
-                for i in commonTimeIntervalList2: 
-                    i, cp, cz = self.computeCrossingsCollisionsAtInstant(i, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ, debug,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)
-                    if len(cp) != 0:
-                        collisionPoints[i] = cp
-                    if len(cz) != 0:
-                        crossingZones[i] = cz
-                if collisionPoints!={} or crossingZones!={}:
-                    for i in commonTimeIntervalList1:
-                        if i not in commonTimeIntervalList2:
-                            i, cp, cz = self.computeCrossingsCollisionsAtInstant(i, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ, debug,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)
-                            if len(cp) != 0:
-                                collisionPoints[i] = cp
-                            if len(cz) != 0:
-                                crossingZones[i] = cz                        
-            else:
-                for i in list(commonTimeInterval)[:-1]: # do not look at the 1 last position/velocities, often with errors
-                    i, cp, cz = self.computeCrossingsCollisionsAtInstant(i, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ, debug,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)
-                    if len(cp) != 0:
-                        collisionPoints[i] = cp
-                    if len(cz) != 0:
-                        crossingZones[i] = cz
+            # if usePrototypes:
+            #     firstInstant= next( (x for x in xrange(commonTimeInterval.first,commonTimeInterval.last) if x-obj1.getFirstInstant() >= acceptPartialLength and x-obj2.getFirstInstant() >= acceptPartialLength), commonTimeInterval.last)
+            #     commonTimeIntervalList1= range(firstInstant,commonTimeInterval.last-1) # do not look at the 1 last position/velocities, often with errors
+            #     commonTimeIntervalList2= range(firstInstant,commonTimeInterval.last-1,step) # do not look at the 1 last position/velocities, often with errors
+            #     for i in commonTimeIntervalList2: 
+            #         i, cp, cz = self.computeCrossingsCollisionsAtInstant(i, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ, debug,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)
+            #         if len(cp) != 0:
+            #             collisionPoints[i] = cp
+            #         if len(cz) != 0:
+            #             crossingZones[i] = cz
+            #     if collisionPoints!={} or crossingZones!={}:
+            #         for i in commonTimeIntervalList1:
+            #             if i not in commonTimeIntervalList2:
+            #                 i, cp, cz = self.computeCrossingsCollisionsAtInstant(i, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ, debug,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)
+            #                 if len(cp) != 0:
+            #                     collisionPoints[i] = cp
+            #                 if len(cz) != 0:
+            #                     crossingZones[i] = cz                        
+            # else:
+            for i in list(commonTimeInterval)[:-1]: # do not look at the 1 last position/velocities, often with errors
+                i, cp, cz = computeCrossingsCollisionsAtInstant(self, i, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ, debug)#,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)
+                if len(cp) != 0:
+                    collisionPoints[i] = cp
+                if len(cz) != 0:
+                    crossingZones[i] = cz
         else:
             pool = Pool(processes = nProcesses)
-            jobs = [pool.apply_async(computeCrossingsCollisionsAtInstant, args = (self, i, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ, debug,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype)) for i in list(commonTimeInterval)[:-1]]
+            jobs = [pool.apply_async(computeCrossingsCollisionsAtInstant, args = (self, i, obj1, obj2, collisionDistanceThreshold, timeHorizon, computeCZ, debug)) for i in list(commonTimeInterval)[:-1]] #,usePrototypes,route1,route2,prototypes,secondStepPrototypes,nMatching,objects,noiseEntryNums,noiseExitNums,minSimilarity,mostMatched,useDestination,useSpeedPrototype
             #results = [j.get() for j in jobs]
             #results.sort()
             for j in jobs:
@@ -437,7 +435,6 @@
         return predictedTrajectories
 
 class PointSetPredictionParameters(PredictionParameters):
-    # todo generate several trajectories with normal adaptatoins from each position (feature)
     def __init__(self, maxSpeed):
         PredictionParameters.__init__(self, 'point set', maxSpeed)
         #self.nPredictedTrajectories = nPredictedTrajectories
@@ -456,6 +453,7 @@
             print('Object {} has no features'.format(obj.getNum()))
             return None
 
+        
 class EvasiveActionPredictionParameters(PredictionParameters):
     def __init__(self, maxSpeed, nPredictedTrajectories, accelerationDistribution, steeringDistribution, useFeatures = False):
         '''Suggested acceleration distribution may not be symmetric, eg
@@ -580,22 +578,36 @@
 
         return currentInstant, collisionPoints, crossingZones
 
-####
-# Other Methods
-####
 class PrototypePredictionParameters(PredictionParameters):
-    def __init__(self, maxSpeed, nPredictedTrajectories, constantSpeed = True):
-        name = 'prototype'
-        PredictionParameters.__init__(self, name, maxSpeed)
+    def __init__(self, prototypes, nPredictedTrajectories, pointSimilarityDistance, minSimilarity, lcssMetric = 'cityblock', minFeatureTime = 10, constantSpeed = False, useFeatures = True): # lcss parameters
+        PredictionParameters.__init__(self, 'prototypes', None)
+        self.prototypes = prototypes
         self.nPredictedTrajectories = nPredictedTrajectories
+        self.lcss = LCSS(metric = lcssMetric, epsilon = pointSimilarityDistance)
+        #self.similarityFunc = lambda x,y : self.lcss.computeNormalized(x, y)
+        self.minSimilarity = minSimilarity
+        self.minFeatureTime = minFeatureTime
         self.constantSpeed = constantSpeed
+        self.useFeatures = useFeatures
         
-    def generatePredictedTrajectories(self, obj, instant,prototypeTrajectories):
+    def generatePredictedTrajectories(self, obj, instant):
         predictedTrajectories = []
-        initialPosition = obj.getPositionAtInstant(instant)
-        initialVelocity = obj.getVelocityAtInstant(instant)
-        for prototypeTraj in prototypeTrajectories.keys():
-            predictedTrajectories.append(PredictedTrajectoryPrototype(initialPosition, initialVelocity, prototypeTraj, constantSpeed = self.constantSpeed, probability = prototypeTrajectories[prototypeTraj])) 
+        if instant-obj.getFirstInstant()+1 >= self.minFeatureTime:
+            if self.useFeatures and obj.hasFeatures():
+                # get current features existing for the most time, sort on first instant of feature and take n first
+                pass
+            else:
+                if not hasattr(obj, 'prototypeSimilarities'):
+                    obj.prototypeSimilarities = []
+                    for proto in self.prototypes:
+                        self.lcss.similarities(proto.getMovingObject().getPositions().asArray().T, obj.getPositions().asArray().T)
+                        similarities = self.lcss.similarityTable[-1, :-1].astype(float)
+                        obj.prototypeSimilarities.append(similarities/np.minimum(np.arange(1.,len(similarities)+1), proto.getMovingObject().length()*np.ones(len(similarities))))
+                for proto, similarities in zip(self.prototypes, obj.prototypeSimilarities):
+                    if similarities[instant-obj.getFirstInstant()] >= self.minSimilarity:
+                        initialPosition = obj.getPositionAtInstant(instant)
+                        initialVelocity = obj.getVelocityAtInstant(instant)
+                        predictedTrajectories.append(PredictedTrajectoryPrototype(initialPosition, initialVelocity, proto.getMovingObject(), constantSpeed = self.constantSpeed, probability = proto.getNMatchings())) 
         return predictedTrajectories
 
 if __name__ == "__main__":
--- a/python/storage.py	Tue Jul 18 18:01:16 2017 -0400
+++ b/python/storage.py	Wed Jul 19 18:02:38 2017 -0400
@@ -1381,6 +1381,7 @@
         self.maxExtremeAcceleration = config.getfloat(self.sectionHeader, 'max-extreme-acceleration')/self.videoFrameRate**2
         self.maxExtremeSteering = config.getfloat(self.sectionHeader, 'max-extreme-steering')/self.videoFrameRate
         self.useFeaturesForPrediction = config.getboolean(self.sectionHeader, 'use-features-prediction')
+        self.constantSpeedPrototypePrediction = config.getboolean(self.sectionHeader, 'constant-speed')
 
     def __init__(self, filename = None):
         if filename is not None and path.exists(filename):
--- a/scripts/safety-analysis.py	Tue Jul 18 18:01:16 2017 -0400
+++ b/scripts/safety-analysis.py	Wed Jul 19 18:02:38 2017 -0400
@@ -14,8 +14,8 @@
 parser.add_argument('--cfg', dest = 'configFilename', help = 'name of the configuration file', required = True)
 parser.add_argument('-n', dest = 'nObjects', help = 'number of objects to analyse', type = int)
 # TODO analyze only 
-parser.add_argument('--prediction-method', dest = 'predictionMethod', help = 'prediction method (constant velocity (cvd: vector computation (approximate); cve: equation solving; cv: discrete time (approximate)), normal adaptation, point set prediction)', choices = ['cvd', 'cve', 'cv', 'na', 'ps', 'proto'])
-parser.add_argument('--cfg', dest = 'prototypeDatabaseFilename', help = 'name of the database containing the prototypes')
+parser.add_argument('--prediction-method', dest = 'predictionMethod', help = 'prediction method (constant velocity (cvd: vector computation (approximate); cve: equation solving; cv: discrete time (approximate)), normal adaptation, point set prediction)', choices = ['cvd', 'cve', 'cv', 'na', 'ps', 'mp'])
+parser.add_argument('--prototypeDatabaseFilename', dest = 'prototypeDatabaseFilename', help = 'name of the database containing the prototypes')
 parser.add_argument('--pet', dest = 'computePET', help = 'computes PET', action = 'store_true')
 parser.add_argument('--display-cp', dest = 'displayCollisionPoints', help = 'display collision points', action = 'store_true')
 parser.add_argument('--nthreads', dest = 'nProcesses', help = 'number of processes to run in parallel', type = int, default = 1)
@@ -48,10 +48,15 @@
                                                                            params.useFeaturesForPrediction)
 elif predictionMethod == 'ps':
     predictionParameters = prediction.PointSetPredictionParameters(params.maxPredictedSpeed)
-elif predictionMethod == 'proto':
-    prototypes = storage.loadPrototypesFromSqlite(args.prototypeDatabaseFilename)
+elif predictionMethod == 'mp':
+    if args.prototypeDatabaseFilename is None:
+        prototypes = storage.loadPrototypesFromSqlite(params.databaseFilename)
+    else:
+        prototypes = storage.loadPrototypesFromSqlite(args.prototypeDatabaseFilename)
     for p in prototypes:
-        p.getMovingObject().getPositions().computeCumulativeDistances()
+        p.getMovingObject().computeCumulativeDistances()
+    predictionParameters = prediction.PrototypePredictionParameters(prototypes, params.nPredictedTrajectories, 2., 0.5, 'cityblock', 10, params.constantSpeedPrototypePrediction, params.useFeaturesForPrediction)
+# else:
 # no else required, since parameters is required as argument
 
 # evasiveActionPredictionParameters = prediction.EvasiveActionPredictionParameters(params.maxPredictedSpeed, 
@@ -61,7 +66,7 @@
 #                                                                                  params.maxExtremeSteering,
 #                                                                                  params.useFeaturesForPrediction)
 
-objects = storage.loadTrajectoriesFromSqlite(params.databaseFilename, 'object', args.nObjects, withFeatures = (params.useFeaturesForPrediction or (predictionMethod == 'ps')))
+objects = storage.loadTrajectoriesFromSqlite(params.databaseFilename, 'object', args.nObjects, withFeatures = (params.useFeaturesForPrediction or predictionMethod == 'ps' or predictionMethod == 'mp'))
 # if params.useFeaturesForPrediction:
 #     features = storage.loadTrajectoriesFromSqlite(params.databaseFilename,'feature') # needed if normal adaptation
 #     for obj in objects:
@@ -70,7 +75,7 @@
 interactions = events.createInteractions(objects)
 for inter in interactions:
     inter.computeIndicators()
-    inter.computeCrossingsCollisions(predictionParameters, params.collisionDistance, params.predictionTimeHorizon, params.crossingZones, nProcesses = args.nProcesses)
+    inter.computeCrossingsCollisions(predictionParameters, params.collisionDistance, params.predictionTimeHorizon, params.crossingZones, nProcesses = args.nProcesses, debug = True)
 
 if args.computePET:
     for inter in interactions:
--- a/tracking.cfg	Tue Jul 18 18:01:16 2017 -0400
+++ b/tracking.cfg	Wed Jul 19 18:02:38 2017 -0400
@@ -91,7 +91,7 @@
 collision-distance = 1.8
 # option to compute crossing zones and predicted PET
 crossing-zones = false
-# prediction method: cv, na, ps
+# prediction method: cv, cvd, na, ps, mp
 prediction-method = na
 # number of predicted trajectories (use depends on prediction method)
 npredicted-trajectories = 10
@@ -107,3 +107,5 @@
 max-extreme-steering = 0.5
 # use feature positions and velocities for prediction
 use-features-prediction = true
+# use constant speed (motion pattern based prediction)
+constant-speed = false
\ No newline at end of file