text: import rospy
  import cv2
  from sensor_msgs.msg import Image
  from pid_tune.msg import PidTune
  from std_msgs.msg import Float32
  from geometry_msgs.msg import Twist
  from cv_bridge import CvBridge
  import numpy as np
  import matplotlib.pyplot as plt
  import math
  
  # Index numbers
  KP = 0
  KI = 1
  KD = 2
  
  MULT = 1e-3
  
  LINVEL = 0.5
  
  IMG_WIDTH = 640/8
  IMG_HEIGHT = 480/8
  
  class Autobot():
      """
      Main Class
      """
      def __init__(self):
          rospy.init_node("autobot")
          rospy.Subscriber("/mybot/camera/image_raw",data_class=Image,callback=self.handle_image)
          rospy.Subscriber('/pid_tuning_roll', PidTune, self._set_pid_const)
          self.err_pub = rospy.Publisher("/err",Float32,queue_size=1)
          self.vel_pub = rospy.Publisher("/cmd_vel",Twist,queue_size=1)
          self.zero_err = rospy.Publisher("/zero_err",Float32,queue_size=1)
          self.i=0
          self.img = np.empty([])
          self.weights = [-(1+10*math.atan(x*1.00/(IMG_WIDTH/2))) for x in range((IMG_WIDTH/2))]
          self.sum = 0.0
  
          # Kp, Ki, Kd
          self.const = [1e-2,0.0,1e-2]
          
          self.err=0.0
          self.output = 0.0
          self.i_lim = 5e5
          self.prev = 0.0
          self.cummulative = 0.0
  
          self.vel = Twist()
      
      def _set_pid_const(self, msg):
          self.const[KP] = msg.Kp * 0.06*(MULT)
          self.const[KI] = msg.Ki * 0.008*(MULT)
          self.const[KD] = msg.Kd * 0.3*(MULT)
      
      def decide_weights(self):
          w = [(1+10*math.atan(((IMG_WIDTH/2)-x)*1.00/(IMG_WIDTH/2))) for x in range((IMG_WIDTH/2))]
          w.extend(self.weights)
          self.weights = w
          self.weights = np.array(self.weights)
          print self.weights
  
      def handle_image(self,data):
          bridge = CvBridge()
          self.img = bridge.imgmsg_to_cv2(data,"bgr8")
          # self.img = cv2.inRange(self.img,(50,50,50),(100,100,100),self.img)
          self.img = cv2.resize(self.img,dsize=(IMG_HEIGHT,IMG_WIDTH))
          self.img = cv2.cvtColor(self.img,cv2.COLOR_BGR2GRAY)
          _,self.img = cv2.threshold(self.img,50,255,cv2.THRESH_BINARY)
          # self.img = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)
          # plt.imshow(self.img)
          # plt.pause(0.00001)
          # print self.img.shape
          self.img = np.array(self.img)
          path = "/home/shreyas/{}.jpg".format(self.i)
          # cv2.imwrite(path,self.img)
          self.detect_lane()
          self.i += 1
      
      def detect_lane(self):
          self.img = self.img[int(IMG_WIDTH*420/640): , :]
          self.img = self.img/np.linalg.norm(self.img)
          # print self.img.shape
          ######### Uncomment to see images ###################
          plt.imshow(self.img)
          plt.pause(0.00001)
          #####################################################
          for rect in self.img:
              for _,y in enumerate(rect):
                  self.sum += self.weights[_]*y
          # print self.sum 
      
          # straight offset on left -103724.882842
          # right slant 39644.9973759
          # left inverted L -253596
          # left curve -411556.281235
          # self.sum = 0 #Make sure that next iteration has zero sum
  
      def pid(self):
          self.err = self.sum
          self.sum = 0.0
          self.cummulative += self.err
          if self.cummulative > self.i_lim:
              self.cummulative = 0.0
          self.output = self.const[KP]*self.err + self.const[KD]*(self.err-self.prev) + self.const[KI]*self.cummulative
          self.prev = self.err
          self.err_pub.publish(self.err)
          self.vel.angular.z = self.output
          self.vel.linear.x = LINVEL
          self.vel_pub.publish(self.vel)
          self.err_pub.publish(self.err)
          self.zero_err.publish(0.0)
          print self.err,self.output
  
          
  if __name__ =="__main__":
      bot = Autobot()
      rate = rospy.Rate(80)
      bot.decide_weights()
      try :
          while not rospy.is_shutdown():
              bot.pid()
              rate.sleep()
      except rospy.ROSInterruptException as e:
          print e.message