본문 바로가기

Projects/2021년 기초제어실습

wall follower- 센서 데이터 그래프 생성하기

보고서를 내야 하는데, 어지간하면 그래프를 보여주면서 하고 싶단 말이지?

그래서, 전에 CF 다루면서 썼던 코드를 좀 많이 수정해 보려고 한다.

그러려고 했는데,

  1. ev3 내부에 numpy같은 라이브러리를 새로 설치해야 하는데, 어떻게 ev3 내부에서 명령어를 실행할 수 있을지 모르겠다.
  1. 굳이 tk를 쓸 이유가 없어서 그냥 matplotlib & numpy로 새로 짜는게 더 나을 듯 하다.

받아온 거리값으로 그래프 만들기

제목→ "pid_graph_dist:"

y축 → distance(mm)

x축 → 시간(s).

ev3에서 별도의 파일을 동시에 실행시킬 수가 없고 ev3 안의 파일을 외부에서 읽을 수 있는지 모른다.

  • CODE ver1.0
    # Make a DataList from txt file AND make graph of data with time
    
    import matplotlib as plt
    import numpy as np
    import time
    import datetime
    from final_term_pre import main as maincode
    
    class MakeDataList:
        def __init__(self, txt_uri):
            self.DataList =[]
            self.DataList_prev = []
            self.f = open(txt_uri, 'r', encoding='UTF8')
    
            self.figplot = plt.Figure(figsize=(5, 4), dpi=100)
            self.ax2 = self.figplot.add_subplot(111)
    
        def ReadLineFrom_txt(self):
            # Find Kp, Ki, Kd string and make a list of data.
            while True:
                line = self.f.readline()
    
                if  "Kp" in line:
                    Kp = line
                    continue
                elif "Ki" in line:
                    Ki = line
                    continue
                elif "Kd" in line:
                    Kd = line
                    continue
                elif line == "Program ended by stop button" or "----------" or "Completed successfully.":
                    continue
                else:
                    self.DataList.append(line)
    
                if not line:
                    break
    
            print(Kp, Ki, Kd, self.DataList)
    
        def MakeGraph(self):
            x= np.arange(0,20, 0.25)
            y= self.DataList
            y_tgt = maincode.target
    
            self.ax2.clear()
    
            self.ax2.plt.xlim([0, 30])
            self.ax2.plt.ylim([0, 1000])
    
            self.ax2.plot(x, self.DataList_prev, '-' ,label='dist_prev', color='red', alpha=0.5)
            self.ax2.plot(x, y, '-' , label='dist', color='red')
            self.ax2.plot(x, y_tgt, '--' ,label='desired', color='blue')
    
            self.ax2.set_title('Mindstrom_wallfollowing_PID', loc='right')
            self.ax2.set_xlabel('Time (s)', loc='right')
            self.ax2.set_ylabel('Distance (mm)', loc='top')
    
            self.now = datetime.datetime.now()
            self.figplot.savefig('pid_graph_'+ self.now.strftime("%Y-%m-%d_%H:%M:%S")+'.png') # !!!!!
    
    def run():
        MakeDataList.ReadLineFrom_txt()
        MakeDataList.MakeGraph()
    
    if __name__ ==  "__main__":
        txt_uri = "~/assignment_2021/Basic_Control/exp_001.txt"
        MakeDataList(txt_uri)
        run()

  • CODE ver2.0
    # Make a DataList from txt file AND make graph of data with time
    
    import matplotlib.pyplot as plt
    import numpy as np
    import datetime
    #from final_term_pre import main as maincode
    
    class MakeDataList:
        def __init__(self, txt_uri_recent, txt_uri_prev):
            self.DataList = None
            self.txt_uri_recent = txt_uri_recent
            self.txt_uri_prev = txt_uri_prev
            #self.f_recent = open(txt_uri_recent, 'r', encoding='UTF8')
            #self.f_prev = open(txt_uri_prev, 'r', encoding='UTF8')
            self.figplot = plt.Figure(figsize=(5, 4), dpi=100)
            self.ax2 = self.figplot.add_subplot(111)
    
        def ReadLineFrom_txt(self, txt_uri):
            # Find Kp, Ki, Kd string and make a list of data.
            f_now = open(txt_uri, 'r', encoding='UTF8')
            DataList_now =[]
            while True:
                line = f_now.readline()
    
                if  "Kp" in line:
                    Kp = line
                    pass
                elif "Ki" in line:
                    Ki = line
                    pass
                elif "Kd" in line:
                    Kd = line
                    pass
                else:
                    if "Program ended by stop button" in line:
                        pass
                    elif  "----------" in line:
                        pass
                    elif "Completed successfully." in line:
                        pass
                    else:
                        DataList_now.append(line[0:3])
    
                if not line:
                    break
    
            print(Kp, Ki, Kd, DataList_now)
            self.DataList = DataList_now
    
    
        def MakeGraph(self, desire_alpha):
            x= np.arange(0,20, 0.125)
            y= self.DataList
    
            # when you use pybrick, use the code below...
            #y_tgt = maincode.target
            y_tgt = 150
    
            #self.ax2.clear()
    
            plt.xlim([0, 30])
            plt.ylim([0, 1000])
    
            self.ax2.plot(x, y, '-' , label='dist', color='red', alpha=desire_alpha)
            self.ax2.plot(x, y_tgt, '--' ,label='desired', color='blue')
    
            self.ax2.set_title('Mindstrom_wallfollowing_PID', loc='right')
            self.ax2.set_xlabel('Time (s)', loc='right')
            self.ax2.set_ylabel('Distance (mm)', loc='top')
    
            self.now = datetime.datetime.now()
            self.figplot.savefig('pid_graph_'+ self.now.strftime("%Y-%m-%d_%H:%M:%S")+'.png') # !!!!!
    
            self.DataList =None
    
        def run(self):
            # Draw prev sensor data graph
            MakeDataList.ReadLineFrom_txt(self, self.txt_uri_prev)
            MakeDataList.MakeGraph(self, 0.5)
    
            # Draw recent sensor data graph
            MakeDataList.ReadLineFrom_txt(self, self.txt_uri_recent)
            MakeDataList.MakeGraph(self, 1.0)
    
            self.ax2.show()
    
    
    if __name__ ==  "__main__":
        #txt_uri = '~/assignment_2021/Basic_Control/exp_001.txt'
        txt_uri_recent = "/home/masterpyo/assignment_2021/Basic_Control/exp_001.txt"
        txt_uri_prev = "/home/masterpyo/assignment_2021/Basic_Control/exp_002.txt"
        MDL = MakeDataList(txt_uri_recent, txt_uri_prev)
        MDL.run()

중간결과!

개선사항

  • 파란 기준선!
    • 해결!
  • PID 파라미터 표시!
    • 해결!
  • 그래프 동시에 나오게 하기!
    • 해결!
  • y축 빼곡한거 더 널널하게!

으아아아아아ㅏ!!!!!!!!!!!!!!1

왜 안돼!!!!

  • y값이 마음대로 논다. 지보다 높은 값이 위에 있질 않나 중간에 낮은 값이 껴있지 않나 → set_ylim을 해봤는데 이상해...
  • 아마 위의 문제랑 겹치는 것 같은데, 파랑 기준선이 지 맘대로 논다
  • 실제로 실험 돌리면 코드에서 현재시간 - 시작시간으로 데이터 길이를 제한할 거지만, x값도 좀 문제가 있는 듯 하다. 지금은 데이터가 들어간 리스트의 구성요소 개수(len(~))으로 해놨는데, 10000은 너무 많잖아. 지금 len(DataList) 이게 recent_data ⇒ range(0, 1002) 1002, prev_data ⇒ range(0, 1002) 1002 이렇게 되는데.
y_prev = self.DataList_prev
        y= self.DataList

        x= range(len(y))
        print(x, len(y))
        print(x, len(y_prev))

        # when you use pybrick, use the code below...
        #y_tgt = maincode.target
        y_tgt = '150'

        self.ax2.set_xlim([0,100])
        self.ax2.set_ylim([0,300])

  • CODE ver.3.0
    # Make a DataList from txt file AND make graph of data with time
    
    import matplotlib.pyplot as plt
    import numpy as np
    import datetime
    #from final_term_pre import main as maincode
    
    class MakeDataList:
        def __init__(self, txt_uri_recent, txt_uri_prev):
            self.DataList = None
            self.DataList_prev = None
            self.txt_uri_recent = txt_uri_recent
            self.txt_uri_prev = txt_uri_prev
            self.Kp = None
            self.Ki = None
            self.Kd = None
    
            self.figplot = plt.Figure(figsize=(5, 4), dpi=1000)
            self.ax2 = self.figplot.add_subplot(111)
    
        def ReadLineFrom_txt(self, txt_uri):
            # Find Kp, Ki, Kd string and make a list of data.
    
            if txt_uri == self.txt_uri_prev :
                txt_uri = self.txt_uri_prev
                factor_time = True
            elif txt_uri == self.txt_uri_recent:
                txt_uri = self.txt_uri_recent
                factor_time = False
            else:
                print("e")
    
            f_now = open(txt_uri, 'r', encoding='UTF8')
            DataList_now =[]
            while True:
                line = f_now.readline()
    
                if  "Kp" in line:
                    self.Kp = line
                    pass
                elif "Ki" in line:
                    self.Ki = line
                    pass
                elif "Kd" in line:
                    self.Kd = line
                    pass
                else:
                    if "Program ended by stop button" in line:
                        pass
                    elif  "----------" in line:
                        pass
                    elif "Completed successfully." in line:
                        pass
                    else:
                        DataList_now.append(line[0:3])
    
                if not line:
                    break
    
            #print(Kp, Ki, Kd, DataList_now)
    
            if factor_time == True:
                self.DataList_prev = DataList_now
            elif factor_time == False:
                self.DataList = DataList_now
    
    
    
        def MakeGraph(self):
            # Graph initalize
            self.ax2.clear()
    
            y_prev = self.DataList_prev
            y= self.DataList
    
            x= range(len(y))
            print(x, len(y))
            print(x, len(y_prev))
    
            # when you use pybrick, use the code below...
            #y_tgt = maincode.target
            y_tgt = '150'
    
            self.ax2.set_xlim([0,100])
            self.ax2.set_ylim([0,300])
    
            self.ax2.plot(x, y_prev, '-' , label='dist_prev', color='red', alpha=0.5)
            self.ax2.plot(x, y, '-' , label='dist_recent', color='red')
    
            self.ax2.axhline(y= y_tgt, color = 'blue', linestyle='--')
    
            self.ax2.set_title('Mindstrom_wallfollowing_PID', loc='right')
            self.ax2.set_xlabel('Time (s)', loc='right')
            self.ax2.set_ylabel('Distance (mm)', loc='top')
    
            self.ax2.text(7.80,6.0, 'Kp='+ str(self.Kp[4:]))
            self.ax2.text(7.80,4.0, 'Ki='+ str(self.Ki[4:]))
            self.ax2.text(7.80,2.0, 'Kd='+ str(self.Kd[4:]))
    
            self.now = datetime.datetime.now()
            self.figplot.savefig('pid_graph_'+ self.now.strftime("%Y-%m-%d_%H:%M:%S")+'.png') # !!!!!
    
    
        def run(self):
            # Read recent sensor data graph
            MakeDataList.ReadLineFrom_txt(self, self.txt_uri_recent)
            # Read prev sensor data graph
            MakeDataList.ReadLineFrom_txt(self, self.txt_uri_prev)
            # Draw data graph
            MakeDataList.MakeGraph(self)
    
    
    
    
    if __name__ ==  "__main__":
        #txt_uri = '~/assignment_2021/Basic_Control/exp_001.txt'
        txt_uri_recent = "/home/masterpyo/assignment_2021/Basic_Control/exp_004.txt"
        txt_uri_prev = "/home/masterpyo/assignment_2021/Basic_Control/exp_003.txt"
        MDL = MakeDataList(txt_uri_recent, txt_uri_prev)
        MDL.run()

환장하제

⇒ 데이터를 수집할때 시간 데이터도 가져오자. 거리값 & 시간!

  • CODE ver4.0
    # Make a DataList from txt file AND make graph of data with time
    
    import matplotlib.pyplot as plt
    import numpy as np
    import datetime
    #from final_term_pre import main as maincode
    
    ## 2021/11/22 update : Adding time value; Reaing, Making graph
    
    class MakeDataList:
        def __init__(self, txt_uri_recent, txt_uri_prev):
            self.txt_uri_recent = txt_uri_recent
            self.txt_uri_prev = txt_uri_prev
            self.DataList = None
            self.DataList_prev = None
            self.TimeList =None
            self.TimeList_prev =None
            self.Kp = None
            self.Ki = None
            self.Kd = None
    
            self.figplot = plt.Figure(figsize=(5, 4), dpi=1000)
            self.ax2 = self.figplot.add_subplot(111)
    
        def ReadLineFrom_txt(self, txt_uri):
            # Find Kp, Ki, Kd string and make a list of data.
    
            if txt_uri == self.txt_uri_prev :
                txt_uri = self.txt_uri_prev
                factor_time = True
            elif txt_uri == self.txt_uri_recent:
                txt_uri = self.txt_uri_recent
                factor_time = False
            else:
                print("e")
    
            f_now = open(txt_uri, 'r', encoding='UTF8')
            DataList_now =[]
            TimeList_now =[]
    
            while True:
                line = f_now.readline()
    
                if  "Kp" in line:
                    self.Kp = line
                    pass
                elif "Ki" in line:
                    self.Ki = line
                    pass
                elif "Kd" in line:
                    self.Kd = line
                    pass
                else:
                    if "Program ended by stop button" in line:
                        pass
                    elif  "----------" in line:
                        pass
                    elif "Completed successfully." in line:
                        pass
                    elif "2021" in line:
                        TimeList_now.append(line)
                    else:
                        DataList_now.append(line[0:3])
    
                if not line:
                    break
    
            #print(Kp, Ki, Kd, DataList_now)
    
            if factor_time == True:
                self.DataList_prev = DataList_now
                self.TimeList_prev = TimeList_now
            elif factor_time == False:
                self.DataList = DataList_now
                self.TimeList = TimeList_now
    
    
    
        def MakeGraph(self):
            # Graph initalize
            self.ax2.clear()
    
            y_prev = self.DataList_prev
            y= self.DataList
    
            x_prev = self.TimeList_prev
            x = self.TimeList
    
            print(len(x), len(y))
            print(len(x_prev), len(y_prev))
    
            # when you use pybrick, use the code below...
            #y_tgt = maincode.target
            y_tgt = '150'
    
            self.ax2.set_xlim([0,100])
            self.ax2.set_ylim([0,300])
    
            self.ax2.plot(x_prev, y_prev, '-' , label='dist_prev', color='red', alpha=0.5)
            self.ax2.plot(x, y, '-' , label='dist_recent', color='red')
    
            self.ax2.axhline(y= y_tgt, color = 'blue', linestyle='--')
    
            self.ax2.set_title('Mindstrom_wallfollowing_PID', loc='right')
            self.ax2.set_xlabel('Time (s)', loc='right')
            self.ax2.set_ylabel('Distance (mm)', loc='top')
    
            self.ax2.text(7.80,6.0, 'Kp='+ str(self.Kp[4:]))
            self.ax2.text(7.80,4.0, 'Ki='+ str(self.Ki[4:]))
            self.ax2.text(7.80,2.0, 'Kd='+ str(self.Kd[4:]))
    
            self.now = datetime.datetime.now()
            self.figplot.savefig('pid_graph_'+ self.now.strftime("%Y-%m-%d_%H:%M:%S")+'.png') # !!!!!
    
    
        def run(self):
            # Read recent sensor data graph
            MakeDataList.ReadLineFrom_txt(self, self.txt_uri_recent)
            # Read prev sensor data graph
            MakeDataList.ReadLineFrom_txt(self, self.txt_uri_prev)
            # Draw data graph
            MakeDataList.MakeGraph(self)
    
    
    
    
    if __name__ ==  "__main__":
    
        #txt_uri = '~/assignment_2021/Basic_Control/exp_001.txt'
        txt_uri_recent = "/home/masterpyo/assignment_2021/Basic_Control/exp_004.txt"
        txt_uri_prev = "/home/masterpyo/assignment_2021/Basic_Control/exp_003.txt"
        MDL = MakeDataList(txt_uri_recent, txt_uri_prev)
        MDL.run()

끝!!!

pybrick에서 시간 모듈이 안되길래 기존처럼 센서 데이터만 가져오는 대신에, 인덱싱을 해주는 프로그램을 만들었다.

그런데 인덱싱하는건 좋았는데 하고 나니까 자꾸 null 데이터(' ')가 들어갔다.

리스트로 받아온 거리값 & 인덱스는 문자열 자료형이기 때문에 정수형으로 바꿔줘야 그래프에 순서대로 쌓인다. 때문에 list(map())으로 정수형으로 변환을 시켰는데 들어온 null 데이터 때문에 자꾸 에러가 생겼다.

그래서 그냥 데이터를 적당히 잘라서 각 텍스트 문서 길이만큼 count가 쌓이면 break 되도록 했다.

해결!

  • CODE ver5.0 _hardcoding&fin
    # Make a DataList from txt file AND make graph of data with time
    
    import matplotlib.pyplot as plt
    import numpy as np
    import datetime
    #from final_term_pre import main as maincode
    
    ## 2021/11/22 update : Adding time value; Reaing, Making graph
    ## 2021/11/23 update : Adding count(time, data) for stop reading null data
    ##              graph: 'vel', 'dt' text included 
    class MakeDataList:
        def __init__(self, txt_uri_recent, txt_uri_prev):
            self.txt_uri_recent = txt_uri_recent
            self.txt_uri_prev = txt_uri_prev
            self.DataList = None
            self.DataList_prev = None
            self.TimeList =None
            self.TimeList_prev =None
            self.Kp = None
            self.Ki = None
            self.Kd = None
            self.vel = None
            self.dt = None
    
            self.figplot = plt.Figure(figsize=(5, 4), dpi=1000)
            self.ax2 = self.figplot.add_subplot(111)
    
        def ReadLineFrom_txt(self, txt_uri):
            # Find Kp, Ki, Kd string and make a list of data.
    
            if txt_uri == self.txt_uri_prev :
                txt_uri = self.txt_uri_prev
                factor_time = True
            elif txt_uri == self.txt_uri_recent:
                txt_uri = self.txt_uri_recent
                factor_time = False
            else:
                print("e")
    
            f_now = open(txt_uri, 'r')
            DataList_now =[]
            TimeList_now =[]
            count_T = 0
            count_data =0
    
            while True:
                line = f_now.readline()
    
                if  "Kp" in line:
                    self.Kp = line
                    pass
                elif "Ki" in line:
                    self.Ki = line
                    pass
                elif "Kd" in line:
                    self.Kd = line
                    pass
                elif "vel" in line:
                    self.vel = line
                    pass
                elif "dt" in line:
                    self.dt = line
                    pass
                else:
                    if "Program ended by stop button" in line:
                        pass
                    elif  "----------" in line:
                        pass
                    elif "Completed successfully." in line:
                        pass
                    elif "T: " in line:
                        line = line.strip('\n')
                        line = line.strip(' ')
                        TimeList_now.append(int(line[3:]))
                        print("CT = %d" %count_T)
                        count_T +=1
                    else:
                        line = line.strip('\n')
                        line = line.strip(' ')
                        DataList_now.append(int(line[:]))
                        print("CD = %d"  %count_data)
                        count_data += 1
    
                # 5293 == exp_B_INDEXED.txt Data.len()
                if (factor_time == True) and (count_T == 5293):
                    break
                # 7437 == exp_B_INDEXED.txt Data.len()
                elif (factor_time == False) and (count_T == 7437):
                    break
                # 11241 == exp_BOX_INDEXED.txt Data.len()
                #if (factor_time == True) and (count_T == 11241):
                #    break
                # 11241 == exp_BOX_INDEXED.txt Data.len()
                #elif (factor_time == False) and (count_T == 7825):
                #    break
    
            if factor_time == True:
                self.DataList_prev = DataList_now
                self.TimeList_prev = TimeList_now
            elif factor_time == False:
                self.DataList = DataList_now
                self.TimeList = TimeList_now
    
    
    
        def MakeGraph(self):
            # Graph initalize
            self.ax2.clear()
            y_prev = []
            y = []
            x_prev =[]
            x= []
            
            # Transform : string list -> int list
            #y_prev = list(map(int,self.DataList_prev))
            #y= list(map(int,self.DataList))
            #x_prev = list(map(int,self.TimeList_prev))
            #x = list(map(int,self.TimeList))
            y_prev = self.DataList_prev
            y=self.DataList
    
            x_prev = self.TimeList_prev
            x = self.TimeList
    
            #print(len(x), len(y))
    
            # when you use pybrick, use the code below...
            #y_tgt = maincode.target
            y_tgt = '150'
    
            #self.ax2.set_xlim([0,100])
            self.ax2.set_ylim([0,300])
    
            self.ax2.plot(x_prev, y_prev, '-' , label='dist_prev', color='red', alpha=1.0)
            self.ax2.plot(x, y, '-' , label='dist_recent', color='red')
            self.ax2.axhline(y= int(y_tgt), color = 'blue', linestyle='--')
    
            self.ax2.set_title('Mindstrom_wallfollowing_PID', loc='right')
            self.ax2.set_xlabel('Time (sequence)', loc='right')
            self.ax2.set_ylabel('Distance (mm)', loc='top')
    
            #self.ax2.text(7.80,600.0, 'Kp='+ str(self.Kp[4:]))
            #self.ax2.text(7.80,570.0, 'Ki='+ str(self.Ki[4:]))
            #self.ax2.text(7.80,540.0, 'Kd='+ str(self.Kd[4:]))
            #self.ax2.text(7.80,510.0, 'vel'+ str(self.vel[4:]))
            #self.ax2.text(7.80,480.0, 'dt='+ str(self.dt[4:]))
            
            self.ax2.text(7.80,250.0, 'Kp='+ str(self.Kp[4:]))
            self.ax2.text(7.80,235.0, 'Ki='+ str(self.Ki[4:]))
            self.ax2.text(7.80,220.0, 'Kd='+ str(self.Kd[4:]))
            self.ax2.text(7.80,205.0, 'vel'+ str(self.vel[4:]))
            self.ax2.text(7.80,190.0, 'dt='+ str(self.dt[4:]))
    
            self.now = datetime.datetime.now()
            self.figplot.savefig('pid_graph_'+ self.now.strftime("%Y-%m-%d_%H:%M:%S")+'.png') # !!!!!
    
    
        def run(self):
            # Read recent sensor data graph
            MakeDataList.ReadLineFrom_txt(self, self.txt_uri_recent)
            # Read prev sensor data graph
            MakeDataList.ReadLineFrom_txt(self, self.txt_uri_prev)
            # Draw data graph
            MakeDataList.MakeGraph(self)
    
    
    
    
    if __name__ ==  "__main__":
    
        #txt_uri = '~/assignment_2021/Basic_Control/exp_001.txt'
        txt_uri_recent = "/home/masterpyo/assignment_2021/Basic_Control/exp_A_INDEXED.txt"
        txt_uri_prev = "/home/masterpyo/assignment_2021/Basic_Control/exp_B_INDEXED.txt"
        MDL = MakeDataList(txt_uri_recent, txt_uri_prev)
        MDL.run()


Uploaded by N2T

'Projects > 2021년 기초제어실습' 카테고리의 다른 글

프로젝트 개요  (0) 2023.01.03
Line Tracer-코드 정리  (0) 2023.01.03
Line Tracer-센서 데이터 그래프 생성  (0) 2023.01.03
wall follower-실험용 코드  (0) 2023.01.03
wall follower-코드 정리  (0) 2023.01.03