Skip to content
Snippets Groups Projects
Select Git revision
  • e48924b57cd3dd2afba7122942909b21f332715f
  • master default protected
  • 2018ws
  • 2017ws
  • 2016ws
5 results

string-ops-4.c

Blame
  • Forked from Peter Gerwinski / hp
    Source project has a limited visibility.
    grafic.py 16.85 KiB
    # -*- coding: utf-8 -*-
    """
    Created on Sat May  6 13:26:28 2023
    
    @author: Jessica Dreyer, Sebastian Böttger
    """
    #%% imports
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import matplotlib.patches as patches
    from matplotlib.patches import Circle
    import matplotlib.image as img
    import tkinter as tk
    
    # not importend imports
    import time
    import random
    
    
    #%% class
    """
    # This class can plot values as a consistant graph.
    # With the method update you can insert a new value to the graph and the grafic will refresh automaticly.
    """
    class Line_Plotter:
        """
        # The constructor needs a title, for the diagramm as well as a lable for the x and y axses.
        # Optional you can set the number of values that are plottet on the x-axses.
        """
        def __init__(self, title, x_lable, y_lable ,x_scale = 100):
            self.counter = 0
            self.fig = plt.figure()
            self.x = np.array(range(-x_scale + 1,1))
            self.y = np.zeros(x_scale)
            self.ax = self.fig.add_subplot(111)
            self.line, = self.ax.plot(self.x, self.y)
            self.ax.set_xlim(self.x[0],self.x[self.x.size -1])
            self.ax.set_ylim(0, 10)
            self.ax.set_title(title)
            self.ax.set_xlabel(x_lable)
            self.ax.set_ylabel(y_lable)
            self.fig.canvas.draw()
            self.fig.canvas.flush_events()
            
        """
        # The method update insert a new value to the graph an refresh the graph automaticly.
        # It needs only the value as a parameter.
        """
        def update(self, value):
            self.y = np.append(self.y, value)
            self.y = self.y[1:]
            self.x = np.append(self.x, self.counter)
            self.x = self.x[1:]
            
            self.line._x = self.x
            self.line.set_ydata(self.y)
            self.fig.canvas.draw()
            self.fig.canvas.flush_events()
            
            self.ax.set_xlim(self.x[0],self.x[self.x.size -1])
            self.ax.set_ylim(self.y.min(), self.y.max())
            
            self.counter = self.counter + 1
        
        """
        # The method close ensures that the window is closed.
        """
        def close(self):
            plt.close(self.fig)
    
    """
    # This class can plot values as a continues graph.
    # It can plot the values with a given timedelta to the last known value.
    """
    class Line_Plotter_Time:
        """
        # The constructor needs a title, for the diagramm as well as a lable for the x and y axses.
        # Optional you can set the number of values that are plottet on the x-axses.
        """
        def __init__(self, title, x_lable, y_lable ,x_scale = 100):
            self.x_scale = x_scale
            self.fig = plt.figure()
            self.x = np.array(range(0,1))
            self.y = np.zeros(1)
            self.ax = self.fig.add_subplot(111)
            self.line, = self.ax.plot(self.x, self.y)
            self.ax.set_xlim(0,10)
            self.ax.set_ylim(0, 10)
            self.ax.set_title(title)
            self.ax.set_xlabel(x_lable)
            self.ax.set_ylabel(y_lable)
            
        """
        # The method update insert a new value to the graph on the timestamp delte which is given an refresh the graph automaticly.
        # It needs the value and a given time delta to the last value as a parameter.
        # The timedelta will be summed to the hight time of a datapoint in the digramm and will plot at this time the new value.
        """
        def update(self, value, time_delta):
            self.y = np.append(self.y, value)
            self.x = np.append(self.x, self.x[self.x.size -1] + time_delta)
            if (self.x.size > self.x_scale):
                self.y = self.y[1:]
                self.x = self.x[1:]
            
            self.line._x = self.x
            self.line.set_ydata(self.y)
            self.fig.canvas.draw()
            self.fig.canvas.flush_events()
            
            self.ax.set_xlim(self.x[0],self.x[self.x.size -1])
            self.ax.set_ylim(self.y.min(), self.y.max())
        
        """
        # The method close ensures that the window is closed.
        """
        def close(self):
            plt.close(self.fig)
    
    """
    # This class can plot the racetrack and highlighte the current section.
    # It should also display a little robot an update the position, but unfortunately, it's not function properly.
    """
    class Track_Plotter:
        """
        # This constructor needs a set of trackparts which contains a URL to the backgroundimage for the plot.
        """
        def __init__(self, background_url, track, ratio = 1):
            self.background = img.imread(background_url)
            self.track = track
            self.ratio = ratio
            self.fig = plt.figure()
            self.ax = self.fig.add_subplot(111)
            self.live_image = self.ax.imshow(self.background, extent=[0,1000,750,0])
            self.robot_is_active = False
            self.robot_position = self.track.iloc[0].start_position
            self.robot_direction = self.track.iloc[0].start_direction
            self.ax.set_xlim(0,1000)
            self.ax.set_ylim(750,0)
            plt.show(block=False)
            plt.pause(0.1)
        
        """
        # Wich this funtion you get a set of trackparts. The URLs are not includet in this git.
        """
        def get_set_of_trackparts_3():
            # Track plotting
            trackparts = []
            trackparts.append(['./Bilder/Strecke_03_S1.PNG', 'S1', (0,0), 0])
            trackparts.append(['./Bilder/Strecke_03_S2.PNG', 'S2', (0,0), 0])
            trackparts.append(['./Bilder/Strecke_03_S3.PNG', 'S3', (0,0), 0])
            trackparts.append(['./Bilder/Strecke_03_S4.PNG', 'S4', (0,0), 0])
            trackparts.append(['./Bilder/Strecke_03_S5.PNG', 'S5', (0,0), 0])
            trackparts.append(['./Bilder/Strecke_03_S6.PNG', 'S6', (0,0), 0])
            trackparts.append(['./Bilder/Strecke_03_S7.PNG', 'S7', (0,0), 0])
            trackparts.append(['./Bilder/Strecke_03_S8.PNG', 'S8', (0,0), 0])
            trackparts.append(['./Bilder/Strecke_03_S9.PNG', 'S9', (0,0), 0])
            trackparts.append(['./Bilder/Strecke_03_S10.PNG', 'S10', (0,0), 0])
            trackparts.append(['./Bilder/Strecke_03_S11.PNG', 'S11', (0,0), 0])
            trackparts.append(['./Bilder/Strecke_03_S12.PNG', 'S12', (0,0), 0])
            trackparts.append(['./Bilder/Strecke_03_S13.PNG', 'S13', (0,0), 0])
            
            # Create DataFrame
            track = pd.DataFrame(trackparts,columns=['image_url', 'name', 'start_position', 'start_direction'])
            background = './Bilder/Strecke_03.png'
            
            return (background, track)
        
        """
        # This method is internal used to create the robot. 
        """
        def __create_triangle(self, position, direction):
            # Definiere die Position der Ecke des Dreiecks
            x = position[0]
            y = position[1]
            
            # Definiere die Länge der Kante, die in Richtung des Winkels theta zeigt
            length = 100
            
            # Definiere den Winkel theta in Grad
            theta_deg = direction
            
            # Berechne den Winkel theta in Bogenmaß
            theta = np.deg2rad(theta_deg)
            
            # Berechne die Koordinaten des Dreiecks
            x1 = x
            y1 = y
            
            x2 = x + length * np.cos(theta -np.deg2rad(135))
            y2 = y + length * np.sin(theta -np.deg2rad(135))
            x3 = x + length * np.cos(theta -np.deg2rad(135) + np.pi/2)
            y3 = y + length * np.sin(theta -np.deg2rad(135) + np.pi/2)
            
            
            # Erstelle das Dreieck
            self.__triangle = patches.Polygon([(x1, y1), (x2, y2), (x3, y3)], closed=True, fill=True, facecolor='green', alpha=0.5)
            return self.__triangle
        
        """
        # This function is used to select a section and set up that backgorundimage
        """
        def select_trackpart(self, trackpart_name):
            trackpart = self.track[self.track.name == trackpart_name]
            image = img.imread(trackpart.iloc[0].image_url)
            self.live_image.set_data(image)
            self.fig.canvas.draw()
            self.fig.canvas.flush_events()
        
        """
        # This funktion is used to set the robot to the startposition of a trackpart.
        # Currently the robot simulation is not usable!
        """
        def set_robot_to_trackpart(self, trackpart_name):
            trackpart = self.track[self.track.name == trackpart_name]
            self.robot_position = trackpart.iloc[0].start_position
            self.robot_direction = trackpart.iloc[0].start_direction
            self.update_robot()
        
        """
        # This funktion is used to move the robot forward.
        # Currently the robot simulation is not usable!
        """
        def move_robot_forward(self, distance):
            x,y = self.robot_position
            theta = np.deg2rad(self.robot_direction)
            x_new = x + distance*self.ratio * np.sin(theta)
            y_new = y - distance*self.ratio * np.cos(theta)
            self.robot_position = (x_new, y_new)
            self.update_robot()
        
        """
        # This funktion is used to set the robot to a specific position on the plot.
        # Currently the robot simulation is not usable!
        """
        def move_robot_to_position(self, position):
            self.robot_position += position
            self.update_robot()
        
        """
        # This funktion is used to rotate the robot.
        # Currently the robot simulation is not usable!
        """
        def rotate_robot(self, rotation):
            self.robot_direction += rotation
            self.update_robot()
        
        """
        # This funktion enable the plotting of the robot.
        # Currently the robot simulation is not usable!
        """
        def activate_robot(self):
            print("Do not use this method!!! - activate_robot")
            self.robot_is_active = True
            self.__circle = Circle(self.robot_position, 10, facecolor='green', edgecolor='green')
            self.__circle = self.ax.add_artist(self.__circle)
            self.__triangle = self.__create_triangle(self.robot_position, self.robot_direction)
            self.__triangle = self.ax.add_artist(self.__triangle)
            self.fig.canvas.draw_idle()
            self.fig.canvas.flush_events()
        
        """
        # This funktion is used to update the position and orientation of the robot on the plot.
        # Currently the robot simulation is not usable!
        """
        def update_robot(self):
            print("Do not use this method!!! - update_robot")
            if self.robot_is_active:
                try:
                    self.__circle.remove()
                    self.__triangle.remove()
                except NotImplementedError:
                    pass
                self.__triangle = self.triangle = self.__create_triangle(self.robot_position, self.robot_direction)
                self.__triangle = self.ax.add_artist(self.__triangle)
                self.__circle = Circle(self.robot_position, 15, facecolor='green', edgecolor='green')
                self.__circle = self.ax.add_artist(self.__circle)
                self.fig.canvas.draw_idle()
                self.fig.canvas.flush_events()
                
                # self.ax.draw_artist(self.__triangle)
                # self.ax.draw_artist(self.__circle)
                # self.fig.canvas.blit(self.fig.bbox)
                # self.ax.figure.canvas.flush_events()
                
                # try:
                #     self.ax.draw_artist(self.__triangle)
                #     self.ax.draw_artist(self.__circle)
                    
                # except AttributeError:
                #     pass
                # self.__circle.set_center(self.robot_position)
                # self.ax.draw_artist(self.__circle)
                # self.fig.canvas.blit(self.fig.bbox)
                # self.fig.canvas.flush_events()
                
        """
        # This funktion close the window.
        """
        def close(self):
            plt.close(self.fig)
    
    """
    # This class creates a little Dashborad with the most important information from the robot and the localization.
    """
    class Dashboard:
        """
        # This constructor needs nothing and set up all values for the dashboard.
        """
        def __init__(self):
            self.current_section_type = ""
            self.last_sections_type = ""
            self.enter_new_section = ""
            self.last_known_section = ""
            self.count_fail_loc = 0
            self.x_position = 0
            self.y_position = 0
            self.driven_distance_on_section = 0
            
            self.window = tk.Tk()
            self.window.title("Dashboard")
            
            self.label_current_section_type = tk.Label(self.window, text="current section type:")
            self.label_last_sections_type = tk.Label(self.window, text="last sections type:")
            self.label_enter_new_section = tk.Label(self.window, text="enter new section:")
            self.label_last_known_section = tk.Label(self.window, text="last known section:")
            self.label_count_fail_loc = tk.Label(self.window, text="count fail loc:")
            self.label_x_position = tk.Label(self.window, text="x position:")
            self.label_y_position = tk.Label(self.window, text="y position:")
            self.label_driven_distance_on_section = tk.Label(self.window, text="driven distance on section:")
            
            self.label_current_section_type.pack()
            self.label_last_sections_type.pack()
            self.label_enter_new_section.pack()
            self.label_last_known_section.pack()
            self.label_count_fail_loc.pack()
            self.label_x_position.pack()
            self.label_y_position.pack()
            self.label_driven_distance_on_section.pack()
            
            self.window.protocol("WM_DELETE_WINDOW", print(""))
            self.window.update_idletasks()
            self.window.update()
    
        """
        # This function sets the current section type to the dashboard
        """
        def set_current_section_type(self, section_type):
            self.current_section_type = section_type
            self.label_current_section_type.config(text="current section type: " + self.current_section_type)
            self.update_window()
        
        """
        # This function sets the last sections type to the dashboard
        """
        def set_last_sections_type(self, last_sections_type):
            self.last_sections_type = last_sections_type
            self.label_last_sections_type.config(text="last sections type: " + self.last_sections_type)
            self.update_window()
        
        """
        # This function sets the value enter new section to the dashboard
        """
        def set_enter_new_section(self, enter_new_section):
            self.enter_new_section = enter_new_section
            self.label_enter_new_section.config(text="enter new section: " + self.enter_new_section)
            self.update_window()
        
        """
        # This function sets the last known section to the dashboard
        """
        def set_last_known_section(self, last_known_section):
            self.last_known_section = last_known_section
            self.label_last_known_section.config(text="last known section: " + self.last_known_section)
            self.update_window()
        
        """
        # This function sets the counter fail localization to the dashboard
        """
        def set_count_fail_loc(self, count_fail_loc):
            self.count_fail_loc = count_fail_loc
            self.label_count_fail_loc.config(text="count fail loc: " + str(self.count_fail_loc))
            self.update_window()
        
        """
        # This function sets the x position of the robot to the dashboard
        """
        def set_x_position(self, x_position):
            self.x_position = x_position/1000
            self.label_x_position.config(text="x position: " + str(self.x_position) + " m")
            self.update_window()
        
        """
        # This function sets the y position of the robot to the dashboard
        """  
        def set_y_position(self, y_position):
            self.y_position = y_position/1000
            self.label_y_position.config(text="y position: " + str(self.y_position) + " m")
            self.update_window()
        
        """
        # This function sets the driven distance on the section to the dashboard
        """
        def set_driven_distance_on_section(self, driven_distance_on_section):
            self.driven_distance_on_section = driven_distance_on_section/1000
            self.label_driven_distance_on_section.config(text="driven distance on section: " + str(self.driven_distance_on_section) + " m")
            self.update_window()
        
        """
        # This function update the dashboard it's self. without this method, the dashboard will not refresh.
        """
        def update_window(self):
            self.window.update_idletasks()
            self.window.update()
    
    #%% Main Skript
    
    if __name__ == '__main__':
        # Line plotter without timing
        #ln_plotter_1 = Line_Plotter("Linieargeschwindigkeit", "Zeitschritte", "mm/s")
        #ln_plotter_2 = Line_Plotter("Winkelgeschwindigkeit", "Zeitschritte", "rad/s")
        #for i in range(200):
            #ln_plotter_1.update(random.random() * 5)
            #ln_plotter_2.update(random.random() * 5)
            #time.sleep(0.05)
        
        # Line plotter with timing
        # ln_plotter_1 = Line_Plotter_Time("Linieargeschwindigkeit", "s", "mm/s")
        # ln_plotter_2 = Line_Plotter_Time("Winkelgeschwindigkeit", "s", "rad/s")
        # for i in range(200):
        #     ln_plotter_1.update(random.random() * 5, 0.05)
        #     ln_plotter_2.update(random.random() * 5, 0.05)
        #     #time.sleep(0.05)
        
        # Track plotting
        background, track = Track_Plotter.get_set_of_trackparts_3()
        
        tr_plotter = Track_Plotter(background, track)
        #tr_plotter.activate_robot()
        #tr_plotter.update_robot()
        #tr_plotter.set_robot_to_trackpart('S1')
        for i in range(3):
            if i == 0:
                tr_plotter.select_trackpart('S1')
            if i ==  1:
                tr_plotter.select_trackpart('S5')
            if i == 2:
                tr_plotter.select_trackpart('S9')
            time.sleep(3)