예제 #1
0
    def draw_fake_balloon(self, frame, veh_pos, balloon_pos, vehicle_roll,
                          vehicle_pitch, vehicle_yaw):
        # calculate bearing to balloon
        bearing_to_balloon = PositionVector.get_bearing(veh_pos, balloon_pos)
        yaw_to_balloon = balloon_utils.wrap_PI(bearing_to_balloon -
                                               vehicle_yaw)

        # calculate earth frame pitch angle from vehicle to balloon
        pitch_to_balloon = vehicle_pitch + PositionVector.get_elevation(
            veh_pos, balloon_pos)

        #print "Fake Balloon Bearing:%f Pitch:%f Dist:%f" % (math.degrees(bearing_to_balloon), math.degrees(pitch_to_balloon), dist_to_balloon_xy)

        # calculate pixel position of balloon
        balloon_x = balloon_video.angle_to_pixels_x(
            yaw_to_balloon) + balloon_video.img_center_x
        balloon_y = balloon_video.angle_to_pixels_y(
            pitch_to_balloon) + balloon_video.img_center_y

        # calculate size of balloon in pixels from distance and size
        dist_to_balloon_xyz = PositionVector.get_distance_xyz(
            veh_pos, balloon_pos)
        balloon_radius = balloon_utils.get_pixels_from_distance(
            dist_to_balloon_xyz, balloon_finder.balloon_radius_expected)

        # store balloon radius
        self.last_balloon_radius = balloon_radius

        # draw balloon
        cv2.circle(frame, (balloon_x, balloon_y), balloon_radius,
                   self.fake_balloon_colour_bgr_scalar, -1)
    def draw_fake_balloon(self, frame, veh_pos, balloon_pos, vehicle_roll, vehicle_pitch, vehicle_yaw):
        # calculate bearing to balloon
        bearing_to_balloon = PositionVector.get_bearing(veh_pos, balloon_pos)
        yaw_to_balloon = balloon_utils.wrap_PI(bearing_to_balloon-vehicle_yaw)

        # calculate earth frame pitch angle from vehicle to balloon
        pitch_to_balloon = vehicle_pitch + PositionVector.get_elevation(veh_pos, balloon_pos)

        #print "Fake Balloon Bearing:%f Pitch:%f Dist:%f" % (math.degrees(bearing_to_balloon), math.degrees(pitch_to_balloon), dist_to_balloon_xy)

        # calculate pixel position of balloon
        balloon_x = balloon_video.angle_to_pixels_x(yaw_to_balloon) + balloon_video.img_center_x
        balloon_y = balloon_video.angle_to_pixels_y(pitch_to_balloon) + balloon_video.img_center_y

        # calculate size of balloon in pixels from distance and size
        dist_to_balloon_xyz = PositionVector.get_distance_xyz(veh_pos, balloon_pos)
        balloon_radius = balloon_utils.get_pixels_from_distance(dist_to_balloon_xyz, balloon_finder.balloon_radius_expected)

        # store balloon radius
        self.last_balloon_radius = balloon_radius

        # draw balloon
        cv2.circle(frame,(balloon_x,balloon_y), balloon_radius, self.fake_balloon_colour_bgr_scalar, -1)
    def get_attitude(self, desired_time_in_sec):
        # return current attitude immediately if dictionary is empty
        if len(self.att_dict) == 0:
            return self.vehicle.attitude

        # get times from dict
        keys = sorted(self.att_dict.keys())

        # debug
        #print "AttDict looking for %f" % desired_time_in_sec

        # initialise best before and after keys
        key_before = keys[0]
        time_diff_before = (key_before - desired_time_in_sec)
        key_after = keys[len(keys)-1]
        time_diff_after = (key_after - desired_time_in_sec)

        # handle case where we hit the time exactly or the time is beyond the end
        if (time_diff_before >= 0):
            #debug
            #print "Time %f was before first entry's time %f" % (desired_time_in_sec, key_before)
            return self.att_dict[key_before]
        if (time_diff_after <= 0):
            #debug
            #print "Time %f was after last entry's time %f" % (desired_time_in_sec, key_after)
            return self.att_dict[key_after]

        # iteration through attitude dictionary
        for t in keys:
            # calc this dictionary entry's time diff from the desired time
            time_diff = t - desired_time_in_sec

            # if before the desired time but after the current best 'before' time use it
            if time_diff <= 0 and time_diff > time_diff_before:
                time_diff_before = time_diff
                key_before = t

            # if after the desired time but before the current best 'before' time use it
            if time_diff >= 0 and time_diff < time_diff_after:
                time_diff_after = time_diff
                key_after = t

        # calc time between before and after attitudes
        tot_time_diff = -time_diff_before + time_diff_after

        # debug
        if (tot_time_diff <= 0):
            print "Div By Zero!"
            print "des time:%f" % desired_time_in_sec
            print "num keys:%d" % len(keys)
            print "key bef:%f aft:%f" % (key_before, key_after)
            print "keys: %s" % keys

        # get attitude before and after
        att_before = self.att_dict[key_before]
        att_after = self.att_dict[key_after]

        # interpolate roll, pitch and yaw values
        interp_val = (-time_diff_before / tot_time_diff)
        roll = wrap_PI(att_before.roll + (wrap_PI(att_after.roll - att_before.roll) * interp_val))
        pitch = att_before.pitch + (att_after.pitch - att_before.pitch) * interp_val
        yaw = wrap_PI(att_before.yaw + (wrap_PI(att_after.yaw - att_before.yaw) * interp_val))

        ret_att = Attitude(pitch, yaw, roll)

        return ret_att
예제 #4
0
    def move_to_balloon(self):

        # exit immediately if we are not controlling the vehicle
        if not self.controlling_vehicle:
            return

        # get current time
        now = time.time()

        # exit immediately if it's been too soon since the last update
        if (now - self.guided_last_update) < self.vel_update_rate:
            return

        # if we have a new balloon position recalculate velocity vector
        if (self.balloon_found):

            # calculate change in yaw since we began the search
            yaw_error = wrap_PI(self.balloon_heading -
                                self.search_balloon_heading)

            # calculate pitch vs ideal pitch angles.  This will cause to attempt to get to 5deg above balloon
            pitch_error = wrap_PI(self.balloon_pitch_top -
                                  self.vel_pitch_target)

            # get time since last time velocity pid controller was run
            dt = self.vel_xy_pid.get_dt(2.0)

            # get speed towards balloon based on balloon distance
            speed = self.balloon_distance * self.vel_dist_ratio

            # apply min and max speed limit
            speed = min(speed, self.vel_speed_max)
            speed = max(speed, self.vel_speed_min)

            # apply acceleration limit
            speed_chg_max = self.vel_accel * dt
            speed = min(speed, self.vel_speed_last + speed_chg_max)
            speed = max(speed, self.vel_speed_last - speed_chg_max)

            # record speed for next iteration
            self.vel_speed_last = speed

            # calculate yaw correction and final yaw movement
            yaw_correction = self.vel_xy_pid.get_pid(yaw_error, dt)
            yaw_final = wrap_PI(self.search_balloon_heading + yaw_correction)

            # calculate pitch correction and final pitch movement
            pitch_correction = self.vel_z_pid.get_pid(pitch_error, dt)
            pitch_final = wrap_PI(self.search_balloon_pitch_top -
                                  pitch_correction)

            # calculate velocity vector we wish to move in
            self.guided_target_vel = balloon_finder.get_ef_velocity_vector(
                pitch_final, yaw_final, speed)

            # send velocity vector to flight controller
            self.send_nav_velocity(self.guided_target_vel[0],
                                   self.guided_target_vel[1],
                                   self.guided_target_vel[2])
            self.guided_last_update = now

        # if have not seen the balloon
        else:
            # if more than a few seconds has passed without seeing the balloon give up
            if now - self.last_spotted_time > self.lost_sight_timeout:
                if self.debug:
                    print "Lost Balloon, Giving up"
                # To-Do: start searching again or maybe slowdown?
                self.complete()
예제 #5
0
    def search_for_balloon(self):

        # exit immediately if we are not controlling the vehicle or do not know our position
        if not self.controlling_vehicle or self.vehicle_pos is None:
            return

        # exit immediately if we are not searching
        if self.search_state <= 0:
            return

        # search states: 0 = not searching, 1 = spinning and looking, 2 = rotating to best balloon and double checking, 3 = finalise yaw

        # search_state = 1: spinning and looking
        if (self.search_state == 1):

            # check if we have seen a balloon
            if self.balloon_found:
                # if this is the first balloon we've found or the closest, store it's position as the closest
                if (self.search_balloon_pos is None) or (
                        self.balloon_distance < self.search_balloon_distance):
                    # check distance is within acceptable limits
                    if (self.mission_alt_min == 0
                            or self.balloon_pos.z >= self.mission_alt_min
                        ) and (self.mission_alt_max == 0
                               or self.balloon_pos.z <= self.mission_alt_max
                               ) and (self.mission_distance_max == 0
                                      or self.balloon_distance <=
                                      self.mission_distance_max):
                        # record this balloon as the closest
                        self.search_balloon_pos = self.balloon_pos
                        self.search_balloon_heading = self.balloon_heading
                        self.search_balloon_pitch_top = self.balloon_pitch_top  # we target top of balloon
                        self.search_balloon_distance = self.balloon_distance
                        print "Found Balloon at heading:%f Alt:%f Dist:%f" % (
                            math.degrees(self.balloon_heading),
                            self.balloon_pos.z, self.balloon_distance)
                    else:
                        print "Balloon Ignored at heading:%f Alt:%f Dist:%f" % (
                            math.degrees(self.balloon_heading),
                            self.balloon_pos.z, self.balloon_distance)

            # update yaw so we keep spinning
            if math.fabs(
                    wrap_PI(self.vehicle.attitude.yaw -
                            self.search_target_heading)) < math.radians(
                                self.search_yaw_speed * 2.0):
                # increase yaw target
                self.search_target_heading = self.search_target_heading - math.radians(
                    self.search_yaw_speed)
                self.search_total_angle = self.search_total_angle + math.radians(
                    self.search_yaw_speed)
                # send yaw heading
                self.condition_yaw(math.degrees(self.search_target_heading))

                # end search if we've gone all the way around
                if self.search_total_angle >= math.radians(360):
                    # if we never saw a balloon then just complete (return control to user or mission)
                    if self.search_balloon_pos is None:
                        print "Search did not find balloon, giving up"
                        self.search_state = 0
                        self.complete()
                    else:
                        # update target heading towards closest balloon and send to flight controller
                        self.search_target_heading = self.search_balloon_heading
                        self.condition_yaw(
                            math.degrees(self.search_target_heading))
                        self.search_state = 2  # advance towards rotating to best balloon stage
                        print "best balloon at %f" % math.degrees(
                            self.search_balloon_heading)

        # search_state = 2: rotating to best balloon and double checking
        elif (self.search_state == 2):
            # check yaw is close to target
            if math.fabs(
                    wrap_PI(self.vehicle.attitude.yaw -
                            self.search_target_heading)) < math.radians(5):
                # reset targeting start time
                if self.targeting_start_time == 0:
                    self.targeting_start_time = time.time()

                # if targeting time has elapsed, double check the visible balloon is within acceptable limits
                if (time.time() - self.targeting_start_time >
                        self.targeting_delay_time):
                    if self.balloon_found and (
                            not self.balloon_pos is None
                    ) and (self.mission_alt_min == 0
                           or self.balloon_pos.z >= self.mission_alt_min) and (
                               self.mission_alt_max == 0
                               or self.balloon_pos.z <= self.mission_alt_max
                           ) and (self.mission_distance_max == 0
                                  or self.balloon_distance <=
                                  self.mission_distance_max):
                        # balloon is within limits so reset balloon target
                        self.search_balloon_pos = self.balloon_pos
                        self.search_balloon_heading = self.balloon_heading
                        self.search_balloon_pitch_top = self.balloon_pitch_top
                        self.search_balloon_distance = self.balloon_distance
                        # move to final heading
                        self.search_target_heading = self.search_balloon_heading
                        self.condition_yaw(
                            math.degrees(self.search_target_heading))
                        # move to finalise yaw state
                        self.search_state = 3
                        print "Balloon was near expected heading, finalising yaw to %f" % (
                            math.degrees(self.search_balloon_heading))

                    # we somehow haven't found the balloon when we've turned back to find it so giveup
                    elif (time.time() - self.targeting_start_time) > (
                            self.targeting_delay_time + 1.0):
                        print "Balloon was not at expected heading: %f, giving up" % (
                            math.degrees(self.search_target_heading))
                        self.search_state = 0
                        self.complete()

        # search_state = 3: finalising yaw
        elif (self.search_state == 3):
            # check yaw is close to target
            if math.fabs(
                    wrap_PI(self.vehicle.attitude.yaw -
                            self.search_target_heading)) < math.radians(5):
                # complete search, move should take-over
                # Note: we don't check again for the balloon, but surely it's still there
                self.search_state = 0
                print "Finalised yaw to %f, beginning run" % (math.degrees(
                    self.search_balloon_heading))
     def run(self):

        yawangle=0.0
        imgnum=0
        bal_rc1=self.vehicle.parameters['RC1_TRIM']
        bal_rc2=self.vehicle.parameters['RC2_TRIM']
        RC7MAX=self.vehicle.parameters['RC7_MAX']
        RC7MIN=self.vehicle.parameters['RC7_MIN']  
        RC6MIN=self.vehicle.parameters['RC6_MIN']
        last_mode=None
        gain=1.0

        deltasatx=0
        deltasaty=0  
        

        try:
            
            #web=Webserver(balloon_config.config.parser,(lambda:self.frame))
            
            fourcc = cv2.cv.CV_FOURCC(*'XVID')
            video_writer = cv2.VideoWriter('output.avi',fourcc, 1.0, (640,480))
            
            print "initialising camera"
            # initialise video capture
            camera = balloon_video.get_camera()
            
            log_gname='Guidedv%s' % (time.time())
            gf = open(log_gname, mode='w')
            gf.write("Guided velocity mode log DATA %s\n"%(time.localtime()))
            gf.write("time\t yaw(org,radians)\t yaw_angle\t objposx\t objposy\t error_total\t vx\t vy\t gain\t imgradius\t RC6VAL\n")
            gf.close

 
            cycle_num=0
            coeffx=1
            coeffy=1
            
            print "Ready to go!"

            while(True):
                
              #print(self.vehicle)
              if self.vehicle is None:
                #print('0.5')
                self.vehicle=self.api.get_vehicles()[0]
                print('no vehicle')
              #print('1.5')

              # get a frame
              _, frame = camera.read()
              newx,newy=frame.shape[1],frame.shape[0]
              newframe=cv2.resize(frame,(newx,newy))
 
              self.frame=newframe

 
              #self.balloon_found, xpos, ypos, size = balloon_finder.analyse_frame(frame)
              self.object_found,xpos,ypos,size=self.object_find(newframe)
              #self.object_found,xpos,ypos,size=self.object_find_hough(frame)
              #if self.object_found:              
              #   video_writer.write(newframe)
              #print xpos
              
              RC6VAL=float(self.vehicle.channel_readback['6'])
              RC7VAL=self.vehicle.channel_readback['7']  
              if RC7VAL<=0 or RC7MAX is None:
                 gain=1.0
              else:
                 gain=7.0*(RC7VAL-RC7MIN)/(RC7MAX-RC7MIN)
              
              if RC7VAL>1099 and RC7VAL<1150:
                 gain=0
              elif RC7VAL>1150 and RC7VAL<1200:
                 gain=0.05
              elif RC7VAL>1200 and RC7VAL<1250:
                 gain=0.1
              elif RC7VAL>1250 and RC7VAL<1300:
                 gain=0.2
              elif RC7VAL>1300 and RC7VAL<1350:
                 gain=0.3
              elif RC7VAL>1350 and RC7VAL<1400:
                 gain=0.4
              elif RC7VAL>1400 and RC7VAL<1450:
                 gain=0.5
              elif RC7VAL>1450:
                 gain=0.6

              print 'gain is:',gain

              #RC6VAL=1
              #if RC6VAL==1:
              if RC6VAL==RC6MIN:#vision-controlled
                           
                 
                 yaw_origin=self.vehicle.attitude.yaw
                 
                 if self.vehicle.mode.name=="GUIDED":#visual-guided
                    last_mode="GUIDED" 

                    

                    if self.object_found: 
                       print('object found')

                       pixelsize=0.03
                       deltax=xpos-320
                       deltay=240-ypos
                       print 'yaw-origin: deltaxpos  deltaypos ', yaw_origin,deltax,deltay

                       #print'deltax y'
                       #print deltax,deltay 
                       angle_yawtmp=0.5*3.14-math.atan2(deltay,deltax)+yaw_origin#radians
                       angle_yaw=wrap_PI(angle_yawtmp)
                       #print'angle1'
                       angle_yawdeg=math.degrees(angle_yaw)
                       
                       angle_pitch=0
                       speedSet=0.15

                       #spdfactor=math.sqrt((deltax*daltax+deltay*deltay))*0.1

                       realrx=deltax*pixelsize

                       realry=deltay*pixelsize
                       #spdfactor=((rx**2+ry**2)**0.5*0.01
 
                       spddist=math.sqrt(realrx**2+realry**2)

                       #print "dist:",spddist
                       #if spddist<=0.5:
                       #   self.vehicle.mode=VehicleMode("LAND")
                       #   self.vehicle.flush()



                       spdfactor=spddist*0.2
                       '''  
                       # get time since last time velocity pid controller was run
                       dt = self.vel_xy_pid.get_dt(2.0)
                       
                       # get speed towards balloon based on balloon   distance
                       #speed = self.balloon_distance * self.vel_dist_ratio
                       speed=spdfactor
                       # apply min and max speed limit
                       speed = min(speed, self.vel_speed_max)
                       speed = max(speed, self.vel_speed_min)

                       # apply acceleration limit
                       speed_chg_max = self.vel_accel * dt
                       speed = min(speed, self.vel_speed_last + speed_chg_max)
                       speed = max(speed, self.vel_speed_last - speed_chg_max)

                       # record speed for next iteration
                       self.vel_speed_last = speed
                       '''
                       cos_pitch=math.cos(angle_pitch)

                       velocity_x=gain*speedSet*math.cos(angle_yaw)*cos_pitch*spdfactor
                       velocity_y=float(gain*speedSet*math.sin(angle_yaw)*cos_pitch*spdfactor)
                       #velocity_x=speedSet*math.cos(angle_yaw)*cos_pitch*speed
                       #velocity_y=speedSet*math.sin(angle_yaw)*cos_pitch*speed
                       #velocity_z=speedSet*math.sin(angle_pitch)
                       velocity_z=0
                       #print 'angle and velocity....'
                       #print angle_yawdeg,velocity_x,velocity_y
                       
                       #start calculate the pid controller's term
                       dtx=self.vx_fopi.get_dt(2.0)
                                              
                       #errorx=math.sqrt(deltax*deltax+deltay*deltay)*math.cos(angle_yaw)*0.265/size#radius of the red circle is 25.5cm
                       #errorx=math.sqrt(deltax*deltax+deltay*deltay)*math.cos(angle_yaw)*0.265/(1*size)#radius of the red circle is 25.5cm
                       #errorx=math.sqrt(deltax*deltax+deltay*deltay)*math.cos(angle_yaw)*0.012/(1*size)#radius of the blue circle is 1.2cm
                       #errorx=errorx-deltasatx*0.3 #anti-wind
                       #errorx=errorx*gain
                       error_total=math.sqrt(deltax*deltax+deltay*deltay)*0.265/(1*size)#radius of the blue circle is 1.2cm
                       print'error_total,gain,angletoN',error_total,gain,angle_yaw
                       upx=error_total*math.cos(angle_yaw)*gain*coeffx
                       upy=error_total*math.sin(angle_yaw)*gain*coeffy
                       
                       
                        
                       if upx>1.0:
                          upx=1.0
                          upy=upx/math.tan(angle_yaw)
                       elif upx<-1.0:
                          upx=-1.0
                          upy=upx/math.tan(angle_yaw)
                       if upy>1.0:
                          upy=1.0
                          upx=upy*math.tan(angle_yaw)
                       elif upy<-1.0:
                          upy=-1.0
                          upx=upy*math.tan(angle_yaw)

                       #errorx=velocity_x
                       '''
                       up_total=self.vx_fopi.get_fopi(error_total, dtx)
                       upx=up_total*math.cos(angle_yaw)*gain
                       upy=up_total*math.sin(angle_yaw)*gain
                       '''
                       #upx=upx*gain
                       ''' 
                       dty=self.vy_fopi.get_dt(2.0)
                       #errory=velocity_y
                       #errory=math.sqrt(deltax*deltax+deltay*deltay)*math.sin(angle_yaw)*0.265/size
                       errory=math.sqrt(deltax*deltax+deltay*deltay)*math.sin(angle_yaw)*0.265/size
                       #errory=math.sqrt(deltax*deltax+deltay*deltay)*math.sin(angle_yaw)*0.012/size
                       #errory=errory-deltasaty*0.3 
                       errory=errory*gain
                       
                       print'errory,gain',errory,gain

                       upy=self.vy_fopi.get_fopi(errory, dty)
                       #upy=upy*gain
                       '''   
                       
                       print'gain,num,sampling time',gain,cycle_num,dtx


                       print 'control speed of x from fo-pi to p upx,velx,upy,vely',upx,velocity_x,upy,velocity_y

                       self.vel_control(upx,upy)
                       time.sleep(0.1)
                       
                       deltatime=time.time()-self.timelast
                       gf = open(log_gname, mode='a')
                       gf.write("%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n"%(deltatime,yaw_origin,angle_yaw,xpos,ypos,error_total,upx,upy,gain,size,coeffx,coeffy,RC6VAL))
                       gf.close()

                    else:#not-found
                         print "guided mode,object not found"
                         self.vel_control(0,0)
                         time.sleep(0.5)
                         
                         deltatime=time.time()-self.timelast
                         gf = open(log_gname, mode='a')
                         gf.write("%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n"%(deltatime,0,0,-566,-566,0,0,0,0,size,-500))
                         gf.close()
                 else:#non-guided
                        
                        print "vision control but non-guided"
                        
                        if last_mode=="GUIDED":
                            self.vel_control(0,0)
                            last_mode=self.vehicle.mode.name
                            time.sleep(0.5)

                                               
 
              else:#non-vision-controlled
                   
                   print "non-vision-controlled,landing......"
                   while(self.vehicle.mode.name=="GUIDED"):

                             self.vehicle.mode.name="LAND"
                             self.vehicle.mode = VehicleMode("LAND")
                             self.vehicle.flush()
                             time.sleep(1)
                   while(self.vehicle.armed is True):
                             self.vehicle.armed=False
                             self.vehicle.flush()
                             time.sleep(1)
                      
                    
              #time.sleep(1)  
        # handle interrupts
        except:
            print "interrupted, exiting"

        # exit and close web server
        print "exiting..."
    def move_to_balloon(self):

        # exit immediately if we are not controlling the vehicle
        if not self.controlling_vehicle:
            return

        # get current time
        now = time.time()

        # exit immediately if it's been too soon since the last update
        if (now - self.guided_last_update) < self.vel_update_rate:
            return;

        # if we have a new balloon position recalculate velocity vector
        if (self.balloon_found):

            # calculate change in yaw since we began the search
            yaw_error = wrap_PI(self.balloon_heading - self.search_balloon_heading)

            # calculate pitch vs ideal pitch angles.  This will cause to attempt to get to 5deg above balloon 
            pitch_error = wrap_PI(self.balloon_pitch_top - self.vel_pitch_target)

            # get time since last time velocity pid controller was run
            dt = self.vel_xy_pid.get_dt(2.0)

            # get speed towards balloon based on balloon distance
            speed = self.balloon_distance * self.vel_dist_ratio

            # apply min and max speed limit
            speed = min(speed, self.vel_speed_max)
            speed = max(speed, self.vel_speed_min)

            # apply acceleration limit
            speed_chg_max = self.vel_accel * dt
            speed = min(speed, self.vel_speed_last + speed_chg_max)
            speed = max(speed, self.vel_speed_last - speed_chg_max)

            # record speed for next iteration
            self.vel_speed_last = speed

            # calculate yaw correction and final yaw movement
            yaw_correction = self.vel_xy_pid.get_pid(yaw_error, dt)
            yaw_final = wrap_PI(self.search_balloon_heading + yaw_correction)

            # calculate pitch correction and final pitch movement
            pitch_correction = self.vel_z_pid.get_pid(pitch_error, dt)
            pitch_final = wrap_PI(self.search_balloon_pitch_top + pitch_correction)
            
            # calculate velocity vector we wish to move in
            self.guided_target_vel = balloon_finder.get_ef_velocity_vector(pitch_final, yaw_final, speed)

            # send velocity vector to flight controller
            self.send_nav_velocity(self.guided_target_vel[0], self.guided_target_vel[1], self.guided_target_vel[2])
            self.guided_last_update = now

        # if have not seen the balloon
        else:
            # if more than a few seconds has passed without seeing the balloon give up
            if now - self.last_spotted_time > self.lost_sight_timeout:
                if self.debug:
                    print "Lost Balloon, Giving up"
                # To-Do: start searching again or maybe slowdown?
                self.complete()
    def search_for_balloon(self):

        # exit immediately if we are not controlling the vehicle or do not know our position
        if not self.controlling_vehicle or self.vehicle_pos is None:
            return

        # exit immediately if we are not searching
        if self.search_state <= 0:
            return

        # search states: 0 = not searching, 1 = spinning and looking, 2 = rotating to best balloon and double checking, 3 = finalise yaw

        # search_state = 1: spinning and looking
        if (self.search_state == 1):

            # check if we have seen a balloon
            if self.balloon_found:
                # if this is the first balloon we've found or the closest, store it's position as the closest
                if (self.search_balloon_pos is None) or (self.balloon_distance < self.search_balloon_distance):
                    # check distance is within acceptable limits
                    if (self.mission_alt_min == 0 or self.balloon_pos.z >= self.mission_alt_min) and (self.mission_alt_max == 0 or self.balloon_pos.z <= self.mission_alt_max) and (self.mission_distance_max == 0 or self.balloon_distance <= self.mission_distance_max):
                        # record this balloon as the closest
                        self.search_balloon_pos = self.balloon_pos
                        self.search_balloon_heading = self.balloon_heading
                        self.search_balloon_pitch_top = self.balloon_pitch_top  # we target top of balloon
                        self.search_balloon_distance = self.balloon_distance
                        print "Found Balloon at heading:%f Alt:%f Dist:%f" % (math.degrees(self.balloon_heading), self.balloon_pos.z, self.balloon_distance)
                    else:
                        print "Balloon Ignored at heading:%f Alt:%f Dist:%f" % (math.degrees(self.balloon_heading), self.balloon_pos.z, self.balloon_distance)

            # update yaw so we keep spinning
            if math.fabs(wrap_PI(self.vehicle.attitude.yaw - self.search_target_heading)) < math.radians(self.search_yaw_speed * 2.0):
                # increase yaw target
                self.search_target_heading = self.search_target_heading - math.radians(self.search_yaw_speed)
                self.search_total_angle = self.search_total_angle + math.radians(self.search_yaw_speed)
                # send yaw heading
                self.condition_yaw(math.degrees(self.search_target_heading))

                # end search if we've gone all the way around
                if self.search_total_angle >= math.radians(360):
                    # if we never saw a balloon then just complete (return control to user or mission)
                    if self.search_balloon_pos is None:
                        print "Search did not find balloon, giving up"
                        self.search_state = 0
                        self.complete()
                    else:
                        # update target heading towards closest balloon and send to flight controller
                        self.search_target_heading = self.search_balloon_heading
                        self.condition_yaw(math.degrees(self.search_target_heading))
                        self.search_state = 2   # advance towards rotating to best balloon stage
                        print "best balloon at %f" % math.degrees(self.search_balloon_heading)

        # search_state = 2: rotating to best balloon and double checking
        elif (self.search_state == 2):
            # check yaw is close to target
            if math.fabs(wrap_PI(self.vehicle.attitude.yaw - self.search_target_heading)) < math.radians(5):
                # reset targeting start time
                if self.targeting_start_time == 0:
                    self.targeting_start_time = time.time()

                # if targeting time has elapsed, double check the visible balloon is within acceptable limits
                if (time.time() - self.targeting_start_time > self.targeting_delay_time):
                    if self.balloon_found and (not self.balloon_pos is None) and (self.mission_alt_min == 0 or self.balloon_pos.z >= self.mission_alt_min) and (self.mission_alt_max == 0 or self.balloon_pos.z <= self.mission_alt_max) and (self.mission_distance_max == 0 or self.balloon_distance <= self.mission_distance_max):
                        # balloon is within limits so reset balloon target
                        self.search_balloon_pos = self.balloon_pos
                        self.search_balloon_heading = self.balloon_heading
                        self.search_balloon_pitch_top = self.balloon_pitch_top
                        self.search_balloon_distance = self.balloon_distance
                        # move to final heading
                        self.search_target_heading = self.search_balloon_heading
                        self.condition_yaw(math.degrees(self.search_target_heading))
                        # move to finalise yaw state
                        self.search_state = 3
                        print "Balloon was near expected heading, finalising yaw to %f" % (math.degrees(self.search_balloon_heading))

                    # we somehow haven't found the balloon when we've turned back to find it so giveup
                    elif (time.time() - self.targeting_start_time) > (self.targeting_delay_time + 1.0):
                        print "Balloon was not at expected heading: %f, giving up" % (math.degrees(self.search_target_heading))
                        self.search_state = 0
                        self.complete()

        # search_state = 3: finalising yaw
        elif (self.search_state == 3):
            # check yaw is close to target
            if math.fabs(wrap_PI(self.vehicle.attitude.yaw - self.search_target_heading)) < math.radians(5):
                # complete search, move should take-over
                # Note: we don't check again for the balloon, but surely it's still there
                self.search_state = 0
                print "Finalised yaw to %f, beginning run" % (math.degrees(self.search_balloon_heading))
예제 #9
0
     def run(self):

        yawangle=0.0
        imgnum=0
        bal_rc1=self.vehicle.parameters['RC1_TRIM']
        bal_rc2=self.vehicle.parameters['RC2_TRIM']
        RC7MAX=self.vehicle.parameters['RC7_MAX']
        RC7MIN=self.vehicle.parameters['RC7_MIN']  
        RC6MIN=self.vehicle.parameters['RC6_MIN']
        RC6MAX=self.vehicle.parameters['RC6_MAX']
        RC6MID=(RC6MIN+RC6MAX)/2
       # print "RC6MIN=",RC6MIN,",RC6MAX=",RC6MAX,",RC6MID=",RC6MID
        last_mode=None
        gain=1.0
        last_gain=1.0

        deltasatx=0
        deltasaty=0  
        

        try:
            
            web=Webserver(balloon_config.config.parser,(lambda:self.webframe))
            #Shang uncommented here. 
			#web=Webserver(balloon_config.config.parser,(lambda:self.frame))

            fourcc = cv2.cv.CV_FOURCC(*'XVID')
            video_name='video_%s.avi' % (time.time())
            video_writer = cv2.VideoWriter(video_name,fourcc, 1.0, (640,480))
            
            print "Initialising camera."
            # initialise video capture
            camera = balloon_video.get_camera()
            
            log_gname='BoTest%s.txt' % (time.time())
            gf = open(log_gname, mode='w')
            gf.write("Guided velocity mode log DATA %s\n"%(time.localtime()))
            gf.write("time\t yaw(org,radians)\t yaw_angle\t objposx\t objposy\t error_total\t vx\t vy\t gain\t imgradius\t roll\t pitch\t RC6VAL\n") #coeffx\t coeffy\t
            gf.close
            
 
            cycle_num=0
            coeffx=1
            coeffy=1
            
            print "Ready to go!"

            while(True):
                
              #print(self.vehicle)
              if self.vehicle is None:
                #print('0.5')
                self.vehicle=self.api.get_vehicles()[0]
                print('no vehicle')
              #print('1.5')

              # get a frame
              _, frame = camera.read()
              newx,newy=frame.shape[1],frame.shape[0]
              newframe=cv2.resize(frame,(newx,newy))
 
              self.frame=newframe

 
              #self.balloon_found, xpos, ypos, size = balloon_finder.analyse_frame(frame)
              self.object_found,xpos,ypos,size=self.object_find(newframe)
              #self.object_found,xpos,ypos,size=self.object_find_hough(frame)
              #if self.object_found:              
			  
              #adding text to image
              font = cv2.FONT_HERSHEY_SIMPLEX
              #Python:#cv2.putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[,bottomLeftOrigin]]]) 
              cv2.putText(newframe,'Object Found? ' + str(self.object_found)[0],(10,20), font, 0.3,(255,255,255),1)
              cv2.putText(newframe,'Mode: ' + self.vehicle.mode.name,(10,40), font, 0.3,(255,255,255),1)
              cv2.putText(newframe,'Time: ' + str(time.time()),(10,60), font, 0.3,(255,255,255),1)
              cv2.putText(newframe,'Alt: ' + str(self.vehicle.location.global_relative_frame),(10,100), font, 0.3,(255,255,255),1)
              cv2.putText(newframe,'RC5: ' + str(self.vehicle.channels['5']),(10,120), font, 0.3,(255,255,255),1)
              #print 'New video frame. Time: %s' % (time.time()) 
              #print xpos
              
              RC6VAL=float(self.vehicle.channels['6'])
              RC7VAL=self.vehicle.channels['7']  
              if RC7VAL==0 or RC7MAX is None:
                 gain=last_gain
              #else:
              #   gain=7.0*(RC7VAL-RC7MIN)/(RC7MAX-RC7MIN)
              
              if RC7VAL>=1099 and RC7VAL<=1150:
                 gain=0
              elif RC7VAL>=1150 and RC7VAL<=1200:
                 gain=0.05
              elif RC7VAL>=1200 and RC7VAL<=1250:
                 gain=0.1
              elif RC7VAL>=1250 and RC7VAL<=1300:
                 gain=0.2
              elif RC7VAL>=1300 and RC7VAL<=1350:
                 gain=0.3
              elif RC7VAL>=1350 and RC7VAL<=1400:
                 gain=0.4
              elif RC7VAL>=1400 and RC7VAL<=1450:
                 gain=0.5
              elif RC7VAL>=1450 and RC7VAL<=1500:
                 gain=0.6
              elif RC7VAL>=1500 and RC7VAL<=1550:
                 gain=0.7
              elif RC7VAL>=1550 and RC7VAL<=1600:
                 gain=0.8	 
              elif RC7VAL>=1600 and RC7VAL<=1650:
                 gain=0.9
              elif RC7VAL>=1650:
                 gain=1.0
              last_gain=gain
              cv2.putText(newframe,'Gain: ' + str(gain),(10,140), font, 0.3,(255,255,255),1)
              cv2.putText(newframe,'Roll: ' + str(self.vehicle.attitude.roll),(10,160), font, 0.3,(255,255,255),1)
              cv2.putText(newframe,'Pitch: ' + str(self.vehicle.attitude.pitch),(10,180), font, 0.3,(255,255,255),1)
              cv2.putText(newframe,'Battery: ' + str(self.vehicle.battery),(10,200), font, 0.3,(255,255,255),1)
              cv2.putText(newframe,'[vx, vy, vz ](in m/s): ' + str(self.vehicle.velocity),(10,220), font, 0.3,(255,255,255),1)

              #gain1=0.05*gain
              #gain=gain1
              #print 'gain is:',gain,'RC7=',RC7VAL

              #RC6VAL=1
              #if RC6VAL==1:
              if RC6VAL<RC6MID:#vision-controlled
                           
                 #print 'vision-controlled.'
				 
                 yaw_origin=self.vehicle.attitude.yaw
                 roll_origin=self.vehicle.attitude.roll
                 pitch_origin=self.vehicle.attitude.pitch
                 #attitude_origin=self.vehicle.attitude
                 print "Heading: %s" % self.vehicle.heading
                 cv2.line(newframe,(320,240),(int(320+100*math.sin(-yaw_origin)),int(240-100*math.cos(-yaw_origin))),(255,255,255),1)
                 cv2.putText(newframe,"N: " + str(math.degrees(yaw_origin))[0:5],(int(320+100*math.sin(-yaw_origin)),int(240-100*math.cos(-yaw_origin))),font,0.3,(255,255,255),1)
                 #print 'yaw_origin=', yaw_origin
                 if self.vehicle.mode.name=="GUIDED":#visual-guided
                    if last_mode!="GUIDED":
                       self.condition_yaw(0)
                    last_mode="GUIDED"

                    #print "---------------New period-----------------"

                    #print 'vehicle.mode = Guided. Gain =',gain
					
                    if self.object_found: 
                       print('object found')

                       pixelsize=0.03
                       deltax=xpos-320  
					   #cv2.line(frame,(320,240),320)
                       deltay=240-ypos
                       #print 'yaw-origin: deltaxpos  deltaypos ', yaw_origin,deltax,deltay
                       print 'roll, pitch=', roll_origin,pitch_origin
					   
                       #print'deltax y'
                       #print deltax,deltay 
                       angle_yawtmp=0.5*3.14-math.atan2(deltay,deltax)+yaw_origin#radians
                       angle_yaw=wrap_PI(angle_yawtmp)
                       #print'angle1'
                       angle_yawdeg=math.degrees(angle_yaw)
                       
                       angle_pitch=0
                       speedSet=0.15

                       #spdfactor=math.sqrt((deltax*daltax+deltay*deltay))*0.1

                       realrx=deltax*pixelsize

                       realry=deltay*pixelsize
                       #spdfactor=((rx**2+ry**2)**0.5*0.01
 
                       spddist=math.sqrt(realrx**2+realry**2)

                       #print "dist:",spddist
                       #if spddist<=0.5:
                       #   self.vehicle.mode=VehicleMode("LAND")
                       #   self.vehicle.flush()



                       spdfactor=spddist*0.2
                       '''  
                       # get time since last time velocity pid controller was run
                       dt = self.vel_xy_pid.get_dt(2.0)
                       
                       # get speed towards balloon based on balloon   distance
                       #speed = self.balloon_distance * self.vel_dist_ratio
                       speed=spdfactor
                       # apply min and max speed limit
                       speed = min(speed, self.vel_speed_max)
                       speed = max(speed, self.vel_speed_min)

                       # apply acceleration limit
                       speed_chg_max = self.vel_accel * dt
                       speed = min(speed, self.vel_speed_last + speed_chg_max)
                       speed = max(speed, self.vel_speed_last - speed_chg_max)

                       # record speed for next iteration
                       self.vel_speed_last = speed
                       '''
                       cos_pitch=math.cos(angle_pitch)

                       velocity_x=gain*speedSet*math.cos(angle_yaw)*cos_pitch*spdfactor
                       velocity_y=float(gain*speedSet*math.sin(angle_yaw)*cos_pitch*spdfactor)
                       #velocity_x=speedSet*math.cos(angle_yaw)*cos_pitch*speed
                       #velocity_y=speedSet*math.sin(angle_yaw)*cos_pitch*speed
                       #velocity_z=speedSet*math.sin(angle_pitch)
                       velocity_z=0
                       #print 'angle and velocity....'
                       #print angle_yawdeg,velocity_x,velocity_y
                       
                       #start calculate the pid controller's term
                       dtx=self.vx_fopi.get_dt(2.0)
                                              
                       #errorx=math.sqrt(deltax*deltax+deltay*deltay)*math.cos(angle_yaw)*0.265/size#radius of the red circle is 25.5cm
                       #errorx=math.sqrt(deltax*deltax+deltay*deltay)*math.cos(angle_yaw)*0.265/(1*size)#radius of the red circle is 25.5cm
                       #errorx=math.sqrt(deltax*deltax+deltay*deltay)*math.cos(angle_yaw)*0.012/(1*size)#radius of the blue circle is 1.2cm
                       #errorx=errorx-deltasatx*0.3 #anti-wind
                       #errorx=errorx*gain
                       
                       error_total=math.sqrt(deltax*deltax+deltay*deltay)*0.265/(1*size)#radius of the blue circle is 1.2cm

                       error_x=error_total*math.cos(angle_yaw)
                       error_y=error_total*math.sin(angle_yaw)
                   
                          
                       #print'error_total,gain,angletoN',error_total,gain,angle_yaw
                       upx=error_total*math.cos(angle_yaw)*gain*coeffx
                       upy=error_total*math.sin(angle_yaw)*gain*coeffy
                       

                       upx_fo=self.vx_fopi.get_fopi(error_x, dtx)*gain
                       upy_fo=upx_fo/math.tan(angle_yaw)

                       
                       #print 'upx,upx_fo,upy,upy_fo to object',upx,upx_fo,upy,upy_fo

                       #print 'err_total,error_x',error_total,error_x                       

                       upx=upx_fo
                       upy=upy_fo
                       #print 'upx,upy to drone',upx,upy
                        
                       if upx>1.0:
                          upx=1.0
                          upy=upx/math.tan(angle_yaw)
                       elif upx<-1.0:
                          upx=-1.0
                          upy=upx/math.tan(angle_yaw)
                       if upy>1.0:
                          upy=1.0
                          upx=upy*math.tan(angle_yaw)
                       elif upy<-1.0:
                          upy=-1.0
                          upx=upy*math.tan(angle_yaw)

                       #errorx=velocity_x
                       
                       #upx=upx*gain
                       ''' 
                       dty=self.vy_fopi.get_dt(2.0)
                       #errory=velocity_y
                       #errory=math.sqrt(deltax*deltax+deltay*deltay)*math.sin(angle_yaw)*0.265/size
                       errory=math.sqrt(deltax*deltax+deltay*deltay)*math.sin(angle_yaw)*0.265/size
                       #errory=math.sqrt(deltax*deltax+deltay*deltay)*math.sin(angle_yaw)*0.012/size
                       #errory=errory-deltasaty*0.3 
                       errory=errory*gain
                       
                       print'errory,gain',errory,gain

                       upy=self.vy_fopi.get_fopi(errory, dty)
                       #upy=upy*gain
                       '''   
                       '''                       
                       print'gain,num,sampling time',gain,cycle_num,dtx


                       print 'control speed of x from fo-pi to p upx,velx,upy,vely',upx,velocity_x,upy,velocity_y
                       '''
                       if deltay > 100:
                          upx=gain
                       elif deltay < -100:
                          upx=-gain
                       else:
                          upx=deltay*0.01*gain
                       if deltax > 100:
                          upy=gain
                       elif deltax < -100:
                          upy=-gain
                       else:
                          upy=deltax*0.01*gain

                       self.vel_control(upx,upy)
                       cv2.putText(newframe,'upx(N): ' + str(upx) + ', upy(E): ' + str(upy),(10,80), font, 0.3,(255,255,255),1)
                       time.sleep(0.1)
                 
                       #deltatime=time.time()-self.timelast
                       gf = open(log_gname, mode='a')
                       gf.write("%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n"%(time.time(),yaw_origin,angle_yaw,xpos,ypos,error_total,upx,upy,gain,size,roll_origin,pitch_origin,RC6VAL))
                       gf.close()

                    else:#not-found
                         print "Guided mode,object not found. Gain = %f; Time = %f" % (gain,time.time())
                         self.vel_control(0,0)
                         #time.sleep(0.5)

                         RC6VAL=float(self.vehicle.channels['6'])
                         #deltatime=time.time()-self.timelast
                         gf = open(log_gname, mode='a')
                         gf.write("%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n"%(time.time(),0,0,-566,-566,0,0,0,0,size,roll_origin,pitch_origin,RC6VAL))
                         gf.close()

                 else:#non-guided
                        
                        print "Vision control but non-guided. Yaw=", math.degrees(yaw_origin), ", Time=", time.time()

                        RC6VAL=float(self.vehicle.channels['6'])
                        #deltatime=time.time()-self.timelast
                        gf = open(log_gname, mode='a')
                        gf.write("%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n"%(time.time(),0,0,-566,-566,0,0,0,0,size,roll_origin,pitch_origin,RC6VAL))
                        gf.close()
                        
                        if last_mode=="GUIDED":
                            self.vel_control(0,0)
                            last_mode=self.vehicle.mode.name
                            time.sleep(0.5)

                                               
 
              else:#non-vision-controlled
                   
                   print "non-vision-controlled,landing......"

                   #deltatime=time.time()-self.timelast
                   gf = open(log_gname, mode='a')
                   gf.write("%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n"%(time.time(),yaw_origin,angle_yaw,xpos,ypos,error_total,upx,upy,gain,size,RC6VAL,RC6VAL,RC6VAL))
                   gf.close()

                   while(self.vehicle.mode.name=="GUIDED"):

                             self.vehicle.mode.name="LAND"
                             self.vehicle.mode = VehicleMode("LAND")
                             self.vehicle.flush()
                             time.sleep(1)
                   while(self.vehicle.armed is True):
                             self.vehicle.armed=False
                             self.vehicle.flush()
                             time.sleep(1)
                      
              video_writer.write(newframe)
              self.webframe=newframe
      
              #time.sleep(1)  
        # handle interrupts
        except KeyboardInterrupt:
            print 'interrupted, exiting'

        # exit and close web server
        print "exiting..."
        web.close()
        #Shang uncommented here.

        video_writer.release()