def build_ukf(x, P, std_r, std_b, dt=1.0): ''' Build UKF. x: initial state. P: initial covariance matrix. std_r: standard var. of laser measurement. std_b: standard var. of IMU measurement. dt: time interval. Plus some defined functions as parameters. returns ukf. ''' # Calculate sigma points. points = MerweScaledSigmaPoints(n=6, alpha=0.001, beta=2, kappa=-3, subtract=residual_x) ukf = UKF(dim_x=6, dim_z=4, fx=move, hx=Hx, \ dt=dt, points=points, x_mean_fn=state_mean, \ z_mean_fn=z_mean, residual_x=residual_x, residual_z=residual_z) ukf.x = np.array(x) ukf.P = P ukf.R = np.diag([std_r ** 2, std_r ** 2, std_b ** 2, std_b ** 2]) q1 = Q_discrete_white_noise(dim=2, dt=dt, var=1.0) q2 = Q_discrete_white_noise(dim=2, dt=dt, var=1.0) q3 = Q_discrete_white_noise(dim=2, dt=dt, var=3.05 * pow(10, -4)) ukf.Q = block_diag(q1, q2, q3) # ukf.Q = np.eye(3) * 0.0001 return ukf
def unscented_kf(self, number=NUMBER): global Time P0 = np.diag([ 3e-2, 3e-2, 3e-2, 3e-6, 3e-6, 3e-6, 3e-2, 3e-2, 3e-2, 3e-6, 3e-6, 3e-6 ]) error = np.random.multivariate_normal(mean=np.zeros(12), cov=P0) X0 = np.hstack((HPOP_1[0], HPOP_2[0])) + error points = MerweScaledSigmaPoints(n=12, alpha=0.001, beta=2.0, kappa=-9) ukf = UKF(dim_x=12, dim_z=4, fx=self.state_equation, hx=self.measure_equation, dt=STEP, points=points) ukf.x = X0 ukf.P = P0 ukf.R = Rk ukf.Q = Qk XF, XP = [X0], [X0] print(error, "\n", Qk[0][0], "\n", Rk[0][0]) for i in range(1, number + 1): ukf.predict() Z = nav.measure_stk(i) ukf.update(Z) X_Up = ukf.x.copy() XF.append(X_Up) Time = Time + STEP XF = np.array(XF) return XF
def test_rts(): def fx(x, dt): A = np.eye(3) + dt * np.array([[0, 1, 0], [0, 0, 0], [0, 0, 0]]) f = np.dot(A, x) return f def hx(x): return np.sqrt(x[0]**2 + x[2]**2) dt = 0.05 sp = JulierSigmaPoints(n=3, kappa=1.) kf = UKF(3, 1, dt, fx=fx, hx=hx, points=sp) kf.Q *= 0.01 kf.R = 10 kf.x = np.array([0., 90., 1100.]) kf.P *= 100. radar = RadarSim(dt) t = np.arange(0, 20 + dt, dt) n = len(t) xs = np.zeros((n, 3)) random.seed(200) rs = [] #xs = [] for i in range(len(t)): r = radar.get_range() #r = GetRadar(dt) kf.predict() kf.update(z=[r]) xs[i, :] = kf.x rs.append(r) kf.x = np.array([0., 90., 1100.]) kf.P = np.eye(3) * 100 M, P = kf.batch_filter(rs) assert np.array_equal(M, xs), "Batch filter generated different output" Qs = [kf.Q] * len(t) M2, P2, K = kf.rts_smoother(Xs=M, Ps=P, Qs=Qs) if DO_PLOT: print(xs[:, 0].shape) plt.figure() plt.subplot(311) plt.plot(t, xs[:, 0]) plt.plot(t, M2[:, 0], c='g') plt.subplot(312) plt.plot(t, xs[:, 1]) plt.plot(t, M2[:, 1], c='g') plt.subplot(313) plt.plot(t, xs[:, 2]) plt.plot(t, M2[:, 2], c='g')
def test_linear_1d(): """ should work like a linear KF if problem is linear """ def fx(x, dt): F = np.array([[1., dt], [0, 1]]) return np.dot(F, x) def hx(x): return np.array([x[0]]) dt = 0.1 points = MerweScaledSigmaPoints(2, .1, 2., -1) kf = UKF(dim_x=2, dim_z=1, dt=dt, fx=fx, hx=hx, points=points) kf.x = np.array([1, 2]) kf.P = np.array([[1, 1.1], [1.1, 3]]) kf.R *= 0.05 kf.Q = np.array([[0., 0], [0., .001]]) z = np.array([2.]) kf.predict() kf.update(z) zs = [] for i in range(50): z = np.array([i + randn() * 0.1]) zs.append(z) kf.predict() kf.update(z) print('K', kf.K.T) print('x', kf.x)
def build_ukf(x0=None, P0=None, Q = None, R = None ): # build ukf if x0 is None: x0 = np.zeros(6) if P0 is None: P0 = np.diag([1e-6,1e-6,1e-6, 1e-1, 1e-1, 1e-1]) if Q is None: Q = np.diag([1e-4, 1e-4, 1e-2, 1e-1, 1e-1, 1e-1]) #xyhvw if R is None: R = np.diag([1e-1, 1e-1, 1e-1]) # xyh #spts = MerweScaledSigmaPoints(6, 1e-3, 2, 3-6, subtract=ukf_residual) spts = JulierSigmaPoints(6, 6-2, sqrt_method=np.linalg.cholesky, subtract=ukf_residual) ukf = UKF(6, 3, (1.0 / 30.), # dt guess ukf_hx, ukf_fx, spts, x_mean_fn=ukf_mean, z_mean_fn=ukf_mean, residual_x=ukf_residual, residual_z=ukf_residual) ukf.x = x0.copy() ukf.P = P0.copy() ukf.Q = Q ukf.R = R return ukf
def ukf_process(x, P, sigma_range, sigma_bearing, dt=1.0): """ construct Unscented Kalman Filter with the initial state x and the initial covaiance matrix P sigma_range: the std of laser range sensors sigma_bearing: the std of IMU """ # construct the sigma points points = MerweScaledSigmaPoints(n=3, alpha=0.001, beta=2, kappa=0, subtract=residual) # build the UKF based on previous functions ukf = UKF(dim_x=3, dim_z=3, fx=move, hx=Hx, dt=dt, points=points, x_mean_fn=state_mean, z_mean_fn=z_mean, residual_x=residual, residual_z=residual) # assign the parameters of ukf ukf.x = np.array(x) ukf.P = P ukf.R = np.diag([sigma_range**2, sigma_range**2, sigma_bearing**2]) ukf.Q = np.eye(3) * 0.0001 return ukf
def create_ukf(cmds, landmarks, sigma_vel, sigma_steer, sigma_range, sigma_bearing, ellipse_step=1, step=10): points = MerweScaledSigmaPoints(n=3, alpha=0.03, beta=2., kappa=0, subtract=residual_x, sqrt_method=sqrt_func) ukf = UKF(dim_x=3, dim_z=2 * len(landmarks), fx=move, hx=Hx, dt=dt, points=points, x_mean_fn=state_mean, z_mean_fn=z_mean, residual_x=residual_x, residual_z=residual_h) ukf.x = np.array([203.0, 1549.2, 1.34]) ukf.P = np.diag([100., 100., .5]) ukf.R = np.diag([sigma_range**2, sigma_bearing**2] * len(landmarks)) ukf.Q = np.diag([10.**2, 10.**2, 0.3**2]) return ukf
def run_localization( cmds, landmarks, sigma_vel, sigma_steer, sigma_range, sigma_bearing, ellipse_step=1, step=10): plt.figure() points = MerweScaledSigmaPoints(n=3, alpha=.00001, beta=2, kappa=0, subtract=residual_x) ukf = UKF(dim_x=3, dim_z=2*len(landmarks), fx=fx, hx=Hx, dt=dt, points=points, x_mean_fn=state_mean, z_mean_fn=z_mean, residual_x=residual_x, residual_z=residual_h) ukf.x = np.array([2, 6, .3]) ukf.P = np.diag([.1, .1, .05]) ukf.R = np.diag([sigma_range**2, sigma_bearing**2]*len(landmarks)) ukf.Q = np.eye(3)*0.0001 sim_pos = ukf.x.copy() # plot landmarks if len(landmarks) > 0: plt.scatter(landmarks[:, 0], landmarks[:, 1], marker='s', s=60) track = [] for i, u in enumerate(cmds): sim_pos = move(sim_pos, u, dt/step, wheelbase) track.append(sim_pos) if i % step == 0: ukf.predict(fx_args=u) if i % ellipse_step == 0: plot_covariance_ellipse( (ukf.x[0], ukf.x[1]), ukf.P[0:2, 0:2], std=6, facecolor='k', alpha=0.3) x, y = sim_pos[0], sim_pos[1] z = [] for lmark in landmarks: dx, dy = lmark[0] - x, lmark[1] - y d = sqrt(dx**2 + dy**2) + randn()*sigma_range bearing = atan2(lmark[1] - y, lmark[0] - x) a = (normalize_angle(bearing - sim_pos[2] + randn()*sigma_bearing)) z.extend([d, a]) ukf.update(z, hx_args=(landmarks,)) if i % ellipse_step == 0: plot_covariance_ellipse( (ukf.x[0], ukf.x[1]), ukf.P[0:2, 0:2], std=6, facecolor='g', alpha=0.8) track = np.array(track) plt.plot(track[:, 0], track[:,1], color='k', lw=2) plt.axis('equal') plt.title("UKF Robot localization") plt.show() return ukf
def myUKF(fx, hx, P, Q, R): points = MerweScaledSigmaPoints(n=4, alpha=.1, beta=2., kappa=-1.) kf = UKF(4, 2, dt, fx=fx, hx=hx, points=points) #(x_dimm, z_dimm,dt, hx, fx, sigmaPoints) kf.P = P kf.Q = Q kf.R = R kf.x = np.array([0., 90., 1100., 0.]) # initial gauss return kf
def test_vhartman(): """ Code provided by vhartman on github #172 https://github.com/rlabbe/filterpy/issues/172 """ def fx(x, dt): # state transition function - predict next state based # on constant velocity model x = vt + x_0 F = np.array([[1.]], dtype=np.float32) return np.dot(F, x) def hx(x): # measurement function - convert state into a measurement # where measurements are [x_pos, y_pos] return np.array([x[0]]) dt = 1.0 # create sigma points to use in the filter. This is standard for Gaussian processes points = MerweScaledSigmaPoints(1, alpha=1, beta=2., kappa=0.1) kf = UnscentedKalmanFilter(dim_x=1, dim_z=1, dt=dt, fx=fx, hx=hx, points=points) kf.x = np.array([0.]) # initial state kf.P = np.array([[1]]) # initial uncertainty kf.R = np.diag([1]) # 1 standard kf.Q = np.diag([1]) # 1 standard ekf = ExtendedKalmanFilter(dim_x=1, dim_z=1) ekf.F = np.array([[1]]) ekf.x = np.array([0.]) # initial state ekf.P = np.array([[1]]) # initial uncertainty ekf.R = np.diag([1]) # 1 standard ekf.Q = np.diag([1]) # 1 standard np.random.seed(0) zs = [[np.random.randn()] for i in range(50)] # measurements for z in zs: kf.predict() ekf.predict() assert np.allclose(ekf.P, kf.P) assert np.allclose(ekf.x, kf.x) kf.update(z) ekf.update(z, lambda x: np.array([[1]]), hx) assert np.allclose(ekf.P, kf.P) assert np.allclose(ekf.x, kf.x)
def estimateUKF(camPoses): points = MerweScaledSigmaPoints(3,.1,2.,0.) filter = UKF(3,3,0,h, f, points, sqrt_fn=None, x_mean_fn=state_mean, z_mean_fn=state_mean, residual_x=residual, residual_z=residual) filter.P = np.diag([0.04,0.04,0.003]) filter.Q = np.diag([(0.2)**2,(0.2)**2,(1*3.14/180)**2]) filter.R = np.diag([100,100,0.25]) Uposes = [[],[]] for i in range(len(speed)): x = filter.x Uposes[0].append(x[0]) Uposes[1].append(x[1]) filter.predict(fx_args=[speed[i],angle[i]*0.01745]) filter.update(z = [camPoses[0][i],camPoses[1][i],camPoses[2][i]]) return Uposes
def create(self, pose, *args, **kwargs): print 'CREATE!' ukf = UKF(**self.ukf_args) ukf._Q = self.Q.copy() ukf.Q = self.Q.copy() ukf.R = self.R.copy() ukf.x = pose #np.zeros(5, dtype=np.float32) #ukf.x[:3] = pose[:3] ukf.P = self.P.copy() # TODO : fill in more info, such as color(red/green/unknown), type(target/obs/unknown) self.est[self.p_idx] = UKFEstimate(pose, *args, ukf=ukf, **kwargs) self.p_idx += 1
def UKFinit(): global ukf ukf_fuse = [] p_std_x, p_std_y = 0.2, 0.2 v_std_x, v_std_y = 0.01, 0.01 a_std_x, a_std_y = 0.01, 0.01 dt = 0.0125 #80HZ sigmas = MerweScaledSigmaPoints(6, alpha=.1, beta=2., kappa=-1.0) ukf = UKF(dim_x=6, dim_z=6, fx=f_cv, hx=h_cv, dt=dt, points=sigmas) ukf.x = np.array([0., 0., 0., 0., 0., 0.]) ukf.R = np.diag([p_std_x, v_std_x, a_std_x, p_std_y, v_std_y, a_std_y]) ukf.Q[0:3, 0:3] = Q_discrete_white_noise(3, dt=dt, var=0.2) ukf.Q[3:6, 3:6] = Q_discrete_white_noise(3, dt=dt, var=0.2) ukf.P = np.diag([8, 2, 2, 5, 2, 2])
def UKFinit(): global ukf ukf_fuse = [] std_y, std_z = 0.01, 0.01 vstd_y = 0.1 vstd_z = 0.1 dt = 0.005 sigmas = MerweScaledSigmaPoints(4, alpha=.1, beta=2., kappa=-1.0) ukf = UKF(dim_x=4, dim_z=4, fx=f_cv, hx=h_cv, dt=dt, points=sigmas) ukf.x = np.array([0., 0., 0., 0.]) ukf.R = np.diag([std_y, vstd_y, std_z, vstd_z]) ukf.Q[0:2, 0:2] = Q_discrete_white_noise(2, dt=dt, var=0.2) ukf.Q[2:4, 2:4] = Q_discrete_white_noise(2, dt=dt, var=0.2) ukf.P = np.diag([3**2, 0.5, 3**2, 0.5])
def UKFinit(): global ukf p_std_x, p_std_y = 0.1, 0.1 v_std_x, v_std_y = 0.1, 0.1 dt = 0.0125 #80HZ sigmas = MerweScaledSigmaPoints(4, alpha=.1, beta=2., kappa=-1.0) ukf = UKF(dim_x=4, dim_z=4, fx=f_cv, hx=h_cv, dt=dt, points=sigmas) ukf.x = np.array([0., 0., 0., 0.]) ukf.R = np.diag([p_std_x, v_std_x, p_std_y, v_std_y]) ukf.Q[0:2, 0:2] = Q_discrete_white_noise(2, dt=dt, var=0.2) ukf.Q[2:4, 2:4] = Q_discrete_white_noise(2, dt=dt, var=0.2) ukf.P = np.diag([8, 1.5 ,5, 1.5])
def test_rts(): def fx(x, dt): A = np.eye(3) + dt * np.array ([[0, 1, 0], [0, 0, 0], [0, 0, 0]]) f = np.dot(A, x) return f def hx(x): return np.sqrt (x[0]**2 + x[2]**2) dt = 0.05 sp = JulierSigmaPoints(n=3, kappa=1.) kf = UKF(3, 1, dt, fx=fx, hx=hx, points=sp) kf.Q *= 0.01 kf.R = 10 kf.x = np.array([0., 90., 1100.]) kf.P *= 100. radar = RadarSim(dt) t = np.arange(0,20+dt, dt) n = len(t) xs = np.zeros((n,3)) random.seed(200) rs = [] #xs = [] for i in range(len(t)): r = radar.get_range() #r = GetRadar(dt) kf.predict() kf.update(z=[r]) xs[i,:] = kf.x rs.append(r) kf.x = np.array([0., 90., 1100.]) kf.P = np.eye(3)*100 M, P = kf.batch_filter(rs) assert np.array_equal(M, xs), "Batch filter generated different output" Qs = [kf.Q]*len(t) M2, P2, K = kf.rts_smoother(Xs=M, Ps=P, Qs=Qs)
def UKFinit(): global ukf ukf_fuse = [] p_std_yaw = 0.004 v_std_yaw = 0.008 dt = 0.0125 #80HZ sigmas = MerweScaledSigmaPoints(2, alpha=.1, beta=2., kappa=-1.0) ukf = UKF(dim_x=2, dim_z=2, fx=f_cv, hx=h_cv, dt=dt, points=sigmas) ukf.x = np.array([ 0., 0., ]) ukf.R = np.diag([p_std_yaw, v_std_yaw]) ukf.Q[0:2, 0:2] = Q_discrete_white_noise(2, dt=dt, var=0.2) ukf.P = np.diag([6.3, 1])
def ukf_process(x, P, sigma_range, sigma_bearing, dt=1.0): points = MerweScaledSigmaPoints(n=3, alpha=0.001, beta=2, kappa=0, subtract=residual) # build the UKF based on previous functions ukf = UKF(dim_x=3, dim_z=3, fx=move, hx=Hx, dt=dt, points=points, x_mean_fn=state_mean, z_mean_fn=z_mean, residual_x=residual, residual_z=residual) # assign the parameters of ukf ukf.x = np.array(x) ukf.P = P ukf.R = np.diag([sigma_range**2, sigma_range**2, sigma_bearing**2]) ukf.Q = np.eye(3)*0.0001 return ukf
def Unscentedfilter(zs): # Filter function points = MerweScaledSigmaPoints(2, alpha=.1, beta=2., kappa=1) ukf = UnscentedKalmanFilter(dim_x=2, dim_z=1, fx=fx, hx=hx, points=points, dt=dt) ukf.Q = array(([50, 0], [0, 50])) ukf.R = 100 ukf.P = eye(2) * 2 mu, cov = ukf.batch_filter(zs) x, _, _ = ukf.rts_smoother(mu, cov) return x[:, 0]
def UKFinit(): global ukf ukf_fuse = [] p_std_x = rospy.get_param('~p_std_x',0.005) v_std_x = rospy.get_param('~v_std_x',0.05) p_std_y = rospy.get_param('~p_std_y',0.005) v_std_y = rospy.get_param('~v_std_y',0.05) dt = rospy.get_param('~dt',0.01) #100HZ sigmas = MerweScaledSigmaPoints(4, alpha=.1, beta=2., kappa=-1.0) ukf = UKF(dim_x=4, dim_z=4, fx=f_cv, hx=h_cv, dt=dt, points=sigmas) ukf.x = np.array([0., 0., 0., 0.,]) ukf.R = np.diag([p_std_x, v_std_x, p_std_y, v_std_y]) ukf.Q[0:2, 0:2] = Q_discrete_white_noise(2, dt=dt, var=4.0) ukf.Q[2:4, 2:4] = Q_discrete_white_noise(2, dt=dt, var=4.0) ukf.P = np.diag([3, 1, 3, 1])
def test_1d(): def fx(x, dt): F = np.array([[1., dt], [0, 1]]) return np.dot(F, x) def hx(x): return np.array([[x[0]]]) ckf = CKF(dim_x=2, dim_z=1, dt=0.1, hx=hx, fx=fx) ckf.x = np.array([[1.], [2.]]) ckf.P = np.array([[1, 1.1], [1.1, 3]]) ckf.R = np.eye(1) * .05 ckf.Q = np.array([[0., 0], [0., .001]]) dt = 0.1 points = MerweScaledSigmaPoints(2, .1, 2., -1) kf = UKF(dim_x=2, dim_z=1, dt=dt, fx=fx, hx=hx, points=points) kf.x = np.array([1, 2]) kf.P = np.array([[1, 1.1], [1.1, 3]]) kf.R *= 0.05 kf.Q = np.array([[0., 0], [0., .001]]) for i in range(50): z = np.array([[i+randn()*0.1]]) #xx, pp, Sx = predict(f, x, P, Q) #x, P = update(h, z, xx, pp, R) ckf.predict() ckf.update(z) kf.predict() kf.update(z[0]) assert abs(ckf.x[0] -kf.x[0]) < 1e-10 assert abs(ckf.x[1] -kf.x[1]) < 1e-10 plt.show()
def test_1d(): def fx(x, dt): F = np.array([[1., dt], [0, 1]]) return np.dot(F, x) def hx(x): return x[0:1] ckf = CKF(dim_x=2, dim_z=1, dt=0.1, hx=hx, fx=fx) ckf.x = np.array([[1.], [2.]]) ckf.P = np.array([[1, 1.1], [1.1, 3]]) ckf.R = np.eye(1) * .05 ckf.Q = np.array([[0., 0], [0., .001]]) dt = 0.1 points = MerweScaledSigmaPoints(2, .1, 2., -1) kf = UKF(dim_x=2, dim_z=1, dt=dt, fx=fx, hx=hx, points=points) kf.x = np.array([1, 2]) kf.P = np.array([[1, 1.1], [1.1, 3]]) kf.R *= 0.05 kf.Q = np.array([[0., 0], [0., .001]]) s = Saver(kf) for i in range(50): z = np.array([[i+randn()*0.1]]) ckf.predict() ckf.update(z) kf.predict() kf.update(z[0]) assert abs(ckf.x[0] - kf.x[0]) < 1e-10 assert abs(ckf.x[1] - kf.x[1]) < 1e-10 s.save() # test mahalanobis a = np.zeros(kf.y.shape) maha = scipy_mahalanobis(a, kf.y, kf.SI) assert kf.mahalanobis == approx(maha) s.to_array()
def test_ukf_ekf_comparison(): def fx(x, dt): # state transition function - predict next state based # on constant velocity model x = vt + x_0 F = np.array([[1.]], dtype=np.float32) return np.dot(F, x) def hx(x): # measurement function - convert state into a measurement # where measurements are [x_pos, y_pos] return np.array([x[0]]) dt = 1.0 # create sigma points to use in the filter. This is standard for Gaussian processes points = MerweScaledSigmaPoints(1, alpha=1, beta=2., kappa=0.1) ukf = UnscentedKalmanFilter(dim_x=1, dim_z=1, dt=dt, fx=fx, hx=hx, points=points) ukf.x = np.array([0.]) # initial state ukf.P = np.array([[1]]) # initial uncertainty ukf.R = np.diag([1]) # 1 standard ukf.Q = np.diag([1]) # 1 standard ekf = ExtendedKalmanFilter(dim_x=1, dim_z=1) ekf.F = np.array([[1]]) ekf.x = np.array([0.]) # initial state ekf.P = np.array([[1]]) # initial uncertainty ekf.R = np.diag([1]) # 1 standard ekf.Q = np.diag([1]) # 1 standard np.random.seed(0) zs = [[np.random.randn()] for i in range(50)] # measurements for z in zs: ukf.predict() ekf.predict() assert np.allclose(ekf.P, ukf.P), 'ekf and ukf differ after prediction' ukf.update(z) ekf.update(z, lambda x: np.array([[1]]), hx) assert np.allclose(ekf.P, ukf.P), 'ekf and ukf differ after update'
def smooth(data: ndarray, dt: float): points = MerweScaledSigmaPoints(3, alpha=1e-3, beta=2.0, kappa=0) noisy_kalman = UnscentedKalmanFilter( dim_x=3, dim_z=1, dt=dt, hx=state_to_measurement, fx=state_transition, points=points, ) noisy_kalman.x = array([0, data[1], data[1] - data[0]], dtype="float32") noisy_kalman.R *= 20**2 # sensor variance noisy_kalman.P = diag([5**2, 5**2, 1**2]) # variance of the system noisy_kalman.Q = Q_discrete_white_noise(3, dt=dt, var=0.05) means, covariances = noisy_kalman.batch_filter(data) means[:, 1][means[:, 1] < 0] = 0 # clip velocity return means[:, 1]
def test_1d(): def fx(x, dt): F = np.array([[1., dt], [0, 1]]) return np.dot(F, x) def hx(x): return x[0:1] ckf = CKF(dim_x=2, dim_z=1, dt=0.1, hx=hx, fx=fx) ckf.x = np.array([[1.], [2.]]) ckf.P = np.array([[1, 1.1], [1.1, 3]]) ckf.R = np.eye(1) * .05 ckf.Q = np.array([[0., 0], [0., .001]]) dt = 0.1 points = MerweScaledSigmaPoints(2, .1, 2., -1) kf = UKF(dim_x=2, dim_z=1, dt=dt, fx=fx, hx=hx, points=points) kf.x = np.array([1, 2]) kf.P = np.array([[1, 1.1], [1.1, 3]]) kf.R *= 0.05 kf.Q = np.array([[0., 0], [0., .001]]) s = Saver(kf) for i in range(50): z = np.array([[i + randn() * 0.1]]) ckf.predict() ckf.update(z) kf.predict() kf.update(z[0]) assert abs(ckf.x[0] - kf.x[0]) < 1e-10 assert abs(ckf.x[1] - kf.x[1]) < 1e-10 s.save() # test mahalanobis a = np.zeros(kf.y.shape) maha = scipy_mahalanobis(a, kf.y, kf.SI) assert kf.mahalanobis == approx(maha) s.to_array()
def test_1d(): def fx(x, dt): F = np.array([[1., dt], [0, 1]]) return np.dot(F, x) def hx(x): return x[0:1] ckf = CKF(dim_x=2, dim_z=1, dt=0.1, hx=hx, fx=fx) ckf.x = np.array([[1.], [2.]]) ckf.P = np.array([[1, 1.1], [1.1, 3]]) ckf.R = np.eye(1) * .05 ckf.Q = np.array([[0., 0], [0., .001]]) dt = 0.1 points = MerweScaledSigmaPoints(2, .1, 2., -1) kf = UKF(dim_x=2, dim_z=1, dt=dt, fx=fx, hx=hx, points=points) kf.x = np.array([1, 2]) kf.P = np.array([[1, 1.1], [1.1, 3]]) kf.R *= 0.05 kf.Q = np.array([[0., 0], [0., .001]]) s = Saver(kf) for i in range(50): z = np.array([[i + randn() * 0.1]]) #xx, pp, Sx = predict(f, x, P, Q) #x, P = update(h, z, xx, pp, R) ckf.predict() ckf.update(z) kf.predict() kf.update(z[0]) assert abs(ckf.x[0] - kf.x[0]) < 1e-10 assert abs(ckf.x[1] - kf.x[1]) < 1e-10 s.save() s.to_array()
def test_linear_1d(): """ should work like a linear KF if problem is linear """ def fx(x, dt): F = np.array([[1., dt], [0, 1]], dtype=float) return np.dot(F, x) def hx(x): return np.array([x[0]]) dt = 0.1 points = MerweScaledSigmaPoints(2, .1, 2., -1) kf = UKF(dim_x=2, dim_z=1, dt=dt, fx=fx, hx=hx, points=points) kf.x = np.array([1, 2]) kf.P = np.array([[1, 1.1], [1.1, 3]]) kf.R *= 0.05 kf.Q = np.array([[0., 0], [0., .001]]) z = np.array([2.]) kf.predict() kf.update(z) zs = [] for i in range(50): z = np.array([i+randn()*0.1]) zs.append(z) kf.predict() kf.update(z) print('K', kf.K.T) print('x', kf.x)
def estimateUKF(camPoses): points = MerweScaledSigmaPoints(3, .1, 2., 0.) filter = UKF(3, 3, 0, h, f, points, sqrt_fn=None, x_mean_fn=state_mean, z_mean_fn=state_mean, residual_x=residual, residual_z=residual) filter.P = np.diag([0.04, 0.04, 0.003]) filter.Q = np.diag([(0.2)**2, (0.2)**2, (1 * 3.14 / 180)**2]) filter.R = np.diag([100, 100, 0.25]) Uposes = [[], []] for i in range(len(speed)): x = filter.x Uposes[0].append(x[0]) Uposes[1].append(x[1]) filter.predict(fx_args=[speed[i], angle[i] * 0.01745]) filter.update(z=[camPoses[0][i], camPoses[1][i], camPoses[2][i]]) return Uposes
def ukf_filter_without_register(x, filt_times, filepath, measurement_raw, timestamp_data): measurement = copy.deepcopy(measurement_raw) # In reverse Order if filt_times % 2 == 0: measurement = measurement[::-1, :] timestamp_data = timestamp_data[::-1, :] for i in range(1, measurement.shape[0]): measurement[measurement.shape[0] - i, 0:3] = -measurement[measurement.shape[0] - i - 1, 0:3] # measurement[i, 0:3] = -measurement[i, 0:3] dt = 0.1 points = MerweScaledSigmaPoints(11, alpha=.1, beta=2., kappa=-1) ukf = UKF(dim_x=11, dim_z=3, dt=dt, fx=ukf_f, hx=ukf_h, points=points) ukf.x = x[0:11] # initial state x_global = x[11:19] ukf.P *= 0.2 # initial uncertainty ukf.R = 1e-5 * np.diag(np.asarray([1, 1, 1])) if filt_times == 1: ukf.P = 1e-4 * np.diag( np.asarray([0.0001, 0.0001, 1, 1, 1, 1, 10, 10, 1, 1, 1])) ukf.Q = 1e-8 * np.diag( np.asarray([0.0001, 0.0001, 1, 1, 1, 1, 10, 10, 1, 1, 1])) else: ukf.P = 1e-4 * np.diag( np.asarray([0.001, 0.001, 0.001, 1, 1, 1, 10, 10, 1, 1, 1])) ukf.Q = 1e-8 * np.diag( np.asarray([0.001, 0.001, 0.001, 1, 1, 1, 10, 10, 1, 1, 1])) # shrink_list = [3, 5, 7] # shrink_index = bisect(shrink_list, filt_times) # ukf.P[6:8,:] /= (10**shrink_index) # ukf.Q[6:8,:] /= (10**shrink_index) # P[8:11,:] = P[8:11,:]/(10**shrink_index) # Q[8:11,:] = Q[8:11,:]/(10**shrink_index) # P[3:7] = P[3:7]/(10**shrink_index) # Q[3:7] = Q[3:7]/(10**shrink_index) x_log = np.zeros((measurement.shape[0], 19)) x_log[0, 0:11] = ukf.x x_log[0, 11:19] = x_global for i in range(measurement.shape[0] - 1): dtime = abs(timestamp_data[i + 1, 1] - timestamp_data[i, 1]) ukf.predict(dt=dtime) # z_measure[3:7] = target_quat_raw z_measure = measurement[i + 1, 3:7] ukf, x_global, _ = ukf_update(ukf, z_measure, x_global) x_global[0:4] = x_global[0:4] / np.linalg.norm(x_global[0:4]) x_global[4:8] = x_global[4:8] / np.linalg.norm(x_global[4:8]) x_log[i + 1, 0:11] = ukf.x x_log[i + 1, 11:19] = x_global np.savetxt(f"{filepath}ukf_log_all_{filt_times}.csv", x_log, delimiter=',') x[0:11] = ukf.x x[11:19] = x_global return x
track_offset = 30230 #tracking log is ~29998 ms behind left gopro track_data_log_offset = track_offset + stereo_offset left_reader = lr.LogReader(l_logname,l_first_data_time_ms) right_reader = lr.LogReader(r_logname,r_first_data_time_ms) track = tr.TrackingReader(track_fname,right_reader,track_data_log_offset,F,30,1,vid_fname=vid_fname) pos_init = left_reader.get_ekf_loc_1d(START_TIME) vel_init = left_reader.get_ekf_vel(START_TIME) att_init = np.deg2rad(left_reader.get_ekf_att(START_TIME)) att_vel_init = np.zeros(3) state_init = np.hstack((pos_init,vel_init,att_init,att_vel_init)) ukf = UKF(dim_x=12, dim_z=15, dt=1.0/30, fx=fx, hx=hx) ukf.P = np.diag([5,5,2, 2,2,2, .017,.017,.017, .1,.1,.1]) ukf.x = state_init ukf.Q = np.diag([.5,.5,.5, .5,.5,.5, .1,.1,.1, .1,.1,.1]) T = np.array([16.878, -7.1368, 0]) #Translation vector joining two inertial frames time = np.arange(START_TIME,END_TIME,dt) print time.shape,time[0],time[-1] d = np.linspace(20,40,time.shape[0]) zs = np.zeros((time.shape[0],15)) Rs = np.zeros((time.shape[0],15,15)) means = np.zeros((time.shape[0],12)) covs = np.zeros((time.shape[0],12,12)) cam_locs = np.zeros((time.shape[0],3)) ekf_locs = np.zeros((time.shape[0],3))
range_std = 5 # meters elevation_angle_std = math.radians(0.5) ac_pos = (0., 1000.) ac_vel = (100., 0.) radar_pos = (0., 0.) h_radar.radar_pos = radar_pos points = MerweScaledSigmaPoints(n=3, alpha=.1, beta=2., kappa=0.) kf = UKF(3, 2, dt, fx=f_radar, hx=h_radar, points=points) kf.Q[0:2, 0:2] = Q_discrete_white_noise(2, dt=dt, var=0.1) kf.Q[2, 2] = 0.1 kf.R = np.diag([range_std**2, elevation_angle_std**2]) kf.x = np.array([0., 90., 1100.]) kf.P = np.diag([300**2, 30**2, 150**2]) #randn.seed(200) pos = (0, 0) radar = RadarStation(pos, range_std, elevation_angle_std) ac = ACSim(ac_pos, (100, 0), 0.02) time = np.arange(0, 360 + dt, dt) xs = [] for _ in time: ac.update(dt) r = radar.noisy_reading(ac.pos) kf.predict() kf.update([r[0], r[1]]) xs.append(kf.x) plot_radar(xs, time)
dt = 20 # ms points = MerweScaledSigmaPoints(n=3, alpha=.1, beta=2., kappa=1.) ukf = UKF(testx.shape[0], testy.shape[0], dt, fx=f_force, hx=h_forceToNeural, points=points) #(x_dimm, z_dimm,dt, hx, fx, sigmaPoints) ukf.x = [0.05, 0, 0] # initial gauss # Optimize : P fstd = 0.5 ratestd = 0.01 yankstd = 0.001 P = np.diag([fstd**2, ratestd**2, yankstd**2]) ukf.P = P ukf.Q = Q ukf.R = R predict, fvar = [], [] for t in np.arange(target.shape[0]): ukf.predict() ukf.update(testy[:, t]) fvar.append(ukf.P[0, 0]) predict.append(ukf.x[0]) #(f,f',f'') criterion = nn.MSELoss() mse_loss = criterion(torch.from_numpy(np.asarray(predict)), torch.from_numpy(np.asarray(target))) figname = plot_dir + "ukfResult"
def two_radar_constalt(): dt = 0.05 def hx(x): r1, b1 = hx.R1.reading_of((x[0], x[2])) r2, b2 = hx.R2.reading_of((x[0], x[2])) return array([r1, b1, r2, b2]) pass def fx(x, dt): x_est = x.copy() x_est[0] += x[1] * dt return x_est vx = 100 / 1000 # meters/sec vz = 0.0 f = UKF(dim_x=3, dim_z=4, dt=dt, hx=hx, fx=fx, kappa=0) aircraft = ACSim((0, 1), (vx * dt, vz * dt), 0.00) range_std = 1 / 1000.0 bearing_std = 1 / 1000000.0 R1 = RadarStation((0, 0), range_std, bearing_std) R2 = RadarStation((60, 0), range_std, bearing_std) hx.R1 = R1 hx.R2 = R2 f.x = array([aircraft.pos[0], vx, aircraft.pos[1]]) f.R = np.diag([range_std ** 2, bearing_std ** 2, range_std ** 2, bearing_std ** 2]) q = Q_discrete_white_noise(2, var=0.0002, dt=dt) # q = np.array([[0,0],[0,0.0002]]) f.Q[0:2, 0:2] = q f.Q[2, 2] = 0.0002 f.P = np.diag([0.1, 0.01, 0.1]) * 0.1 track = [] zs = [] for i in range(int(500 / dt)): pos = aircraft.update() r1, b1 = R1.noisy_reading(pos) r2, b2 = R2.noisy_reading(pos) z = np.array([r1, b1, r2, b2]) zs.append(z) track.append(pos.copy()) zs = asarray(zs) xs, Ps = f.batch_filter(zs) ms, _, _ = f.rts_smoother(xs, Ps) track = asarray(track) time = np.arange(0, len(xs) * dt, dt) plt.figure() plt.subplot(311) plt.plot(time, track[:, 0]) plt.plot(time, xs[:, 0]) plt.legend(loc=4) plt.xlabel("time (sec)") plt.ylabel("x position (m)") plt.subplot(312) plt.plot(time, xs[:, 1] * 1000, label="UKF") plt.plot(time, ms[:, 1] * 1000, label="RTS") plt.legend(loc=4) plt.xlabel("time (sec)") plt.ylabel("velocity (m/s)") plt.subplot(313) plt.plot(time, xs[:, 2] * 1000, label="UKF") plt.plot(time, ms[:, 2] * 1000, label="RTS") plt.legend(loc=4) plt.xlabel("time (sec)") plt.ylabel("altitude (m)") plt.ylim([900, 1100]) for z in zs[:10]: p = R1.z_to_x(z[0], z[1]) # plt.scatter(p[0], p[1], marker='+', c='k') p = R2.z_to_x(z[2], z[3]) # plt.scatter(p[0], p[1], marker='+', c='b') plt.show()
def track_head(camera_matrix, markerss, world_markers): M = camera_matrix f_x, c_x = M[0, 0], M[0, -1] f_y, c_y = M[1, 1], M[1, -1] h = 1 w = 16 / 9 dt = 1 / 30 # TODO: Use the actual timestamps pos = np.array([0.0, 0.0, -2.0]) rot = np.array([0.0, 0.0, 0.0]) dpos = np.array([0.0, 0.0, 0.0]) drot = np.array([0.0, 0.0, 0.0]) state = np.array([ pos, rot, #dpos, drot ]) state_shape = state.shape M = np.prod(state_shape) points = JulierSigmaPoints(M) def project(state, world_positions): return project_plane_markers(world_positions, state.reshape(state_shape)).reshape(-1) kf = UnscentedKalmanFilter( dt=dt, dim_x=M, dim_z=len(world_markers) * 2, points=points, #fx=lambda X, dt: predict_state(X.reshape(4, -1), dt).reshape(-1), fx=lambda x, dt: x, hx=project, ) z_dim = 2 # This changes according to the measurement kf.P = np.eye(M) * 0.3 kf.x = state.reshape(-1).copy() # Initial state guess z_var = 0.05**2 kf.R = z_var # Observation variance dpos_var = 0.01**2 * dt drot_var = np.radians(1.0)**2 * dt #kf.Q = np.diag([0]*3 + [0]*3 + [dpos_var]*3 + [drot_var]*3) kf.Q = np.diag([dpos_var] * 3 + [drot_var] * 3) all_world_positions = [] for w in world_markers.values(): for v in w: all_world_positions.append(v) all_world_positions = np.array(all_world_positions) for row in markerss: markers = row['markers'] world_positions = [] screen_positions = [] for m in markers: try: world = world_markers[str(m['id'])] except KeyError: continue if m['id_confidence'] < 0.7: continue for w, s in zip(world, m['verts']): world_positions.append(w) screen_positions.append(s) world_positions = np.array(world_positions).reshape(-1, 2) screen_positions = np.array(screen_positions).reshape(-1, 2) screen_positions[:, 0] -= c_x screen_positions[:, 0] /= f_x screen_positions[:, 1] -= c_y screen_positions[:, 1] /= -f_y kf.predict() if len(world_positions) >= 0: measurement = screen_positions.reshape(-1) kf.update(measurement, R=np.diag([z_var] * len(measurement)), world_positions=world_positions) yield kf.x.copy(), kf.P.copy()
def test_rts(): def fx(x, dt): A = np.eye(3) + dt * np.array ([[0, 1, 0], [0, 0, 0], [0, 0, 0]]) f = np.dot(A, x) return f def hx(x): return np.sqrt (x[0]**2 + x[2]**2) dt = 0.05 kf = UKF(3, 1, dt, fx=fx, hx=hx, kappa=1.) kf.Q *= 0.01 kf.R = 10 kf.x = np.array([0., 90., 1100.]) kf.P *= 100. radar = RadarSim(dt) t = np.arange(0,20+dt, dt) n = len(t) xs = np.zeros((n,3)) random.seed(200) rs = [] #xs = [] for i in range(len(t)): r = radar.get_range() #r = GetRadar(dt) kf.predict() kf.update(z=[r]) xs[i,:] = kf.x rs.append(r) kf.x = np.array([0., 90., 1100.]) kf.P = np.eye(3)*100 M, P = kf.batch_filter(rs) assert np.array_equal(M, xs), "Batch filter generated different output" Qs = [kf.Q]*len(t) M2, P2, K = kf.rts_smoother(Xs=M, Ps=P, Qs=Qs) if DO_PLOT: print(xs[:,0].shape) plt.figure() plt.subplot(311) plt.plot(t, xs[:,0]) plt.plot(t, M2[:,0], c='g') plt.subplot(312) plt.plot(t, xs[:,1]) plt.plot(t, M2[:,1], c='g') plt.subplot(313) plt.plot(t, xs[:,2]) plt.plot(t, M2[:,2], c='g')
def two_radar_constvel(): dt = 5 def hx(x): r1, b1 = hx.R1.reading_of((x[0], x[2])) r2, b2 = hx.R2.reading_of((x[0], x[2])) return array([r1, b1, r2, b2]) pass def fx(x, dt): x_est = x.copy() x_est[0] += x[1] * dt x_est[2] += x[3] * dt return x_est f = UKF(dim_x=4, dim_z=4, dt=dt, hx=hx, fx=fx, kappa=0) aircraft = ACSim((100, 100), (0.1 * dt, 0.02 * dt), 0.002) range_std = 0.2 bearing_std = radians(0.5) R1 = RadarStation((0, 0), range_std, bearing_std) R2 = RadarStation((200, 0), range_std, bearing_std) hx.R1 = R1 hx.R2 = R2 f.x = array([100, 0.1, 100, 0.02]) f.R = np.diag([range_std ** 2, bearing_std ** 2, range_std ** 2, bearing_std ** 2]) q = Q_discrete_white_noise(2, var=0.002, dt=dt) # q = np.array([[0,0],[0,0.0002]]) f.Q[0:2, 0:2] = q f.Q[2:4, 2:4] = q f.P = np.diag([0.1, 0.01, 0.1, 0.01]) track = [] zs = [] for i in range(int(300 / dt)): pos = aircraft.update() r1, b1 = R1.noisy_reading(pos) r2, b2 = R2.noisy_reading(pos) z = np.array([r1, b1, r2, b2]) zs.append(z) track.append(pos.copy()) zs = asarray(zs) xs, Ps, Pxz = f.batch_filter(zs) ms, _, _ = f.rts_smoother2(xs, Ps, Pxz) track = asarray(track) time = np.arange(0, len(xs) * dt, dt) plt.figure() plt.subplot(411) plt.plot(time, track[:, 0]) plt.plot(time, xs[:, 0]) plt.legend(loc=4) plt.xlabel("time (sec)") plt.ylabel("x position (m)") plt.subplot(412) plt.plot(time, track[:, 1]) plt.plot(time, xs[:, 2]) plt.legend(loc=4) plt.xlabel("time (sec)") plt.ylabel("y position (m)") plt.subplot(413) plt.plot(time, xs[:, 1]) plt.plot(time, ms[:, 1]) plt.legend(loc=4) plt.ylim([0, 0.2]) plt.xlabel("time (sec)") plt.ylabel("x velocity (m/s)") plt.subplot(414) plt.plot(time, xs[:, 3]) plt.plot(time, ms[:, 3]) plt.ylabel("y velocity (m/s)") plt.legend(loc=4) plt.xlabel("time (sec)") plt.show()
def test_fixed_lag(): def fx(x, dt): A = np.eye(3) + dt * np.array ([[0, 1, 0], [0, 0, 0], [0, 0, 0]]) f = np.dot(A, x) return f def hx(x): return np.sqrt (x[0]**2 + x[2]**2) dt = 0.05 kf = UKF(3, 1, dt, fx=fx, hx=hx, kappa=0.) kf.Q *= 0.01 kf.R = 10 kf.x = np.array([0., 90., 1100.]) kf.P *= 1. radar = RadarSim(dt) t = np.arange(0,20+dt, dt) n = len(t) xs = np.zeros((n,3)) random.seed(200) rs = [] #xs = [] M = [] P = [] N =10 flxs = [] for i in range(len(t)): r = radar.get_range() #r = GetRadar(dt) kf.predict() kf.update(z=[r]) xs[i,:] = kf.x flxs.append(kf.x) rs.append(r) M.append(kf.x) P.append(kf.P) print(i) #print(i, np.asarray(flxs)[:,0]) if i == 20 and len(M) >= N: try: M2, P2, K = kf.rts_smoother(Xs=np.asarray(M)[-N:], Ps=np.asarray(P)[-N:]) flxs[-N:] = M2 #flxs[-N:] = [20]*N except: print('except', i) #P[-N:] = P2 kf.x = np.array([0., 90., 1100.]) kf.P = np.eye(3)*100 M, P = kf.batch_filter(rs) Qs = [kf.Q]*len(t) M2, P2, K = kf.rts_smoother(Xs=M, Ps=P, Qs=Qs) flxs = np.asarray(flxs) print(xs[:,0].shape) plt.figure() plt.subplot(311) plt.plot(t, xs[:,0]) plt.plot(t, flxs[:,0], c='r') plt.plot(t, M2[:,0], c='g') plt.subplot(312) plt.plot(t, xs[:,1]) plt.plot(t, flxs[:,1], c='r') plt.plot(t, M2[:,1], c='g') plt.subplot(313) plt.plot(t, xs[:,2]) plt.plot(t, flxs[:,2], c='r') plt.plot(t, M2[:,2], c='g')
def test_fixed_lag(): def fx(x, dt): A = np.eye(3) + dt * np.array([[0, 1, 0], [0, 0, 0], [0, 0, 0]]) f = np.dot(A, x) return f def hx(x): return np.sqrt(x[0]**2 + x[2]**2) dt = 0.05 sp = JulierSigmaPoints(n=3, kappa=0) kf = UKF(3, 1, dt, fx=fx, hx=hx, points=sp) kf.Q *= 0.01 kf.R = 10 kf.x = np.array([0., 90., 1100.]) kf.P *= 1. radar = RadarSim(dt) t = np.arange(0, 20 + dt, dt) n = len(t) xs = np.zeros((n, 3)) random.seed(200) rs = [] #xs = [] M = [] P = [] N = 10 flxs = [] for i in range(len(t)): r = radar.get_range() #r = GetRadar(dt) kf.predict() kf.update(z=[r]) xs[i, :] = kf.x flxs.append(kf.x) rs.append(r) M.append(kf.x) P.append(kf.P) print(i) #print(i, np.asarray(flxs)[:,0]) if i == 20 and len(M) >= N: try: M2, P2, K = kf.rts_smoother(Xs=np.asarray(M)[-N:], Ps=np.asarray(P)[-N:]) flxs[-N:] = M2 #flxs[-N:] = [20]*N except: print('except', i) #P[-N:] = P2 kf.x = np.array([0., 90., 1100.]) kf.P = np.eye(3) * 100 M, P = kf.batch_filter(rs) Qs = [kf.Q] * len(t) M2, P2, K = kf.rts_smoother(Xs=M, Ps=P, Qs=Qs) flxs = np.asarray(flxs) print(xs[:, 0].shape) plt.figure() plt.subplot(311) plt.plot(t, xs[:, 0]) plt.plot(t, flxs[:, 0], c='r') plt.plot(t, M2[:, 0], c='g') plt.subplot(312) plt.plot(t, xs[:, 1]) plt.plot(t, flxs[:, 1], c='r') plt.plot(t, M2[:, 1], c='g') plt.subplot(313) plt.plot(t, xs[:, 2]) plt.plot(t, flxs[:, 2], c='r') plt.plot(t, M2[:, 2], c='g')
#m = array([[5., 10], [10, 5]]) sigma_r = .3 sigma_h = .1#radians(.5)#np.radians(1) #sigma_steer = radians(10) dt = 0.1 wheelbase = 0.5 points = MerweScaledSigmaPoints(n=3, alpha=.1, beta=2, kappa=0, subtract=residual_x) #points = JulierSigmaPoints(n=3, kappa=3) ukf= UKF(dim_x=3, dim_z=2*len(m), fx=fx, hx=Hx, dt=dt, points=points, x_mean_fn=state_mean, z_mean_fn=z_mean, residual_x=residual_x, residual_z=residual_h) ukf.x = array([2, 6, .3]) ukf.P = np.diag([.1, .1, .05]) ukf.R = np.diag([sigma_r**2, sigma_h**2]* len(m)) ukf.Q =np.eye(3)*.00001 u = array([1.1, 0.]) xp = ukf.x.copy() plt.cla() plt.scatter(m[:, 0], m[:, 1]) cmds = [[v, .0] for v in np.linspace(0.001, 1.1, 30)] cmds.extend([cmds[-1]]*50)
""" takes a state variable and returns the measurement that would correspond to that state. """ px = landmark[0] py = landmark[1] dist = np.sqrt((px - x[0])**2 + (py - x[1])**2) Hx = array([dist, atan2(py - x[1], px - x[0]) - x[2]]) return Hx points = MerweScaledSigmaPoints(n=3, alpha=1.e-3, beta=2, kappa=0) ukf= UKF(dim_x=3, dim_z=2, fx=fx, hx=Hx, dt=dt, points=points, x_mean_fn=state_mean, z_mean_fn=z_mean, residual_x=residual_x, residual_z=residual_h) ukf.x = array([2, 6, .3]) ukf.P = np.diag([.1, .1, .2]) ukf.R = np.diag([sigma_r**2, sigma_h**2]) ukf.Q = np.zeros((3,3)) u = array([1.1, .01]) xp = ukf.x.copy() plt.figure() plt.scatter(m[:, 0], m[:, 1]) for i in range(200): xp = move(xp, u, dt/10., wheelbase) # simulate robot plt.plot(xp[0], xp[1], ',', color='g')
def create_ukf(vehicle, landmarks, P0, Q, dt, extents): def f(x, dt, u=np.zeros(2), extents=extents): vehicle.x = x.copy() print(u, dt) vehicle.move(u=u, dt=dt, extents=extents) return vehicle.x def h(x, landmark=None): assert landmark is not None hx = np.empty(2) lx, ly = landmark hx[0] = np.sqrt((lx - x[0])**2 + (ly - x[1])**2) hx[1] = np.arctan2(ly - x[1], lx - x[0]) return hx def residual_h(z, h): """Subtract [range, bearing] vectors, accounting for angle""" y = z - h y[1] = mpi_to_pi(y[1]) wrap(y, extents) return y def residual_x(xa, xb): """Subtract [x, y, phi] vectors, accounting for angle""" dx = xa - xb dx[2] = mpi_to_pi(dx[2]) wrap(dx, extents) return dx def state_mean(sigmas, w_m): x = np.empty(3) # This is a hack (and not a very good one) to handle periodic boundary # crossings. Seems to help a little. std = np.std(sigmas[:, :2]) if std > (extents[1] - extents[0]) / 4: x[:2] = sigmas[0, :2] else: x[0] = np.dot(sigmas[:, 0], w_m) x[1] = np.dot(sigmas[:, 1], w_m) sum_sin = np.dot(np.sin(sigmas[:, 2]), w_m) sum_cos = np.dot(np.cos(sigmas[:, 2]), w_m) x[2] = np.arctan2(sum_sin, sum_cos) wrap(x, extents) return x def z_mean(sigmas, w_m): z_count = sigmas.shape[1] x = np.zeros(z_count) for z in range(0, z_count, 2): sum_sin = np.dot(np.sin(sigmas[:, z + 1]), w_m) sum_cos = np.dot(np.cos(sigmas[:, z + 1]), w_m) x[z] = np.dot(sigmas[:, z], w_m) x[z + 1] = np.arctan2(sum_sin, sum_cos) return x points = MerweScaledSigmaPoints(n=3, alpha=1e-3, beta=2, kappa=0, subtract=residual_x) ukf = UKF( dim_x=3, dim_z=2, fx=f, hx=h, dt=dt, points=points, x_mean_fn=state_mean, z_mean_fn=z_mean, residual_x=residual_x, residual_z=residual_h, ) ukf.x = vehicle.x.copy() ukf.P = P0.copy() ukf.Q = Q # This large scale factor is theoretically unjustified. # TODO: without it, the sim crashes. Figure this out! ukf.R = 1e5 * np.diag([vehicle.range_sigma**2, vehicle.bearing_sigma**2]) # ukf.R = np.diag([vehicle.range_sigma**2, vehicle.bearing_sigma**2]) return ukf
return x def residual(a, b): y = a - b y[2] = normalize_angle(y[2]) return y def f(x,dt,u): """Estimate the non-linear state of the system""" #print ((u[0]/self.L)*math.tan(u[1])) return np.array([x[0]+u[0]*math.cos(x[2]), x[1]+u[0]*math.sin(x[2]), x[2]+((u[0]/1)*math.tan(u[1]))]) def h(z): return z points = MerweScaledSigmaPoints(3,.001,2.,0.) filter = UKF(3,3,0,h, f, points, sqrt_fn=None, x_mean_fn=state_mean, z_mean_fn=state_mean, residual_x=residual, residual_z=residual) filter.P = np.diag([0.04,0.04,1]) filter.Q = np.diag([(0.2)**2,(0.2)**2,(1*3.14/180)**2]) filter.R = np.diag([100,100,0.25]) robot = vehicle.Vehicle(1,50) #create a robot robot.setOdometry(True) #configure its odometer robot.setOdometryVariance([0.2,1]) speed,angle = [],[] for a in xrange(4): #create a retangular path for i in xrange(400): angle.append(0) for i in xrange(9): angle.append(10) for i in xrange(len(angle)): #set the speed to a constant along the path speed.append(1)
def register_and_filter_once(x, filt_times): start_frame = 48 end_frame = 12 skip = 1 filepath = "./20210312_3axis/" pose_data = np.genfromtxt(f'{filepath}point_cloud_pose.txt', delimiter=',') timestamp_data = np.genfromtxt(f'{filepath}timestamp.txt', delimiter=',') pose_data = pose_data[start_frame:-end_frame:skip, :] measurement_data = np.genfromtxt(f'{filepath}registration_measurement.csv', delimiter=',') measurement_data = measurement_data[::skip, :] pose_data[:, 6:10] = measurement_data[::skip, 3:7] timestamp_data = timestamp_data[start_frame:-end_frame:skip, :] pose_data = continous_quat(pose_data) # filepath = "./test_pointcloud/" # pose_data = np.genfromtxt(f'{filepath}blensor_data_csv.txt', delimiter=',') # pose_data = np.concatenate((np.zeros((pose_data.shape[0],6)), pose_data), axis=1) # arange_data = np.arange(pose_data.shape[0]).reshape((pose_data.shape[0],1)) # timestamp_data = np.concatenate((arange_data, arange_data*0.05), axis=1) # pose_data = pose_data[::skip,:] # timestamp_data = timestamp_data[::skip,:] quat0_inv = quat_inv(pose_data[0, 6:10]) for i in range(pose_data.shape[0]): pose_data[i, 6:10] = quaternion_mul_num(pose_data[i, 6:10], quat0_inv) # In reverse Order if filt_times % 2 == 0: pose_data = pose_data[::-1, :] timestamp_data = timestamp_data[::-1, :] measurement_data[:, 0:3] = -measurement_data[::-1, 0:3] source_quat_zero_raw = pose_data[0, 6:10] R = 1e-6 * np.diag(np.asarray([1, 1, 1])) P = 1e-4 * np.diag( np.asarray([0.001, 0.001, 0.001, 1, 1, 1, 10, 10, 1, 1, 1])) Q = 1e-8 * np.diag( np.asarray([0.001, 0.001, 0.001, 1, 1, 1, 10, 10, 1, 1, 1])) # shrink_list = [3, 5, 7] # shrink_index = bisect(shrink_list, filt_times) # P[7:9,:] = P[7:9,:]/(10**shrink_index) # Q[7:9,:] = Q[7:9,:]/(10**shrink_index) # P[0:6]*=skip**2 # Q[0:6]*=skip**2 P[0:3] *= 1000 Q[0:3] *= 1000 x_log = np.zeros((pose_data.shape[0], 19)) x_log[0, :] = x #UKF setting points = MerweScaledSigmaPoints(11, alpha=.1, beta=2., kappa=-1) ukf = UKF(dim_x=11, dim_z=3, dt=0.1, fx=ukf_f, hx=ukf_h, points=points) ukf.x = x[0:11] # initial state ukf.P = P ukf.Q = Q ukf.R = R x_global = x[11:19] # w_body = np.zeros((pose_data.shape[0]-1, 3)) # for i in range(w_body.shape[0]): # w_body[i, :] = get_w_in_body_frame(pose_data[i,6:10], pose_data[i+1,6:10], timestamp_data[i+1, 1] - timestamp_data[i, 1]) source_s_root = 1 now_quat = source_quat_zero_raw register_log = np.zeros((pose_data.shape[0], 4)) dq_real_log = np.zeros((pose_data.shape[0] - 1, 4)) dq_correct_log = np.zeros((pose_data.shape[0] - 1, 4)) register_log[0, :] = now_quat loop_start_R = Rotation.from_quat(to_scalar_last(now_quat)) loop_angle_log = np.zeros((pose_data.shape[0], )) for i in range(pose_data.shape[0] - 1): source_quat_raw = pose_data[i, 6:10] target_quat_raw = pose_data[i + 1, 6:10] source_quat = np.zeros((4, )) target_quat = np.zeros((4, )) source_quat[3] = source_quat_raw[0] source_quat[0:3] = source_quat_raw[1:4] target_quat[3] = target_quat_raw[0] target_quat[0:3] = target_quat_raw[1:4] sourceR = Rotation.from_quat(source_quat) targetR = Rotation.from_quat(target_quat) nowR_from_loop_start = targetR * loop_start_R.inv() nowR_from_loop_start_angle = np.linalg.norm( nowR_from_loop_start.as_rotvec()) loop_angle_log[i] = nowR_from_loop_start_angle dR_real = targetR * sourceR.inv() dq_real = to_scalar_first(dR_real.as_quat()) dq_real_log[i, :] = dq_real dtime = abs(timestamp_data[i + 1, 1] - timestamp_data[i, 1]) # x_predict, P = ekf_predict(x, P, Q, dtime) x_predict, P = mekf_predict(x, P, Q, dtime) # ukf.predict(dt=dtime) # point to plane ICP dq_estimate = dR_real.as_quat() if dq_estimate[3] > 0.5: dq_estimate = dq_estimate else: dq_estimate = -dq_estimate z_measure = np.zeros((7, )) z_measure[0:3] = dq_estimate[0:3] # z_measure[3:7] = quaternion_mul_num(to_scalar_first(dq_estimate), now_quat) z_measure[3:7] = target_quat_raw # x_correct, P, z_correct = ekf_update(x, x_predict, P, z_measure, R, dtime) x_correct, P, z_correct = mekf_update(x_predict, P, measurement_data[i + 1, 0:3], R, dtime) # ukf, x_global, _ = ukf_update(ukf, z_measure[3:7], x_global) # dq_correct = np.asarray([z_correct[0],z_correct[1],z_correct[2],1]) # dR_correct = Rotation.from_quat(dq_correct/np.linalg.norm(dq_correct)) x_correct = mekf_normalize_state(x_correct) x_log[i + 1, :] = x_correct x = x_correct # x_global[0:4] = x_global[0:4]/np.linalg.norm(x_global[0:4]) # x_global[4:8] = x_global[4:8]/np.linalg.norm(x_global[4:8]) # x_log[i+1,0:11] = ukf.x # x_log[i+1,11:19] = x_global # now_quat = quaternion_mul_num(to_scalar_first(dq_correct), now_quat) # now_quat = z_correct[3:7] # register_log[i+1, :] = now_quat # dq_correct_log[i,:] = to_scalar_first(dq_correct) np.savetxt(f"{filepath}mekf_log_ground_truth_{filt_times}.csv", x_log, delimiter=',') # x[0:11] = ukf.x # x[11:19] = x_global return x