list_of_walls = [east_wall, north_wall, west_wall, south_wall]

fig = plt.figure(num=1, clear=True)
ax = fig.add_subplot(1, 1, 1, projection='3d')

east_wall.plot(ax)
south_window.plot(ax)
north_wall.plot(ax)
fake_east_window.plot(ax)
west_wall.plot(ax)
fake_west_window.plot(ax)
south_wall.plot(ax)

#ground_plane.plot(ax)

s.cast_on(list_of_reflective_boundaries, ax)
m.draw_mission_planes(list_of_walls, ax)

ax.set_xlabel('X: East')
ax.set_xlim(-10, 10)
ax.set_ylabel('Y: North')
ax.set_ylim(-10, 10)
ax.set_zlabel('Z: Up')
ax.set_zlim(-10, 10)

axnext = plt.axes([0.85, 0.25, 0.10, 0.075])
bnext = Button(axnext, 'Path')

slider_box = plt.axes([0.15, 0.05, 0.65, 0.03],
                      facecolor='lightgoldenrodyellow')
time_slider = Slider(slider_box,
コード例 #2
0
class Planner():
    def __init__(self, building_height):
        rospy.init_node('offb')
        self.height = building_height
        self.GPS_ready = False

        # Wait for Offboard and drone to be ready
        ready = rospy.wait_for_message('/gps_ready_from_offboard', Bool, timeout=rospy.Duration(60*5)) # Wait for offboard to get GPS fix for 5 minutes, because sometimes GPS locks take long to get when a board is booted up the first time

        if ready:
            nav = NavSatFix()
            # And now put the node into a waiting loop to wait for GPS Lock from Offboard
            nav = rospy.wait_for_message('mavros/global_position/global', NavSatFix)
            self.coordinates = np.array([nav.latitude, nav.longitude])
        else:
            rospy.loginfo("Never got position confirmation from Offboard")

        self.house_result_pub = rospy.Publisher('/house_results_from_overpass_local', BuildingPolygonResult, queue_size=5) # Information about the house
        self.camera_stuff_pub = rospy.Publisher('/camera_and_distances', CameraStuff, queue_size=1)
        self.impression_keyframes_pub = rospy.Publisher('/impression_poses_from_planner', PoseArray, queue_size=5) # Poses to take one image of each facade of the house
        self.inspection_keyframes_pub = rospy.Publisher('/keyframes_poses_from_planner', PoseArray, queue_size=5)

        #self.segmented_image_sub = rospy.Subscriber('segmented_image_from_cnn', cnnResult, self.segmented_image_callback, queue_size=5)

        self.image_and_rois_sub = rospy.Subscriber('/segmented_image_from_cnn', ImageAndRois, callback=self.image_and_rois_callback)

        self.get_tiles_ready = False

        self.images_list = []
        self.rois_list = []

        self.s = Sun(self.coordinates[0], self.coordinates[1])
        self.m = Mission(80, 80)
        self.model_walls = []
        self.model_windows = []

        self.fig_thread = Thread(target=self.draw_thread, args=())
        self.fig_thread.daemon = True

        self.fig = []
        self.ax = []
        

    def image_and_rois_callback(self, data):
        image = data.img
        rois = data.rois

        self.images_list.append(image)
        self.rois_list.append(rois)

        if self.get_tiles_ready == False:
            
            self.get_tiles_ready = True


    def send_camera_and_mission_information_to_cnn(self, mission, distances):
        ''' Format of message is
        float64[] aov
        float64 focal_length
        float64 resolution
        float64[] distances_from_walls
        '''
        c = CameraStuff()
        c.aov = [mission.aov[0], mission.aov[1]]
        c.focal_length = mission.f
        c.resolution =  [mission.sensor_resolution[0], mission.sensor_resolution[1]]
        c.distances_from_walls = distances

        self.camera_stuff_pub.publish(c)

    def build_walls(self, polygon_result, local_coords):
        rospy.loginfo("Planner recieved information about the house. Building walls for detailed model")
        #model_walls = []
        for i in range(len(local_coords) - 1):
            # Use the local coordinates to build walls
            self.model_walls.append(Boundary(local_coords[i][0], local_coords[i][1], 0.0, local_coords[i+1][0], local_coords[i+1][1], 0.0, local_coords[i][0], local_coords[i][1], polygon_result.building_height, "wall", self.s.get_lightsource()))


        # Let's also initiate the figure and plot all the walls
        self.fig = plt.figure(num=1, clear=True)
        self.ax = self.fig.add_subplot(1, 1, 1, projection='3d')

        # For loop that goes through all the model walls and plots them
        for wall in self.model_walls:
            wall.plot(self.ax)

        #ground_plane.plot(ax)
        self.ax.set_xlabel('X: East')
        self.ax.set_xlim(-50, 50)
        self.ax.set_ylabel('Y: North')
        self.ax.set_ylim(-50, 50)
        self.ax.set_zlabel('Z: Up')
        self.ax.set_zlim(-20, 20)

        axsolarbutton = plt.axes([0.85, 0.25, 0.10, 0.075])
        self.solar_button = Button(axsolarbutton, 'Solar Check')


        self.m.draw_mission_planes(self.model_walls, self.ax)

        axbrushfirebutton = plt.axes([0.85, 0.10, 0.10, 0.075])
        self.brushfirebutton = Button(axbrushfirebutton, 'Generate mission')


    def put_up_windows(self, facade_image, windows, wall_length, model_wall):
        rospy.loginfo("Planner received information about the windows. Putting windows on walls")
        # Generate an array that takes the time from now and the next 30 minutes, which we will say is the estimated mission duration
        # We assume that the image itself is the plane, which is harsh to assume, but it's the best we've got... 
        # Based on the size of the image (width, height), we make translation factors for x and y to be able to place the windows on the planes.

        # Let's then generate windows in the form that our mission class can understand, taking the bounding boxes of the instance segmentation, aka the rois and make windows out of them
        for i in range(len(windows)):
            # Remember that the coordinates of the rois (windows) are upside down on the y-axis
            # The rois are in the following form : y1,x1, y2,x2
            
            n_xy_tiles = len(model_wall.x)
            n_z_tiles = len(model_wall.z) # this is the y coordinate of the image, but the z coordinate in the world-frame
            
            x1 = n_xy_tiles - round((windows[i].roi[1] / facade_image.width) * n_xy_tiles) - 1 
            y1 = n_z_tiles - round((windows[i].roi[0] / facade_image.height) * n_z_tiles) - 1
            x2 = n_xy_tiles - round((windows[i].roi[3] / facade_image.width) * n_xy_tiles) - 1
            y2 = n_z_tiles - round((windows[i].roi[2] / facade_image.height) * n_z_tiles) - 1

            #rospy.loginfo([x1, y1, x2, y2])
            # We are going to find indecies for the plane and just select the ones that the window covers

            #  TODO: COrrect this method. It's not quite right...

            p1 = np.array([model_wall.x[x1], model_wall.y[x1], model_wall.z[y2]])
            p2 = np.array([model_wall.x[x2], model_wall.y[x2], model_wall.z[y2]])
            p3 = np.array([model_wall.x[x1], model_wall.y[x1], model_wall.z[y1]])

            window = Boundary(p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], p3[0], p3[2], p3[2], "window", self.s.get_lightsource())

            window.plot(self.ax)

            self.model_windows.append(window)

        rospy.loginfo(self.s.date.timestamp())

        return PoseArray()
   

    def generate_keyframes_for_inspection(self, segmented_image):
        # Something someting
        rospy.loginfo("I'm in the generate keyframes for inspection function now")
        return_poses = PoseArray()
        return return_poses

    def solar_button_callback(self, event):
        rospy.loginfo("Analyzing mission planes for solar reflections for the next 30 minutes")
        time_range = range(int(self.s.date.timestamp()), int(self.s.date.timestamp() + 30.0*60.0), 120) # generate a time-instance every 30th second? 30 minutes

        for i in range(len(time_range)):
            self.s.date = datetime.datetime.fromtimestamp(time_range[i], tz=pytz.timezone("Europe/Copenhagen"))
            self.s.cast_on(self.model_windows, self.ax)
            self.fig.canvas.draw_idle()
            self.m.check_for_reflection(self.s, self.ax)
        rospy.loginfo("Done analyzing mission planes for solar reflections for the next 30 minutes")

    def brushfirebutton_callback(self, event):
        self.m.generate_mission(self.ax)

    def draw_thread(self):
        thread_rate = rospy.Rate(20)  # Hz
        plt.show()

        while not rospy.is_shutdown():
            #self.fig.canvas.draw_idle()
            
            

            try:  # prevent garbage in console output when thread is killed
                thread_rate.sleep()
            except rospy.ROSInterruptException:
                pass