(self)
Actually draw the map
Actually draw the map
Actually draw the map
def render_map(self):
        '''
        Actually draw the map
        '''
        draw_final = show_time =False
        #save self.old_x_y
        old_x_y = self.old_x_y
        #get x,y theta location note: this updates self.old_x_y with new x_y
        x_y, theta = self.offset_coordinates(self.co_ords)

        if self.show_final_map == False:
            self.log.info("MAP: received: new co-ords: {} "
                          "phase: {}, state: {}".format(self.co_ords,
                          self.phase, self.current_state))

        if  self.current_state == self.states["charge"]:
            x_y = None
            self.display_text = "Charging: Battery: {}%".format(self.batPct)
            self.clear_flags(['battery_low', 'stuck'])
            if self.is_set('update_after_completed'):
                self.log.info('not updating map/text (mission complete), resume in {}s'.format(self.when_run('update_after_completed')))
            else:
                self.save_text_and_map_on_whitebg(self.map_no_text)
            draw_final = True

        elif self.current_state == self.states["recharge"]:
            x_y = None
            self.display_text = "Recharging: Time: {}m, Bat: {}%".format(self.rechrgM,self.batPct)
            self.clear_flags(['battery_low', 'stuck'])
            self.save_text_and_map_on_whitebg(self.map_no_text)

        elif self.current_state == self.states["pause"]:
            self.display_text = "Paused: {}m, Bat: {}%".format(self.mssnM,self.batPct)
            self.save_text_and_map_on_whitebg(self.map_no_text)

        elif self.current_state == self.states["hmPostMsn"]:
            self.display_text = "End Mission: Docking"
            show_time = True
            self.log.info("MAP: end of mission")
            self.show_final_map = False

        elif self.current_state == self.states["evac"]:
            x_y = None
            self.display_text = "Emptying Bin"
            self.log.info("MAP: emptying bin")

        elif self.current_state == self.states["completed"]:
            self.display_text = "Completed"
            show_time = True
            self.log.info("MAP: mission completed")
            self.draw_final_map(True)
            draw_final = True
            
        elif self.current_state == self.states["run"]:
            self.display_text = '{} Time: {}m, Bat: {}%'.format(self.states["run"],self.mssnM,self.batPct)
            self.clear_flags(['stuck', 'new_mission'])
            self.show_final_map = False
            if self.co_ords == self.zero_coords(theta=0):
                #bogus pose received, can't have 0,0,0 when running, usually happens after recovering from an error condition
                self.log.warning('MAP: received 0,0,0 pose when running - ignoring')
                self.old_x_y = None
                return

        elif self.current_state == self.states["stop"]:
            self.display_text = "Stopped: {}m, Bat: {}%".format(self.mssnM,self.batPct)
            self.show_final_map = False

        elif self.current_state == self.states["new"]:
            self.angle = self.mapSize[4]    #reset angle
            self.base = self.make_blank_image()
            # overlay for roomba problem position
            self.roomba_problem = self.make_blank_image()
            # save x and y center of image, for centering of final map image
            self.cx = self.base.size[0] // 2
            self.cy = self.base.size[1] // 2                             
            self.room_outline_contour = self.room_outline = None
            self.show_final_map = False
            self.display_text = None
            self.timer('update_after_completed')
            self.log.info("MAP: created new image at start of new run")
            self.clear_flags()
            self.set_flags('new_mission')

        elif self.current_state == self.states["stuck"]:
            expire = self.expireM
            expire_text = 'Job Cancel in {}m'.format(expire) if expire else 'Job Cancelled'
            self.display_text = ("STUCK!: {} {}").format(self.error_message, expire_text)
            show_time = True
            self.draw_final_map(True)
            draw_final = True
            self.show_final_map = False
            self.set_flags('stuck')

        elif self.current_state == self.states["cancelled"]:
            self.display_text = "Cancelled"
            show_time = True
            self.set_flags('cancelled')

        elif self.current_state == self.states["hmMidMsn"]:
            self.display_text = "Docking"
            self.show_final_map = False
            if not self.is_set('ignore_run'):
                if self.bin_full:
                    self.set_flags('bin_full')
                else:
                    self.display_text = "Battery low: {}%, {}".format(self.batPct,self.display_text)
                    self.set_flags('battery_low')             
                
        elif self.current_state == self.states["hmUsrDock"]:
            self.display_text = "User Docking"
            show_time = True
            self.show_final_map = False
 
        else:
            self.log.warning("MAP: no special handling for state: {}".format(self.current_state))

        if self.base is None:
            self.log.warning("MAP: no image, exiting...")
            return

        if self.display_text is None:
            self.display_text = self.current_state
            
        if self.bin_full:
            self.display_text = "Bin Full: {}".format(self.display_text)
            
        #add date/time to display text
        if show_time:
            self.display_text = '{}: {}'.format(self.display_text, time.strftime("%a %b %d %H:%M:%S"))
        
        if self.show_final_map and not self.debug: #just display final map - not live
            self.log.debug("MAP: not updating map - Roomba not running")
            return

        if self.debug:
            # debug final map (careful, uses a lot of CPU power!)
            self.draw_final_map()
            
        if x_y is None:
            #set zero co_ordinates if x_y is None
            self.log.info("MAP: ignoring new co-ords in {} phase: {}".format(self.current_state, self.co_ords))
            x_y, theta = self.offset_coordinates(None)
            old_x_y = self.old_x_y
            
        #calculate co-ordinates, with 0,0 as center
        roomba_pos = self.get_roomba_pos(x_y)

        self.log.debug("MAP: old x,y: {} new x,y: {} theta: {} roomba pos: {}".format(old_x_y, x_y, theta, roomba_pos))

        #draw lines
        self.draw_vacuum_lines(self.base, old_x_y, x_y, theta)
        #draw roomba
        roomba_sprite = self.draw_roomba(roomba_pos, theta)
        #draw problem roombas
        self.draw_problem_roombas(roomba_pos)
        
        if self.roomOutline or self.auto_rotate:
            # draw room outline (saving results if this is a final map) update
            # x,y and angle if auto_rotate
            self.draw_room_outline(draw_final, x_y)
            
        out = self.base
        
        #merge floorplan into base
        if self.floorplan is not None:
            out = Image.alpha_composite(out, self.floorplan)
            
        # merge room outline into base
        if self.roomOutline:
            out = Image.alpha_composite(out, self.room_outline)
            
        #merge roomba lines (trail) with base
        out = Image.alpha_composite(out, roomba_sprite)

        #merge problem location for roomba into out
        out = Image.alpha_composite(out, self.roomba_problem)

        if draw_final and self.auto_rotate:
            #translate image to center it if auto_rotate is on
            out = self.transform_image(out)
            
        # map is upside down, so rotate 180 degrees, and size to fit
        #(NW 12/4/2018 fixed bug causing distorted maps when rotation is not 0)
        out_rotated = out.rotate(180, expand=False)
        # save composite image
        self.save_text_and_map_on_whitebg(out_rotated)
        if draw_final:
            self.show_final_map = True
def render_map ( self ) : draw_final = show_time = False #save self.old_x_y old_x_y = self . old_x_y #get x,y theta location note: this updates self.old_x_y with new x_y x_y , theta = self . offset_coordinates ( self . co_ords ) if self . show_final_map == False : self . log . info ( "MAP: received: new co-ords: {} " "phase: {}, state: {}" . format ( self . co_ords , self . phase , self . current_state ) ) if self . current_state == self . states [ "charge" ] : x_y = None self . display_text = "Charging: Battery: {}%" . format ( self . batPct ) self . clear_flags ( [ 'battery_low' , 'stuck' ] ) if self . is_set ( 'update_after_completed' ) : self . log . info ( 'not updating map/text (mission complete), resume in {}s' . format ( self . when_run ( 'update_after_completed' ) ) ) else : self . save_text_and_map_on_whitebg ( self . map_no_text ) draw_final = True elif self . current_state == self . states [ "recharge" ] : x_y = None self . display_text = "Recharging: Time: {}m, Bat: {}%" . format ( self . rechrgM , self . batPct ) self . clear_flags ( [ 'battery_low' , 'stuck' ] ) self . save_text_and_map_on_whitebg ( self . map_no_text ) elif self . current_state == self . states [ "pause" ] : self . display_text = "Paused: {}m, Bat: {}%" . format ( self . mssnM , self . batPct ) self . save_text_and_map_on_whitebg ( self . map_no_text ) elif self . current_state == self . states [ "hmPostMsn" ] : self . display_text = "End Mission: Docking" show_time = True self . log . info ( "MAP: end of mission" ) self . show_final_map = False elif self . current_state == self . states [ "evac" ] : x_y = None self . display_text = "Emptying Bin" self . log . info ( "MAP: emptying bin" ) elif self . current_state == self . states [ "completed" ] : self . display_text = "Completed" show_time = True self . log . info ( "MAP: mission completed" ) self . draw_final_map ( True ) draw_final = True elif self . current_state == self . states [ "run" ] : self . display_text = '{} Time: {}m, Bat: {}%' . format ( self . states [ "run" ] , self . mssnM , self . batPct ) self . clear_flags ( [ 'stuck' , 'new_mission' ] ) self . show_final_map = False if self . co_ords == self . zero_coords ( theta = 0 ) : #bogus pose received, can't have 0,0,0 when running, usually happens after recovering from an error condition self . log . warning ( 'MAP: received 0,0,0 pose when running - ignoring' ) self . old_x_y = None return elif self . current_state == self . states [ "stop" ] : self . display_text = "Stopped: {}m, Bat: {}%" . format ( self . mssnM , self . batPct ) self . show_final_map = False elif self . current_state == self . states [ "new" ] : self . angle = self . mapSize [ 4 ] #reset angle self . base = self . make_blank_image ( ) # overlay for roomba problem position self . roomba_problem = self . make_blank_image ( ) # save x and y center of image, for centering of final map image self . cx = self . base . size [ 0 ] // 2 self . cy = self . base . size [ 1 ] // 2 self . room_outline_contour = self . room_outline = None self . show_final_map = False self . display_text = None self . timer ( 'update_after_completed' ) self . log . info ( "MAP: created new image at start of new run" ) self . clear_flags ( ) self . set_flags ( 'new_mission' ) elif self . current_state == self . states [ "stuck" ] : expire = self . expireM expire_text = 'Job Cancel in {}m' . format ( expire ) if expire else 'Job Cancelled' self . display_text = ( "STUCK!: {} {}" ) . format ( self . error_message , expire_text ) show_time = True self . draw_final_map ( True ) draw_final = True self . show_final_map = False self . set_flags ( 'stuck' ) elif self . current_state == self . states [ "cancelled" ] : self . display_text = "Cancelled" show_time = True self . set_flags ( 'cancelled' ) elif self . current_state == self . states [ "hmMidMsn" ] : self . display_text = "Docking" self . show_final_map = False if not self . is_set ( 'ignore_run' ) : if self . bin_full : self . set_flags ( 'bin_full' ) else : self . display_text = "Battery low: {}%, {}" . format ( self . batPct , self . display_text ) self . set_flags ( 'battery_low' ) elif self . current_state == self . states [ "hmUsrDock" ] : self . display_text = "User Docking" show_time = True self . show_final_map = False else : self . log . warning ( "MAP: no special handling for state: {}" . format ( self . current_state ) ) if self . base is None : self . log . warning ( "MAP: no image, exiting..." ) return if self . display_text is None : self . display_text = self . current_state if self . bin_full : self . display_text = "Bin Full: {}" . format ( self . display_text ) #add date/time to display text if show_time : self . display_text = '{}: {}' . format ( self . display_text , time . strftime ( "%a %b %d %H:%M:%S" ) ) if self . show_final_map and not self . debug : #just display final map - not live self . log . debug ( "MAP: not updating map - Roomba not running" ) return if self . debug : # debug final map (careful, uses a lot of CPU power!) self . draw_final_map ( ) if x_y is None : #set zero co_ordinates if x_y is None self . log . info ( "MAP: ignoring new co-ords in {} phase: {}" . format ( self . current_state , self . co_ords ) ) x_y , theta = self . offset_coordinates ( None ) old_x_y = self . old_x_y #calculate co-ordinates, with 0,0 as center roomba_pos = self . get_roomba_pos ( x_y ) self . log . debug ( "MAP: old x,y: {} new x,y: {} theta: {} roomba pos: {}" . format ( old_x_y , x_y , theta , roomba_pos ) ) #draw lines self . draw_vacuum_lines ( self . base , old_x_y , x_y , theta ) #draw roomba roomba_sprite = self . draw_roomba ( roomba_pos , theta ) #draw problem roombas self . draw_problem_roombas ( roomba_pos ) if self . roomOutline or self . auto_rotate : # draw room outline (saving results if this is a final map) update # x,y and angle if auto_rotate self . draw_room_outline ( draw_final , x_y ) out = self . base #merge floorplan into base if self . floorplan is not None : out = Image . alpha_composite ( out , self . floorplan ) # merge room outline into base if self . roomOutline : out = Image . alpha_composite ( out , self . room_outline ) #merge roomba lines (trail) with base out = Image . alpha_composite ( out , roomba_sprite ) #merge problem location for roomba into out out = Image . alpha_composite ( out , self . roomba_problem ) if draw_final and self . auto_rotate : #translate image to center it if auto_rotate is on out = self . transform_image ( out ) # map is upside down, so rotate 180 degrees, and size to fit #(NW 12/4/2018 fixed bug causing distorted maps when rotation is not 0) out_rotated = out . rotate ( 180 , expand = False ) # save composite image self . save_text_and_map_on_whitebg ( out_rotated ) if draw_final : self . show_final_map = True