diff --git a/.gitmodules b/.gitmodules index 7164337..022ac4b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "Work 1/report/AUThReport"] path = Work 1/report/AUThReport url = ssh://git@git.hoo2.net:222/hoo2/AUThReport.git +[submodule "Work 2/report/AUThReport"] + path = Work 2/report/AUThReport + url = ssh://git@git.hoo2.net:222/hoo2/AUThReport.git diff --git a/Work 1/report/Work1_report.pdf b/Work 1/report/Work1_report.pdf index 8137095..4d311ac 100644 Binary files a/Work 1/report/Work1_report.pdf and b/Work 1/report/Work1_report.pdf differ diff --git a/Work 1/report/Work1_report.tex b/Work 1/report/Work1_report.tex index 899748d..a30368f 100644 --- a/Work 1/report/Work1_report.tex +++ b/Work 1/report/Work1_report.tex @@ -48,7 +48,7 @@ %\CoAuthorMail{xxx@ece.auth.gr} \DocTitle{Εργασία 1} -\DocSubTitle{Έλεγχος γωνίας προσανατολισμού δορυφόρου με ασαφείς ελεγκτές} +\DocSubTitle{Έλεγχος γωνίας προσανατολισμού δορυφόρου - Σειρά 15} \Department{Τμήμα ΗΜΜΥ. Τομέας Ηλεκτρονικής} \ClassName{Ασαφή Συστήματα (Υπολογιστική Νοημοσύνη)} @@ -87,7 +87,7 @@ \section{Εισαγωγή} -Στην εργασία αυτή εξετάζεται ο έλεγχος του συστήματος +Στην εργασία αυτή (Σειρά 15), εξετάζεται ο έλεγχος του συστήματος $G_p(s)=\frac{10}{(s+1)(s+9)}$ με δύο προσεγγίσεις: (i) κλασικός PI και (ii) ασαφής ελεγκτής τύπου Fuzzy–PI (Mamdani). Στόχος είναι η ικανοποίηση προδιαγραφών μεταβατικής απόκρισης (υπερύψωση, χρόνος ανόδου/αποκατάστασης) και η σύγκριση της ικανότητας παρακολούθησης αναφορών. diff --git a/Work 2/report/.gitignore b/Work 2/report/.gitignore new file mode 100644 index 0000000..16091e6 --- /dev/null +++ b/Work 2/report/.gitignore @@ -0,0 +1,6 @@ +# LaTeX auxiliary files +*.aux +*.log +*.out +*.synctex.gz + diff --git a/Work 2/report/AUThReport b/Work 2/report/AUThReport new file mode 160000 index 0000000..74ec4b5 --- /dev/null +++ b/Work 2/report/AUThReport @@ -0,0 +1 @@ +Subproject commit 74ec4b5f6c66382e5f1b6d2e6930897e4ed53ea6 diff --git a/Work 2/report/Work2_report.pdf b/Work 2/report/Work2_report.pdf new file mode 100644 index 0000000..ae28018 Binary files /dev/null and b/Work 2/report/Work2_report.pdf differ diff --git a/Work 2/report/Work2_report.tex b/Work 2/report/Work2_report.tex new file mode 100644 index 0000000..ceb78fd --- /dev/null +++ b/Work 2/report/Work2_report.tex @@ -0,0 +1,209 @@ +% +% !TEX TS-program = xelatex +% !TEX encoding = UTF-8 Unicode +% !TEX spellcheck = el-GR +% +% Fuzzy Systems Assignment 2 +% +% Requires compilation with pdfLaTeX or XeLaTeX +% +% authors: +% Χρήστος Χουτουρίδης ΑΕΜ 8997 +% cchoutou@ece.auth.gr + +% Options: +% +% 1) mainlang= +% Default: english +% Set the default language of the document which affects hyphenations, +% localization (section, dates, etc...) +% +% example: \documentclass[mainlang=greek]{AUThReport} +% +% 2) +% Add hyphenation and typesetting support for other languages +% Currently supports: english, greek, german, frenc +% +% example: \documentclass[english, greek]{AUThReport} +% +% 3) short: Requests a shorter title for the document +% Default: no short +% +% example: \documentclass[short]{AUThReport} +% +\documentclass[a4paper, 11pt, mainlang=greek, english]{AUThReport/AUThReport} + +\CurrentDate{\today} + +% Greek report document setup suggestions +%--------------------------------- +% \WorkGroup{Ομάδα Χ} + +\AuthorName{Χρήστος Χουτουρίδης} +\AuthorAEM{8997} +\AuthorMail{cchoutou@ece.auth.gr} + +%\CoAuthorName{Όνομα Επίθετο} +%\CoAuthorAEM{1234} +%\CoAuthorMail{xxx@ece.auth.gr} + +\DocTitle{Εργασία 2} +\DocSubTitle{Car Control - Σειρά 3} + +\Department{Τμήμα ΗΜΜΥ. Τομέας Ηλεκτρονικής} +\ClassName{Ασαφή Συστήματα (Υπολογιστική Νοημοσύνη)} + +\InstructorName{Θεοχάρης Ιωάννης} +\InstructorMail{theochar@ece.auth.gr} + +\CoInstructorName{Χαδουλός Χρήστος} +\CoInstructorMail{christgc@auth.gr} + + +\usepackage{float} +\usepackage{minted} +\usepackage{xcolor} % +\usepackage{amsmath, amssymb, amsfonts} +\usepackage{diagbox} +%\usepackage{tabular} + +\setminted[cpp]{ + fontsize=\small, + breaklines, + autogobble, + baselinestretch=1.1, + tabsize=2, + numbersep=8pt, + gobble=0 +} + +\newcommand{\repo}{https://git.hoo2.net/hoo2/FuzzySystems/src/branch/master/Work\%202} + +\begin{document} + +% Request a title page or header +\InsertTitle +%\InsertTitle[img/background.png][0.8\textwidth][2cm] + +\section{Εισαγωγή} + +Στην παρούσα εργασία σχεδιάστηκε και αξιολογήθηκε ένας \textbf{ελεγκτής ασαφούς λογικής (FLC)} τύπου Mamdani για το πρόβλημα \textit{Car Control} (Σειρά~3). Το όχημα κινείται σε επίπεδο με \emph{σκαλοπάτια}/εμπόδια και στόχος είναι να ακολουθεί μια ασφαλή τροχιά, λαμβάνοντας ως πληροφορία μόνο τις \emph{αποστάσεις από τα εμπόδια} και τον \emph{προσανατολισμό} του. + +Ο ελεγκτής υλοποιεί κανόνες της μορφής +\[ + \text{IF } d_V \text{ is } \{S,M,L\} \text{ AND } d_H \text{ is } \{S,M,L\} \text{ AND } \theta \text{ is } \{N,ZE,P\} \text{ THEN } \Delta\theta \text{ is } \{N,ZE,P\}, +\] +με τελεστές $ \mathrm{AND}:\min $, $ \mathrm{OR}:\max $, συνεπαγωγή $\min$, σύνθεση/συσσώρευση $\mathrm{sum}$ και αποασαφοποίηση $\mathrm{centroid}$ (COA), όπως ζητείται. + +Η ανάπτυξη έγινε σε \textit{MATLAB}. +Το FIS δημιουργήθηκε μέσω του \textit{Fuzzy Logic Designer} (GUI) και αποθηκεύτηκε σε αρχείο \texttt{.fis}. +Η προσομοίωση της κίνησης και η παραγωγή των αποτελεσμάτων έγιναν προγραμματιστικά. + + +\subsection{Παραδοτέα} +Τα παραδοτέα της εργασίας αποτελούνται από: +\begin{itemize} + \item Την παρούσα αναφορά. + \item Τον κατάλογο \textbf{source}, με τον κώδικα της matlab. + \item Το \href{\repo}{σύνδεσμο με το αποθετήριο} που περιέχει τον κώδικα της matlab καθώς και αυτόν της αναφοράς. +\end{itemize} + +\section{Υλοποίηση} +Πριν τη στοχοθετημένη αξιολόγηση, περιγράφεται συνοπτικά η αρχιτεκτονική της υλοποίησης. +Στόχος μας ήταν ένα \emph{αυτοτελές} σενάριο προσομοίωσης που να συνδυάζει: +\begin{itemize} + \item Ένα "νοητό" περιβάλλον με σκαλοπάτια/τοίχους + \item Την κινηματική του οχήματος + \item Τον ασαφή ελεγκτή. +\end{itemize} + +Στο σχήμα \ref{fig:fcl_surface} φαίνεται το περιβάλλον της εργασίας. +\InsertFigure{!ht}{0.65}{fig:fcl_surface}{img/Terain.png}{Απεικόνιση του περιβάλλοντος με σκιασμένες περιοχές.} + +Για να διατηρηθεί καθαρή διεπαφή, το περιβάλλον και η κινηματική ενσωματώθηκαν σε δύο βοηθητικές συναρτήσεις, ενώ ο ελεγκτής ορίστηκε σε ανεξάρτητη συνάρτηση/αντικείμενο FIS. +Η προσομοίωση εκτελείται από ένα κύριο script που διακρητοποιεί τον χρόνο, τροφοδοτεί τον ελεγκτή με μετρήσεις και ενημερώνει την κατάσταση. + +\subsection{\texttt{wallDistance}} + +Η \texttt{wallDistance($corners,x,y$)} υλοποιεί τον ``αισθητήρα'' του περιβάλλοντος. +Δεδομένων των \emph{γωνιών} που ορίζουν τα σκαλοπάτια (πίνακας \texttt{corners} με σημεία $(x_i, y_i)$), υπολογίζει: +\begin{itemize} + \item $d_h$: την \emph{οριζόντια} απόσταση μέχρι τον επόμενο τοίχο στα δεξιά του οχήματος ($x$-διεύθυνση), + \item $d_v$: την \emph{κάθετη} απόσταση μέχρι τον πλησιέστερο ``πάτο'' κάτω από το όχημα ($y$-διεύθυνση). +\end{itemize} +Ο αλγόριθμος ταξινομεί κατάλληλα τα \texttt{corners} (με \texttt{sortrows}) και επιλέγει τα \emph{ενεργά} τμήματα τοίχων ανάλογα με την τρέχουσα θέση $(x,y)$. +Τιμές $d_h,d_v \le 0$ αντιστοιχούν σε σύγκρουση, ενώ $\infty$ δηλώνει απουσία τοίχου προς την εξεταζόμενη κατεύθυνση. +Οι μετρήσεις κατόπιν \emph{κορεσμού} $[0,1]$ χρησιμοποιούνται αυτούσιες ως είσοδοι του FIS, όπως ορίζει η εκφώνηση. + +\subsection{\texttt{moveCar}} +Η \texttt{moveCar($x,y,\theta,\Delta\theta$)} υλοποιεί τη στοιχειώδη κινηματική: πρώτα εφαρμόζεται η διόρθωση γωνίας $\theta \leftarrow \theta+\Delta\theta$, έπειτα ενημερώνεται η θέση +\[ + x \leftarrow x + v\,T_s \cos(\theta), \quad + y \leftarrow y + v\,T_s \sin(\theta), +\] +με σταθερό μέτρο ταχύτητας $v$ και περίοδο δειγματοληψίας $T_s$. +Η γωνία χρησιμοποιείται σε \emph{μοίρες} ώστε να είναι συμβατή με τα διαστήματα της εκφώνησης. + +\subsection{\texttt{carFLC}} +Ο ασαφής ελεγκτής είναι Mamdani με: +\begin{itemize} + \item \textbf{Εισόδους:} $d_h\in[0,1]$, $d_v\in[0,1]$, $\theta\in[-180,180]$ (μοίρες). + \item \textbf{Έξοδο:} $\Delta\theta\in[-130,130]$ (μοίρες). +\end{itemize} +Για $d_h,d_v$ χρησιμοποιούνται τριγωνικές MF $\{S,M,L\}$, ενώ για $\theta$ και $\Delta\theta$ οι MF $\{N,ZE,P\}$ όπως δίνονται στην εκφώνηση. +Οι τελεστές είναι: +\[ + \mathrm{AND}=\min,\quad \mathrm{OR}=\max,\quad \mathrm{Implication}=\min,\quad + \mathrm{Aggregation}=\mathrm{sum},\quad \mathrm{Defuzzification}=\mathrm{centroid}. +\] +Το \texttt{.fis} δημιουργήθηκε με το \emph{Fuzzy Logic Designer} και αποθηκεύτηκε ως \texttt{CarFLC.fis}. +Στο σχήμα \ref{fig:fcl_rules} φαίνεται ένα στηγμιότηπο με τους κανόνες που χρησιμοποιήθηκαν για τον ελεγκτή. +Δυστυχώς, από την προηγούμενη εργασία μέχρι και αυτή, δεν προλάβαμε να γίνουμε ειδικοί, επομένως οι κανόνες βασίζονται και πάλι στη δική μας "φτωχή" προσέγγιση. + +\InsertFigure{!ht}{0.95}{fig:fcl_rules}{img/FLC_Rules.png}{Ενδεικτικό στιγμιότυπο κανόνων.} + +Στο σχήμα \ref{fig:fcl_surface} βλέπουμε και την επιφάνεια των κανόνων ως συνάρτηση των εισόδων των αποστάσεων. + +\InsertFigure{!ht}{0.7}{fig:fcl_surface}{../source/FLC_surface_edit.png}{Ενδεικτική επιφάνεια βάσης κανόνων ($\Delta\theta$ ως συνάρτηση δύο εισόδων).} + +\subsection{\texttt{runSimulation}} +Το κύριο script εκτελεί την προσομοίωση: για κάθε χρονικό βήμα καλεί διαδοχικά \texttt{wallDistance} $\rightarrow$ \texttt{evalfis} $\rightarrow$ \texttt{moveCar}, αποθηκεύοντας την τροχιά. +Η διαδικασία επαναλαμβάνεται για τις τρεις αρχικές γωνίες $\theta_0\in\{-45^\circ,0^\circ,45^\circ\}$. +Στην δική μας έκδοση το όχημα εκκινεί από τη θέση $(x_{init},y_{init}) = (3.8, 0.5)$. +Η εκτέλεση τερματίζει είτε σε σύγκρουση (οριακή τιμή $d_H$ ή $d_V\le0$) είτε όταν το όχημα φτάσει στο $(x_d,y_d) = (10, 3.2)$. + +\section{Ζητούμενα} +Τα ζητούμενα (τροχιές για διαφορετικές αρχικές γωνίες) παράγονται αυτόματα από το \texttt{runSimulation} και αποθηκεύονται ως εικόνες. +Παρακάτω παρατίθενται οι τροχιές από την εκτέλεση του script. + +\InsertFigure{!ht}{0.85}{fig:car_track_min45}{../source/CarMovement_theta-45.png}{Πορεία οχήματος για αρχική γωνία $\theta_0=-45^\circ$.} +\InsertFigure{!ht}{0.85}{fig:car_track_0}{../source/CarMovement_theta0.png}{Πορεία οχήματος για αρχική γωνία $\theta_0=0^\circ$.} +\InsertFigure{!ht}{0.85}{fig:car_track_45}{../source/CarMovement_theta45.png}{Πορεία οχήματος για αρχική γωνία $\theta_0=45^\circ$.} + + +\subsection{Σχολιασμός} +Η λειτουργία του ελεγκτή είναι \emph{σταθερή} και \emph{ομαλή}: παρατηρούνται ομαλές καμπύλες χωρίς απότομες γωνίες, καθώς οι MF επικάλυψης εξομαλύνουν τις μεταβάσεις κανόνων. +Η σύγκλιση προς το επιθυμητό $x_d$ επιτυγχάνεται και στις τρεις περιπτώσεις, με την τροχιά να ακολουθεί πρακτικά τα εμπόδια. + +Ωστόσο, η συμπεριφορά δεν είναι ιδανική για δύο λόγους: +\begin{enumerate} + \item Ο ελεγκτής \textbf{δεν} λαμβάνει άμεση πληροφορία για το \emph{στόχο} ($x_d,y_d$). + Bασίζεται μόνο στις αποστάσεις από εμπόδια και στη γωνία, άρα η κάθετη διόρθωση ($y$) δεν ``οδηγείται'' ρητά από το σφάλμα έως τον στόχο. + \item Οι αποστάσεις $d_h,d_v$ \textbf{ψαλιδισμένες} στο $[0,1]$ περιορίζουν τη δυναμική περιοχή (lossy αισθητηριακή πληροφορία σε μεγάλες αποστάσεις), κάτι που επιβαρύνει την προσέγγιση ειδικά σε ύψος. +\end{enumerate} +Παρά τους περιορισμούς, ο FLC επιτυγχάνει αποφυγή εμποδίων και καλή ευθυγράμμιση με χαμηλό υπολογιστικό κόστος και υψηλή ερμηνευσιμότητα κανόνων. + +\section {Συμπεράσματα} +Αναπτύξαμε έναν Mamdani FLC για το πρόβλημα \textit{Car Control} (Σειρά~3) με εισόδους $(d_h,d_v,\theta)$ και έξοδο $\Delta\theta$. Ο ελεγκτής, με κανόνες τύπου IF--THEN και COA αποασαφοποίηση, κατεύθυνε το όχημα με ομαλές τροχιές, αποφεύγοντας τα εμπόδια και επιτυγχάνοντας τη μετάβαση στο επιθυμητό επίπεδο. +\textbf{Στα θετικά}, είχαμε την ομαλότητα ελέγχου, ερμηνευσιμότητα κανόνων, επαναληψιμότητα σε διαφορετικές αρχικές γωνίες, απλή παραμετροποίηση. +\textbf{Στα αρνητικά}, είχαμε την έλλειψη ρητής πληροφορίας στόχου $(x_d,y_d)$, περιορισμένη δυναμική πληροφορία αποστάσεων λόγω κορεσμού $[0,1]$. + + +Θεωρούμε πως το σύστημα θα βελτιωνόταν αρκετά με: +\begin{itemize} + \item Προσθήκη επιπλέον εισόδου με σφάλμα προς τον στόχο (πχ.\ $e_x=x_d-x,\ e_y=y_d-y$), + \item Ανακλιμάκωση ή προσαρμοστικό κορεσμό των αποστάσεων, + \item Χρήση υβριδικού ελεγκτής (FLC για αποφυγή εμποδίων + PD/TSK για καθοδήγηση στον στόχο). +\end{itemize} + +\end{document} diff --git a/Work 2/report/img/FLC_Rules.png b/Work 2/report/img/FLC_Rules.png new file mode 100644 index 0000000..ce3d9ea Binary files /dev/null and b/Work 2/report/img/FLC_Rules.png differ diff --git a/Work 2/report/img/Terain.png b/Work 2/report/img/Terain.png new file mode 100644 index 0000000..e0c5651 Binary files /dev/null and b/Work 2/report/img/Terain.png differ diff --git a/Work 2/source/.gitignore b/Work 2/source/.gitignore new file mode 100644 index 0000000..41aff6c --- /dev/null +++ b/Work 2/source/.gitignore @@ -0,0 +1,3 @@ +# Matlab auxiliary files +*.asv + diff --git a/Work 2/source/CarFLC.fis b/Work 2/source/CarFLC.fis new file mode 100644 index 0000000..c06628d --- /dev/null +++ b/Work 2/source/CarFLC.fis @@ -0,0 +1,73 @@ +[System] +Name='CarFLC' +Type='mamdani' +Version=2.0 +NumInputs=3 +NumOutputs=1 +NumRules=27 +AndMethod='min' +OrMethod='max' +ImpMethod='min' +AggMethod='sum' +DefuzzMethod='centroid' + +[Input1] +Name='dh' +Range=[0 1] +NumMFs=3 +MF1='S':'trimf',[0 0 0.5] +MF2='M':'trimf',[0 0.5 1] +MF3='L':'trimf',[0.5 1 1] + +[Input2] +Name='dv' +Range=[0 1] +NumMFs=3 +MF1='S':'trimf',[0 0 0.5] +MF2='M':'trimf',[0 0.5 1] +MF3='L':'trimf',[0.5 1 1] + +[Input3] +Name='theta' +Range=[-180 180] +NumMFs=3 +MF1='N':'trimf',[-180 -180 0] +MF2='ZE':'trimf',[-180 0 180] +MF3='P':'trimf',[0 180 180] + +[Output1] +Name='dtheta' +Range=[-130 130] +NumMFs=3 +MF1='N':'trimf',[-130 -130 0] +MF2='ZE':'trimf',[-130 0 130] +MF3='P':'trimf',[0 130 130] + +[Rules] +1 1 1, 3 (1) : 1 +1 2 1, 3 (1) : 1 +1 3 1, 3 (1) : 1 +2 1 1, 3 (1) : 1 +2 2 1, 2 (1) : 1 +2 3 1, 2 (1) : 1 +3 1 1, 3 (1) : 1 +3 2 1, 3 (1) : 1 +3 3 1, 3 (1) : 1 +1 1 2, 3 (1) : 1 +1 2 2, 3 (1) : 1 +1 3 2, 3 (1) : 1 +2 1 2, 2 (1) : 1 +2 2 2, 2 (1) : 1 +2 3 2, 2 (1) : 1 +3 1 2, 2 (1) : 1 +3 2 2, 2 (1) : 1 +3 3 2, 2 (1) : 1 +1 1 3, 2 (1) : 1 +1 2 3, 2 (1) : 1 +1 3 3, 2 (1) : 1 +2 1 3, 2 (1) : 1 +2 2 3, 2 (1) : 1 +2 3 3, 1 (1) : 1 +3 1 3, 2 (1) : 1 +3 2 3, 2 (1) : 1 +3 3 3, 1 (1) : 1 diff --git a/Work 2/source/CarMovement_theta-45.png b/Work 2/source/CarMovement_theta-45.png new file mode 100644 index 0000000..86d8626 Binary files /dev/null and b/Work 2/source/CarMovement_theta-45.png differ diff --git a/Work 2/source/CarMovement_theta0.png b/Work 2/source/CarMovement_theta0.png new file mode 100644 index 0000000..b58b567 Binary files /dev/null and b/Work 2/source/CarMovement_theta0.png differ diff --git a/Work 2/source/CarMovement_theta45.png b/Work 2/source/CarMovement_theta45.png new file mode 100644 index 0000000..d4bf216 Binary files /dev/null and b/Work 2/source/CarMovement_theta45.png differ diff --git a/Work 2/source/FLC_surface.png b/Work 2/source/FLC_surface.png new file mode 100644 index 0000000..ea4a4b4 Binary files /dev/null and b/Work 2/source/FLC_surface.png differ diff --git a/Work 2/source/FLC_surface_edit.png b/Work 2/source/FLC_surface_edit.png new file mode 100644 index 0000000..33cf28d Binary files /dev/null and b/Work 2/source/FLC_surface_edit.png differ diff --git a/Work 2/source/mkFIS.m b/Work 2/source/mkFIS.m new file mode 100644 index 0000000..1cff5e2 --- /dev/null +++ b/Work 2/source/mkFIS.m @@ -0,0 +1,77 @@ +% +% Local script to create FIS (w/o the GUI crap) +% + + +% FIS control +% R2025 compatibility: +% - newfis->mamfis +% - defuzzMethod='cos' -> AggregationMethod="sum", DefuzzificationMethod="centroid" +fis = mamfis( ... + AndMethod="min", ... + OrMethod="max", ... + ImplicationMethod="min", ... + AggregationMethod="sum", ... + DefuzzificationMethod="centroid" ); + +% Inputs +fis = addInput(fis,[0 1],'Name','dh'); +fis = addMF(fis,'dh','trimf',[0 0 0.5],'Name','S'); +fis = addMF(fis,'dh','trimf',[0 0.5 1],'Name','M'); +fis = addMF(fis,'dh','trimf',[0.5 1 1],'Name','L'); + +fis = addInput(fis,[0 1],'Name','dv'); +fis = addMF(fis,'dv','trimf',[0 0 0.5],'Name','S'); +fis = addMF(fis,'dv','trimf',[0 0.5 1],'Name','M'); +fis = addMF(fis,'dv','trimf',[0.5 1 1],'Name','L'); + +fis = addInput(fis,[-180 180],'Name','theta'); +fis = addMF(fis,'theta','trimf',[-180 -180 0],'Name','N'); +fis = addMF(fis,'theta','trimf',[-180 0 180],'Name','ZE'); +fis = addMF(fis,'theta','trimf',[ 0 180 180],'Name','P'); + +% Output +fis = addOutput(fis,[-130 130],'Name','dtheta'); +fis = addMF(fis,'dtheta','trimf',[-130 -130 0],'Name','N'); +fis = addMF(fis,'dtheta','trimf',[-130 0 130],'Name','ZE'); +fis = addMF(fis,'dtheta','trimf',[ 0 130 130],'Name','P'); + +% Rules + +fis = addRule(fis, "IF theta IS N dh IS S AND dv IS S AND THEN dtheta IS P"); +fis = addRule(fis, "IF theta IS N dh IS S AND dv IS M AND THEN dtheta IS P"); +fis = addRule(fis, "IF theta IS N dh IS S AND dv IS L AND THEN dtheta IS P"); +fis = addRule(fis, "IF theta IS N dh IS M AND dv IS S AND THEN dtheta IS P"); +fis = addRule(fis, "IF theta IS N dh IS M AND dv IS M AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS N dh IS M AND dv IS L AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS N dh IS L AND dv IS S AND THEN dtheta IS P"); +fis = addRule(fis, "IF theta IS N dh IS L AND dv IS M AND THEN dtheta IS P"); +fis = addRule(fis, "IF theta IS N dh IS L AND dv IS L AND THEN dtheta IS P"); + + +fis = addRule(fis, "IF theta IS ZE dh IS S AND dv IS S AND THEN dtheta IS P"); +fis = addRule(fis, "IF theta IS ZE dh IS S AND dv IS M AND THEN dtheta IS P"); +fis = addRule(fis, "IF theta IS ZE dh IS S AND dv IS L AND THEN dtheta IS P"); +fis = addRule(fis, "IF theta IS ZE dh IS M AND dv IS S AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS ZE dh IS M AND dv IS M AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS ZE dh IS M AND dv IS L AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS ZE dh IS L AND dv IS S AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS ZE dh IS L AND dv IS M AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS ZE dh IS L AND dv IS L AND THEN dtheta IS ZE"); + + +fis = addRule(fis, "IF theta IS P dh IS S AND dv IS S AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS P dh IS S AND dv IS M AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS P dh IS S AND dv IS L AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS P dh IS M AND dv IS S AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS P dh IS M AND dv IS M AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS P dh IS M AND dv IS L AND THEN dtheta IS N"); +fis = addRule(fis, "IF theta IS P dh IS L AND dv IS S AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS P dh IS L AND dv IS M AND THEN dtheta IS ZE"); +fis = addRule(fis, "IF theta IS P dh IS L AND dv IS L AND THEN dtheta IS N"); + + +writeFIS(fis,'CarFLC'); + +f1 = figure('Name','FLC surface'); gensurf(fis); grid on; +exportgraphics(f1, sprintf('FLC_surface.png'), 'Resolution', 300); diff --git a/Work 2/source/moveCar.m b/Work 2/source/moveCar.m new file mode 100644 index 0000000..2aada4e --- /dev/null +++ b/Work 2/source/moveCar.m @@ -0,0 +1,15 @@ +function [x_new, y_new, theta_new] = moveCar(x, y, theta, dtheta) +%MOVECAR updates car's position based on previous state +% Detailed explanation goes here + +global Speed_mag; +global Ts; + + +% Stear and then calculate the new position +theta_new = theta + dtheta; + +x_new = x + Speed_mag * Ts * cos(toRadians("degrees", theta_new)); +y_new = y + Speed_mag * Ts * sin(toRadians("degrees", theta_new)); + +end diff --git a/Work 2/source/runSimulation.m b/Work 2/source/runSimulation.m new file mode 100644 index 0000000..ae78d81 --- /dev/null +++ b/Work 2/source/runSimulation.m @@ -0,0 +1,88 @@ +%% Car - Simulation +% +% Assignment 2 in Fuzzy systems +% +% author: +% Christos Choutouridis ΑΕΜ 8997 +% cchoutou@ece.auth.gr +% +clear; clc; close all; + +global Speed_mag; +global Ts; + + +% Configuration +% ---------------------- +Speed_mag = 0.05; +Ts = 1; + +% Givents +% ---------------------- +corners = [5 1 ; 6 2 ; 7 3]; +x_init = 3.8; +y_init = 0.5; +x_final = 10; +y_final = 3.2; +theta_init = [-45 0 45]; + + +% Saturation between min: m and max: M +sat = @(x, m, M) max(m, min(M, x)); + +% Load control +flc = readfis('CarFLC'); + +t = 0:Ts:250; +for i = 1:length(theta_init) + x = x_init; + y = y_init; + theta = theta_init(i); + + X = zeros(size(t)); + Y = zeros(size(t)); + + End=length(t); + for k=1:End + [dh, dv] = wallDistance(corners, x, y); + if isfinite(dh) && ~isfinite(dv) && (dh <=0 || dv <= 0) + End = k-1; + fprintf('Car crashed!! - Stop simulation'); + break; + end + + dtheta = evalfis(flc, [sat(dh, 0, 1) sat(dv, 0, 1) theta]); + [x, y, theta] = moveCar(x, y, theta, dtheta); + X(k) = x; Y(k) = y; + + if x >= x_final + End = k-1; + break; + end + end + + figure(i); clf; hold on; grid on; axis equal; + xlim([2 11]); ylim([-1 4]); + xlabel('x [m]'); ylabel('y [m]'); + title( ... + "Car movement $(\theta_0 =" + theta_init(i)+ "^{\circ})$", ... + 'Interpreter','latex', ... + 'FontSize', 16); + + % Walls + fill([5 6 6 5],[0 0 1 1],[0.5 0.5 0.5],'FaceAlpha',0.4,'EdgeColor','none'); + fill([6 7 7 6],[0 0 2 2],[0.5 0.5 0.5],'FaceAlpha',0.4,'EdgeColor','none'); + fill([7 10 10 7],[0 0 3 3],[0.5 0.5 0.5],'FaceAlpha',0.4,'EdgeColor','none'); + + plot(X(1:End), Y(1:End), '-', 'LineWidth', 1.5); + + hold on; + plot(X(1), Y(1), 'go', 'MarkerFaceColor', 'g'); % begin + plot(X(End), Y(End), 'ro', 'MarkerFaceColor', 'r'); % end + hold off; + + filename = sprintf('CarMovement_theta%d.png', theta_init(i)); + saveas(gcf, filename); +end + + diff --git a/Work 2/source/wallDistance.m b/Work 2/source/wallDistance.m new file mode 100644 index 0000000..6295279 --- /dev/null +++ b/Work 2/source/wallDistance.m @@ -0,0 +1,45 @@ +function [dh, dv] = wallDistance(corners, x, y) +% Calculates the distances from the walls. +% - Negative value means colision +% - Inf value means no wall in this direction +% +% Inputs: +% corners[] : corner matrix (each line is a corner point) +% x: Car's x position +% y: Car's y position +% Outputs: +% dh: Horizontal distance from wall +% dv: Vertical distance from wall + + % Calculate the distances in the x direction + srt_corners = sortrows(corners, 2); + active_corners = -Inf(size(corners)); + + for i=1:length(srt_corners) + if srt_corners(i, 2) >= y + active_corners = srt_corners(i:end, :); + break; + end + end + dx = active_corners(:, 1) - x; % Walls are on the right + dh = min(dx); % Minimum distance in x direction + + % Calculate the distances in the y direction + srt_corners = sortrows(corners, 1, 'descend'); + active_corners = -Inf(size(corners)); + + for i=1:length(srt_corners) + if srt_corners(i, 1) <= x + active_corners = srt_corners(i:end, :); + break; + end + end + dy = y - active_corners(:, 2); % Walls are on the bottom + dv = min(dy); % Minimum distance in y direction + + if ~isfinite(dh) dh = Inf; end + if ~isfinite(dv) dv = Inf; end +end + + +