Advertisement
Guest User

kalman_pravi

a guest
Jan 23rd, 2019
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.05 KB | None | 0 0
  1. #!/usr/bin/env python
  2. import csv
  3. import rospy
  4. from nav_msgs.msg import Odometry
  5. from geometry_msgs.msg import Pose
  6. from sensor_msgs.msg import LaserScan
  7. from tf.transformations import euler_from_quaternion as e2q
  8. from math import sin, cos, sqrt, atan2, isnan
  9. from numpy.linalg import multi_dot, inv
  10. from numpy import pi
  11. import numpy as np
  12. import time
  13. import rospkg
  14. from Astarlib import show_path
  15. from std_msgs.msg import Float64
  16.  
  17. class prosireni_kalman():
  18.     def __init__(self):
  19.         self.zakret_sonara = [4.71]
  20.         self.ranges = [0, 0, 0, 0, 0, 0, 0, 0]
  21.         self.pose_x = 0
  22.         self.pose_y = 0
  23.         self.yaw = 0
  24.         self.linear_x = 0
  25.         self.angular_z = 0
  26.         self.x_hat = [0,0,0]
  27.         self.P_k = np.matrix([
  28.             [0.1, 0, 0],
  29.             [0, 0.1, 0],
  30.             [0, 0, 0.05]
  31.         ])
  32.         self.T = 0.1
  33.         #korijen od var_deltaTheta = sigma2
  34.         self.var_deltaTheta = 0.0575
  35.         self.var_D = 0.05
  36.         self.var_sonara = 0.025
  37.         self.lista_prepreka = []
  38.         self.cellsize = 0.03
  39.         self.dimenzija_celije = 1./self.cellsize
  40.         self.th3db = 0.025
  41.         self.odometrija = False
  42.         binOccGrid = np.zeros([100, 100])
  43.  
  44.         rospack = rospkg.RosPack()
  45.         pkg_path = rospack.get_path('mobile_robotics')
  46.         reader = csv.reader(open(pkg_path + "/shit_map.csv"))
  47.         for i,row in enumerate(reader):
  48.             for j,el in enumerate(row):
  49.                 if float(el)<0.64:
  50.                     binOccGrid[i][j] = 0
  51.                 else:
  52.                     binOccGrid[i][j] = 1
  53.                     # x koordinata je j
  54.                     self.lista_prepreka.append([j/self.cellsize+self.dimenzija_celije/2.,
  55.                                                 (260-i)/self.cellsize+self.dimenzija_celije/2.])
  56.  
  57.         show_path(binOccGrid)
  58.         sub_odom_noise = rospy.Subscriber('/odom_noise', Odometry, self.odom_noise_callback)
  59.         sub_odom_noise = rospy.Subscriber('/ground_truth_pose', Odometry, self.gt_cb)
  60.         sub_scan = rospy.Subscriber('/scan', Float64, self.laser_scan_callback)
  61.  
  62.         self.pub_x_k = rospy.Publisher('/x_hat', Pose, queue_size=1)
  63.         self.pub_x_k_msg = Pose()
  64.  
  65.         self.pub_Pdet = rospy.Publisher('/P_det', Float64, queue_size=1)
  66.         self.pub_Ptrace = rospy.Publisher('/P_trace', Float64, queue_size=1)
  67.         self.msg_Pdet = Float64()
  68.         self.msg_Ptrace = Float64()
  69.        
  70.     def odom_noise_callback(self, data):
  71.         self.odometrija = True
  72.         #self.pose_x = data.pose.pose.position.x
  73.         #self.pose_y = data.pose.pose.position.y
  74.         #self.yaw = data.pose.pose.position.z # in matlab there is calculated yaw
  75.         #self.yaw = e2q([data.pose.pose.orientation.x, data.pose.pose.orientation.y, data.pose.pose.orientation.z, data.pose.pose.orientation.w])[2]
  76.         self.linear_x = data.twist.twist.linear.x
  77.         self.angular_z = data.twist.twist.angular.z
  78.  
  79.     def gt_cb(self, data):
  80.         self.yaw_gt = e2q([data.pose.pose.orientation.x, data.pose.pose.orientation.y, data.pose.pose.orientation.z, data.pose.pose.orientation.w])[2]
  81.        
  82.     def laser_scan_callback(self, data):
  83.         self.ranges = [data.data]
  84.  
  85.     def model_robota(self, x, y, theta, D, deltaTheta, w_theta, w_D):
  86.         '''
  87.        :param x:
  88.        :param y:
  89.        :param theta:
  90.        :param D:
  91.        :param deltaTheta:
  92.        :param w_theta:
  93.        :param w_D:
  94.        :return: returns apriori prediction x_hat_minus(k+1)
  95.        '''
  96.         theta_prior = theta + deltaTheta + w_theta
  97.         x_prior = x + (D+w_D)*cos(theta_prior)
  98.         y_prior = y + (D+w_D)*sin(theta_prior)
  99.         x_hat_prior = np.array([x_prior, y_prior, theta_prior])
  100.         x_hat_prior.shape=(3,1)
  101.         return x_hat_prior
  102.  
  103.     def racunanje_P_prior(self, D, theta_hat, delta_theta, P_k):
  104.         A = np.matrix([
  105.             [1,0, -D*sin(theta_hat+delta_theta)],
  106.             [0,1,D*cos(theta_hat+delta_theta)],
  107.             [0,0,1]
  108.         ])
  109.  
  110.         W = np.matrix([
  111.             [-D*sin(theta_hat+delta_theta), cos(theta_hat+delta_theta)],
  112.             [D*cos(theta_hat+delta_theta), sin(theta_hat+delta_theta)],
  113.             [1,0]
  114.         ])
  115.  
  116.         Q = np.matrix([
  117.             [delta_theta**2*self.var_deltaTheta, 0],
  118.             [0, self.var_D]
  119.         ])
  120.         return multi_dot([A, P_k, np.transpose(A)])+multi_dot([W, Q, np.transpose(W)])
  121.  
  122.  
  123.     def model_sonara(self, x, y, x_p, y_p, v):
  124.         '''
  125.        :param v:
  126.        :param x: x koordinata sonara
  127.        :param y:
  128.        :param x_p: x pozicija pogodjena i-tim sonarom
  129.        :param y_p:
  130.        :return:
  131.        '''
  132.         return np.sqrt((x-x_p)**2+(y-y_p)**2)+v
  133.  
  134.     def najbliza_prepreka(self, zakret_sonara, x_sonara, y_sonara, zakret_robota):
  135.         '''
  136.        :param x_sonara: isti kao x robota
  137.        :param y_sonara:
  138.        :param zakret_sonara:
  139.        :return: pozicija najblize prepreke koju je udario i-ti sonar
  140.        '''
  141.         najmanja_udalj_prepreke = 100
  142.         najbliza_prepreka = []
  143.        
  144.         for prepreka in self.lista_prepreka:
  145.             ro = sqrt((x_sonara - prepreka[0]) ** 2 + (y_sonara - prepreka[1]) ** 2)
  146.  
  147.             if ro > 5:
  148.                 continue
  149.        
  150.             kut_celije = atan2(prepreka[1] - y_sonara, prepreka[0] - x_sonara)
  151.             theta = kut_celije - zakret_sonara - zakret_robota
  152.  
  153.             if (abs(theta) > self.th3db):
  154.                 continue
  155.            
  156.             print("HELLO")
  157.             if ro<najmanja_udalj_prepreke:
  158.                 najmanja_udalj_prepreke = ro
  159.                 najbliza_prepreka = prepreka
  160.            
  161.  
  162.         if (len(najbliza_prepreka) != 0):
  163.             print("Najbliza prepreka za zakret {} je [{},{}] - ro: {}"
  164.                 .format(zakret_sonara * 180 / pi, najbliza_prepreka[0], najbliza_prepreka[1], najmanja_udalj_prepreke))
  165.         else:
  166.              print("Nema prepreka za zakret: {}".format(zakret_sonara*180/pi))
  167.        
  168.         return najbliza_prepreka
  169.  
  170.     def racunaj_H(self, P_minus, x_minus, y_minus, theta_minus, mjerenja_sonara, odstupanje):
  171.         '''
  172.        :param P_minus:
  173.        :param x_minus:
  174.        :param y_minus:
  175.        :param mjerenja_sonara:
  176.        :param odstupanje: max odstupanje idealnog mjerenja od stvarnog
  177.        :return: S, H
  178.        '''
  179.         H = []
  180.         inovacija = []
  181.         v = 0 #sum
  182.         for indeks_sonara, mjerenje in enumerate(mjerenja_sonara):
  183.  
  184.             if isnan(mjerenje):
  185.                 continue
  186.  
  187.             najbliza_prepreka = self.najbliza_prepreka(self.zakret_sonara[indeks_sonara], x_minus, y_minus, theta_minus)
  188.  
  189.             if(len(najbliza_prepreka)==0):
  190.                 continue
  191.  
  192.             idealno_mjerenje = self.model_sonara(x_minus, y_minus, najbliza_prepreka[0], najbliza_prepreka[1], v)[0]
  193.             if(abs(idealno_mjerenje-mjerenje)>odstupanje):
  194.                 continue
  195.             djelitelj = 1/(sqrt((x_minus-najbliza_prepreka[0])**2+(y_minus-najbliza_prepreka[1])**2))
  196.  
  197.             temp = [((x_minus-najbliza_prepreka[0])/djelitelj)[0], ((y_minus-najbliza_prepreka[1])/djelitelj)[0], 0]
  198.             H.append(temp)
  199.             inovacija.append(mjerenje-idealno_mjerenje)
  200.  
  201.         return  H, np.array(inovacija)
  202.  
  203.     def pokreni_Kalman(self):
  204.         while not self.odometrija and not rospy.is_shutdown():
  205.             print("Nema mjerenja...")
  206.             rospy.sleep(1)
  207.  
  208.         self.x_hat = np.array([
  209.             0.25, 0.25, 0
  210.         ])
  211.         self.x_hat.shape = (3, 1)
  212.  
  213.         filter_rate = rospy.Rate(1./self.T)
  214.         while not rospy.is_shutdown():
  215.             curr_range = self.ranges
  216.  
  217.             D = self.linear_x*self.T
  218.             delta_theta = self.angular_z*self.T
  219.             print(D);
  220.             print(delta_theta)
  221.             x_hat_minus = self.model_robota(
  222.                 self.x_hat[0],
  223.                 self.x_hat[1],
  224.                 self.x_hat[2],
  225.                 D,
  226.                 delta_theta,
  227.                 0, 0
  228.             )
  229.             P_minus = self.racunanje_P_prior(D, self.x_hat[2], delta_theta, self.P_k)
  230.             H, inovacija = self.racunaj_H(P_minus, x_hat_minus[0], x_hat_minus[1], x_hat_minus[2], curr_range, 0.5)
  231.  
  232.             if(len(H)==0):
  233.                 print("Nema korekcije")
  234.                 self.x_hat = x_hat_minus
  235.                 self.P_k = P_minus
  236.                 filter_rate.sleep()
  237.             else:
  238.                 print("Korekcija")
  239.                 V = np.eye(len(H))
  240.                 R = np.eye(len(H)) * self.var_sonara
  241.  
  242.                 #print("x_hat_minus:\n{}\n".format(x_hat_minus))
  243.                 #print("P_minus:\n{}\n".format(P_minus))
  244.                 #print("H:\n{}\n".format(H))
  245.                 #print("inovacija:\n{}\n".format(inovacija))
  246.                
  247.                 S = multi_dot([H, P_minus, np.transpose(H)]) + multi_dot([V, R, np.transpose(V)])
  248.  
  249.                 #print("matrica inovacije:\n{}\n".format(S))
  250.                
  251.                 K = multi_dot([P_minus, np.transpose(H), inv(S)])
  252.  
  253.                 #print("K:\n{}\n".format(K))
  254.                 #print("inovacija:\n{}\n".format(inovacija))
  255.  
  256.                 self.P_k = P_minus-multi_dot([K, S, np.transpose(K)])
  257.                 self.x_hat = x_hat_minus+multi_dot([K, inovacija.reshape(-1,1)])
  258.  
  259.             print("x_hat:\n{}\n".format(self.x_hat))
  260.             #print(self.yaw_gt)
  261.             print("P_k:\n{}\n".format(self.P_k))
  262.             print('publishing')
  263.  
  264.             self.pub_x_k_msg.position.x = self.x_hat[0];
  265.             self.pub_x_k_msg.position.y = self.x_hat[1];
  266.             self.pub_x_k_msg.position.z = self.x_hat[2];
  267.             self.pub_x_k.publish(self.pub_x_k_msg)
  268.  
  269.             self.msg_Ptrace.data = np.trace(self.P_k)
  270.             self.msg_Pdet.data = np.linalg.det(self.P_k)
  271.  
  272.             self.pub_Ptrace.publish(self.msg_Ptrace)
  273.             self.pub_Pdet.publish(self.msg_Pdet)
  274.  
  275.             print("\n\n")
  276.             filter_rate.sleep()
  277.  
  278. if __name__=='__main__':
  279.     rospy.init_node('kalman_node')
  280.     kalman = prosireni_kalman()
  281.     kalman.pokreni_Kalman()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement