#!/usr/bin/env python
import numpy as np
getting ready for Python 3 (#619)
* tabs to spaces
python 2 to 3: https://portingguide.readthedocs.io/en/latest/syntax.html#tabs-and-spaces
* use the new except syntax
python 2 to 3: https://portingguide.readthedocs.io/en/latest/exceptions.html#the-new-except-syntax
* make relative imports absolute
python 2 to 3: https://portingguide.readthedocs.io/en/latest/imports.html#absolute-imports
* Queue renamed to queue in python 3
Use the six compatibility library to support both python 2 and 3: https://portingguide.readthedocs.io/en/latest/stdlib-reorg.html#renamed-modules
* replace dict.has_key() with in
python 2 to 3: https://portingguide.readthedocs.io/en/latest/dicts.html#removed-dict-has-key
* make dict views compatible with python 3
python 2 to 3: https://portingguide.readthedocs.io/en/latest/dicts.html#dict-views-and-iterators
Where needed, wrapping things that will be a view in python 3 with a list(). For example, if it's accessed with []
Python 3 has no iter*() methods, so just using the values() instead of itervalues() as long as it's not too performance intensive. Note that any minor performance hit of using a list instead of a view will go away when switching to python 3. If it is intensive, we could use the six version.
* Explicitly use truncating division
python 2 to 3: https://portingguide.readthedocs.io/en/latest/numbers.html#division
python 3 treats / as float division. When we want the result to be an integer, use //
* replace map() with list comprehension where a list result is needed.
In python 3, map() returns an iterator.
python 2 to 3: https://portingguide.readthedocs.io/en/latest/iterators.html#new-behavior-of-map-and-filter
* replace filter() with list comprehension
In python 3, filter() returns an interatoooooooooooor.
python 2 to 3: https://portingguide.readthedocs.io/en/latest/iterators.html#new-behavior-of-map-and-filter
* wrap zip() in list() where we need the result to be a list
python 2 to 3: https://portingguide.readthedocs.io/en/latest/iterators.html#new-behavior-of-zip
* clean out some lint
Removes these pylint warnings:
************* Module selfdrive.car.chrysler.chryslercan
W: 15, 0: Unnecessary semicolon (unnecessary-semicolon)
W: 16, 0: Unnecessary semicolon (unnecessary-semicolon)
W: 25, 0: Unnecessary semicolon (unnecessary-semicolon)
************* Module common.dbc
W:101, 0: Anomalous backslash in string: '\?'. String constant might be missing an r prefix. (anomalous-backslash-in-string)
************* Module selfdrive.car.gm.interface
R:102, 6: Redefinition of ret.minEnableSpeed type from float to int (redefined-variable-type)
R:103, 6: Redefinition of ret.mass type from int to float (redefined-variable-type)
************* Module selfdrive.updated
R: 20, 6: Redefinition of r type from int to str (redefined-variable-type)
6 years ago
from selfdrive . locationd . kalman import loc_local_model
getting ready for Python 3 (#619)
* tabs to spaces
python 2 to 3: https://portingguide.readthedocs.io/en/latest/syntax.html#tabs-and-spaces
* use the new except syntax
python 2 to 3: https://portingguide.readthedocs.io/en/latest/exceptions.html#the-new-except-syntax
* make relative imports absolute
python 2 to 3: https://portingguide.readthedocs.io/en/latest/imports.html#absolute-imports
* Queue renamed to queue in python 3
Use the six compatibility library to support both python 2 and 3: https://portingguide.readthedocs.io/en/latest/stdlib-reorg.html#renamed-modules
* replace dict.has_key() with in
python 2 to 3: https://portingguide.readthedocs.io/en/latest/dicts.html#removed-dict-has-key
* make dict views compatible with python 3
python 2 to 3: https://portingguide.readthedocs.io/en/latest/dicts.html#dict-views-and-iterators
Where needed, wrapping things that will be a view in python 3 with a list(). For example, if it's accessed with []
Python 3 has no iter*() methods, so just using the values() instead of itervalues() as long as it's not too performance intensive. Note that any minor performance hit of using a list instead of a view will go away when switching to python 3. If it is intensive, we could use the six version.
* Explicitly use truncating division
python 2 to 3: https://portingguide.readthedocs.io/en/latest/numbers.html#division
python 3 treats / as float division. When we want the result to be an integer, use //
* replace map() with list comprehension where a list result is needed.
In python 3, map() returns an iterator.
python 2 to 3: https://portingguide.readthedocs.io/en/latest/iterators.html#new-behavior-of-map-and-filter
* replace filter() with list comprehension
In python 3, filter() returns an interatoooooooooooor.
python 2 to 3: https://portingguide.readthedocs.io/en/latest/iterators.html#new-behavior-of-map-and-filter
* wrap zip() in list() where we need the result to be a list
python 2 to 3: https://portingguide.readthedocs.io/en/latest/iterators.html#new-behavior-of-zip
* clean out some lint
Removes these pylint warnings:
************* Module selfdrive.car.chrysler.chryslercan
W: 15, 0: Unnecessary semicolon (unnecessary-semicolon)
W: 16, 0: Unnecessary semicolon (unnecessary-semicolon)
W: 25, 0: Unnecessary semicolon (unnecessary-semicolon)
************* Module common.dbc
W:101, 0: Anomalous backslash in string: '\?'. String constant might be missing an r prefix. (anomalous-backslash-in-string)
************* Module selfdrive.car.gm.interface
R:102, 6: Redefinition of ret.minEnableSpeed type from float to int (redefined-variable-type)
R:103, 6: Redefinition of ret.mass type from int to float (redefined-variable-type)
************* Module selfdrive.updated
R: 20, 6: Redefinition of r type from int to str (redefined-variable-type)
6 years ago
from selfdrive . locationd . kalman . kalman_helpers import ObservationKind
from selfdrive . locationd . kalman . ekf_sym import EKF_sym
class States ( object ) :
VELOCITY = slice ( 0 , 3 ) # device frame velocity in m/s
ANGULAR_VELOCITY = slice ( 3 , 6 ) # roll, pitch and yaw rates in device frame in radians/s
GYRO_BIAS = slice ( 6 , 9 ) # roll, pitch and yaw biases
ODO_SCALE = slice ( 9 , 10 ) # odometer scale
ACCELERATION = slice ( 10 , 13 ) # Acceleration in device frame in m/s**2
class LocLocalKalman ( object ) :
def __init__ ( self ) :
x_initial = np . array ( [ 0 , 0 , 0 ,
0 , 0 , 0 ,
0 , 0 , 0 ,
1 ,
0 , 0 , 0 ] )
# state covariance
P_initial = np . diag ( [ 10 * * 2 , 10 * * 2 , 10 * * 2 ,
1 * * 2 , 1 * * 2 , 1 * * 2 ,
0.05 * * 2 , 0.05 * * 2 , 0.05 * * 2 ,
0.02 * * 2 ,
1 * * 2 , 1 * * 2 , 1 * * 2 ] )
# process noise
Q = np . diag ( [ 0.0 * * 2 , 0.0 * * 2 , 0.0 * * 2 ,
.01 * * 2 , .01 * * 2 , .01 * * 2 ,
( 0.005 / 100 ) * * 2 , ( 0.005 / 100 ) * * 2 , ( 0.005 / 100 ) * * 2 ,
( 0.02 / 100 ) * * 2 ,
3 * * 2 , 3 * * 2 , 3 * * 2 ] )
self . obs_noise = { ObservationKind . ODOMETRIC_SPEED : np . atleast_2d ( 0.2 * * 2 ) ,
ObservationKind . PHONE_GYRO : np . diag ( [ 0.025 * * 2 , 0.025 * * 2 , 0.025 * * 2 ] ) }
# MSCKF stuff
self . dim_state = len ( x_initial )
self . dim_main = self . dim_state
name = ' loc_local '
loc_local_model . gen_model ( name , self . dim_state )
# init filter
self . filter = EKF_sym ( name , Q , x_initial , P_initial , self . dim_main , self . dim_main )
@property
def x ( self ) :
return self . filter . state ( )
@property
def t ( self ) :
return self . filter . filter_time
@property
def P ( self ) :
return self . filter . covs ( )
def predict ( self , t ) :
if self . t :
# Does NOT modify filter state
return self . filter . _predict ( self . x , self . P , t - self . t ) [ 0 ]
else :
raise RuntimeError ( " Request predict on filter with uninitialized time " )
def rts_smooth ( self , estimates ) :
return self . filter . rts_smooth ( estimates , norm_quats = True )
def init_state ( self , state , covs_diag = None , covs = None , filter_time = None ) :
if covs_diag is not None :
P = np . diag ( covs_diag )
elif covs is not None :
P = covs
else :
P = self . filter . covs ( )
self . filter . init_state ( state , P , filter_time )
def predict_and_observe ( self , t , kind , data ) :
if len ( data ) > 0 :
data = np . atleast_2d ( data )
if kind == ObservationKind . CAMERA_ODO_TRANSLATION :
r = self . predict_and_update_odo_trans ( data , t , kind )
elif kind == ObservationKind . CAMERA_ODO_ROTATION :
r = self . predict_and_update_odo_rot ( data , t , kind )
elif kind == ObservationKind . ODOMETRIC_SPEED :
r = self . predict_and_update_odo_speed ( data , t , kind )
else :
r = self . filter . predict_and_update_batch ( t , kind , data , self . get_R ( kind , len ( data ) ) )
return r
def get_R ( self , kind , n ) :
obs_noise = self . obs_noise [ kind ]
dim = obs_noise . shape [ 0 ]
R = np . zeros ( ( n , dim , dim ) )
for i in xrange ( n ) :
R [ i , : , : ] = obs_noise
return R
def predict_and_update_odo_speed ( self , speed , t , kind ) :
z = np . array ( speed )
R = np . zeros ( ( len ( speed ) , 1 , 1 ) )
for i , _ in enumerate ( z ) :
R [ i , : , : ] = np . diag ( [ 0.2 * * 2 ] )
return self . filter . predict_and_update_batch ( t , kind , z , R )
def predict_and_update_odo_trans ( self , trans , t , kind ) :
z = trans [ : , : 3 ]
R = np . zeros ( ( len ( trans ) , 3 , 3 ) )
for i , _ in enumerate ( z ) :
R [ i , : , : ] = np . diag ( trans [ i , 3 : ] * * 2 )
return self . filter . predict_and_update_batch ( t , kind , z , R )
def predict_and_update_odo_rot ( self , rot , t , kind ) :
z = rot [ : , : 3 ]
R = np . zeros ( ( len ( rot ) , 3 , 3 ) )
for i , _ in enumerate ( z ) :
R [ i , : , : ] = np . diag ( rot [ i , 3 : ] * * 2 )
return self . filter . predict_and_update_batch ( t , kind , z , R )
if __name__ == " __main__ " :
LocLocalKalman ( )