summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Dybiec <pawel.to.malpa@gmail.com>2018-02-12 09:00:38 +0100
committerPaweł Dybiec <pawel.to.malpa@gmail.com>2018-02-12 09:00:38 +0100
commit29eefafba31abcef3af2f09d82f5cbf3519dcd5d (patch)
treed8f8ca97142fcaf073d41c26c6fd19c0f248bb0e
parentb3fd8401e3b6ba476339c0007cef1620ee4ee14c (diff)
wiecej tekstu, blisko final
-rw-r--r--Chapters/chapter1.tex128
-rw-r--r--Chapters/chapter2.tex41
-rw-r--r--Chapters/chapter3.tex90
-rw-r--r--Chapters/chapter4.tex19
-rw-r--r--iithesis.pdfbin183608 -> 469879 bytes
-rwxr-xr-xiithesis.tex13
-rw-r--r--img/real_data_ang.pngbin42123 -> 23251 bytes
-rw-r--r--img/real_img.pngbin0 -> 80913 bytes
-rw-r--r--img/real_img_act.pngbin0 -> 55081 bytes
-rw-r--r--img/sim_img.pngbin0 -> 29660 bytes
-rw-r--r--img/sim_img_act.pngbin0 -> 55510 bytes
11 files changed, 225 insertions, 66 deletions
diff --git a/Chapters/chapter1.tex b/Chapters/chapter1.tex
index cad65a3..d6d302d 100644
--- a/Chapters/chapter1.tex
+++ b/Chapters/chapter1.tex
@@ -5,24 +5,102 @@ Z jego powodu(trzeba zmienic to wyrazenie), powstało wiele rozwiązań dla zada
Żaden spośród łazików biorących udział w University Rover Challenge nie
używa sieci neuronowych bezpośrednio do nawigacji , ale prawie wszystkie używają
-ROS ( Robot Operating System ) jako podstawy całego oprogramowania. Z tego powodu
+ROS (Robot Operating System) jako podstawy całego oprogramowania. Z tego powodu
w tym rozdziale poruszone będą:
\begin{itemize}
+ \item Łazik Aleph 1
\item Podstawy sieci neuronowych.
\item Architektura ROS
- \item Autonomia Aleph 1
\end{itemize}
+\section {Łazik}
+Łazik Aleph 1 powstał z inicjatywy koła naukowego Continuum\footnote{ Strona koła naukowego Continuum:
+\href{http://continuum.uni.wroc.pl/}{http://continuum.uni.wroc.pl/}}
+w roku 2014. Od tego czasu został zaprezentowany na konkursach takich jak
+European Rover Challenge (ERC) oraz University Rover Challenge (URC). Przez ostatnie
+dwa lata łazik był doceniany na konkursie URC (w roku 2016 zajął 3 miejsce, a w roku
+2017 -- 2 miejsce).
+
+Podczas konkursu URC pojazdy były ocenianie w czterech kategoriach\footnote{
+Regulamin konkursu URC: \href{http://urc.marssociety.org/home/requirements-guidelines}
+{http://urc.marssociety.org/home/requirements-guidelines}}:
+\begin{itemize}
+ \item Science Cache Task -- pobieranie i badanie próbek w terenie
+ \item Extreme Retrieval and Delivery Task -- transport pakunku w różnych warunkach
+ terenowych
+ \item Equipment Servicing Task -- zdolności manualne (umiejętność podnoszenia,
+ przenoszenia obiektów, obsługa przycisków, przełączników i innych narzędzi)
+ \item Autonomous Traversal Task -- umiejętność poruszania się pomiędzy wyznaczonymi
+ punktami
+\end{itemize}
+
\section{Podstawy sieci neuronowych}
+Głebokie sieci neuronowe (deep neural networks) to popularny model w uczeniu maszynowym.
+Celem sieci jest przybliżenie funkcji $f^*$, przyporządkowującej argumentom $x$ wartości
+$y$, funkcją $f(x,\theta)=y$ oraz znalezienie parametru $\theta$, który da najlepsze
+przybliżenie.
\subsection{Jak działają}
+Sieci neuronowe są zazwyczaj złożone z wielu różnych funkcji, nazywanych warstwami. Przykładowo
+$f(x)=f^{(3)}(f^{(2)}(f^{(1)}(x)))$, wtedy $f^{(3)}$ jest wartwą wyjściową, której wyniki
+powinny odpowiadać funkcji $f^*$. Wyniki dla pozostałych warstw nie są znane, z tego
+powodu nazywa się je ukrytymi warstwami.
\subsection{Jak trenować}
-\subsection{Warstwy typowe dla CNN}
-\subsection{Dlaczego działają}
+W wyniku trenowania chcemy znaleźć takie $\theta$, żeby $f^*(x)\approx f(x,\theta)$.
+W tym celu należy zdefiniować funkcję kosztu $L(\theta)$ tzn. odległości modelu
+od celu, zależną od $\theta $,
+przykładowo dla regresji średni błąd kwadratowy dla danych uczących. Dla takiej
+funkcji chcielibyśmy teraz znaleźć minimum. Minimum globalne może być trudne
+do znalezienia, ale minima lokalne zazwyczaj są wystarczająco dobre.
+
+Gdyby $L$ byłoby funkcją jednej zmiennej, wystarczyłoby zacząć w losowym miejscu i
+wielokrotnie wykonać następujący
+krok $x=x-\epsilon L'(x)$, aby dotrzeć do minimum lokalnego. Dla funkcji
+wielu zmiennych podobny algorytm działa, ale pochodną należy zastąpić gradientem
+$x=x-\epsilon \nabla _x L(x)$.
+\subsection{Popularne warstwy}
+Warstwa liniowa (linear lub dense) jest najbardziej podstawową warstwą. Każdy
+element wyjściowy ($m$ wartości) jest kombinacją wszystkich wejść ($n$ wartości)
+danej warstwy (powiększoną o stałą). Zatem taka warstwa jest parametryzowana
+macierzą rozmiaru $n \cdot m$ oraz wektorem rozmiaru $m$.
+
+Dwie takie sąsiednie warstwy liniowe można by zredukować do jednej, ponieważ
+$W_2 \cdot (W_1 \cdot x + b_1) +b_2 = W \cdot x + b$, gdy $W=W_2 \cdot W_1$ oraz
+$b = W_2 \cdot b_1 +b_2$. Zatem dowolnie głęboką sieć złożoną z takich warstw
+możnaby zredukować do 1 takiej warstwy, ale po każdej funkcji liniowej aplikuje
+się funkcję nieliniową np. tanh lub relu ($\max(0,x)$). Dzięki temu sieci neuronowe
+są w stanie pokryć znacznie większą przestrzeń funkcji niż tylko liniowe.
+
+Inną warstwą, już specjalizowaną w przetwarzaniu danych położonych na pewnej kracie,
+jest warstwa konwolucyjna. Przykładowym wejściem dla takiej warstwy może być
+dwuwymiarowa siatka pikseli. Natomiast wyjściem jest obraz o zbliżonej (lub tej samej)
+rozdzielczości, którego wartość jest kombinancją liniową spójnego bloku piksli z
+wejścia. Ważną cechą takiej warstwy jest fakt, że wszystkie wyjścia korzystają
+z tych samych parametrów, co powoduje że znajdują te same wzorce położone w
+innych miejscach.
+
+Kolejnym typem warstw specjalizowanym w przetwarzaniu obrazów jest pooling.
+Dzieli ona wejście na spójne rozłączne bloki, na każdym z nich osobno aplikuje
+funkcję np. $max$ lub $avg$. Taka operacja powoduje niewrażliwość na małe
+przemieszczenia wejść. Dodatkowo zmniejsza to rozmiar wejścia w kolejnych warstwach
+co zmniejsza liczbę parametrów.
+\subsection{Uwagi}
+Konwolucyjne sieci neuronowe bardzo dobrze radzą soie z widzeniem maszynowym, są w stanie
+klasyfikować bezproblemowo obrazki\footnote{\href
+{https://www.cs.toronto.edu/\~kriz/imagenet\_classification\_with\_deep\_convolutional.pdf}
+{https://www.cs.toronto.edu/\~kriz/imagenet\_classification\_with\_deep\_convolutional.pdf}}.
+Ale w przypadku patrzenia na tylko jedną kratkę nie są wstanie wyciągnąć wniosków.
+Co w przypadku nawigacji oznacza, że proces sterowania jest tylko ciągiem
+spontanicznych decyzji bez planowania trasy. Dodatkową konsekwencją takiej architektury
+jest ukryte założenie, że dla każdego obrazu z kamery jest tylko jedna poprawna
+odpowiedź.
\section{ROS}
-Ros to otwarty system operacyjny przeznaczony dla robotów.
-Dostarcza abstrakcję nad sprzętem oraz środki komunikacji między procesami.
+ROS to rozbudowany framework przeznaczony do programowania robotów.
+Składa się na niego wiele bibliotek oraz narzędzi mających na celu zbudowanie
+klastra komputerów tworzących spójny system.
+Dostarcza on abstrakcję nad sprzętem, środki komunikacji między procesami oraz
+oraz inne funkcjonalności dostarczane przez typowy system operacyjny.
Ze względu na modułową budowę oraz architekturę peer-to-peer procesy mogą
bezproblemowo działać na różnych komputerach.
\subsection{Node}
@@ -38,22 +116,28 @@ Tematy(topic) pozwalają bezproblemowo zapewnić komunikację międzyprocesową
w ROSie. Każdy node może zadelkarować chęć nadawania bądź nasłuchiwania na
danym temacie. Przykładowo moduł jazdy autonomicznej może zasubskrybować
obraz z kamery Kinect, a publikować na temacie reprezentującym kierunek ruchu.
-\subsection{Rosbag}
-Rosbagi służą do zapisywania wybranych topiców wraz ze znacznikami czasu.
-Niestety ten format wspiera tylko dostęp sekwencyjny przy odtwarzaniu, co wystarczy
-do symulowania łazika, ale nie zawsze to wystarczyło. Aby temu zaradzić dane były
-konwertowane do prostszego formatu.
-%\subsection{Gotowe moduły}
+Tematy są otypowane, co gwarantuje że wszystkie wiadomości wysłane na tym
+samym temacie mają taką samą strukturę.
+\subsection{Gotowe moduły}
+ROS dostarcza wiele gotowych modułów pozwalających szybko rozpocząć projekt.
+Jednym z nich jest Odom, który zbiera informacje o położeniu i prędkości
+z wielu źródeł danych i łączy je w jedno (o większej pewności). Przykładowo
+dane może zbierać z czujnika gps, prędkości obrotowej kół oraz akcelerometru.
+
+Inny moduł potrafi tworzyć mapy na podstawie obrazu z kamery oraz mapy głębokości.
+Wynik tej rekonstrukcji można obejrzeć z pomocą innych usług służących do
+wizualizacji różnych typów danych takich jak obraz, wartości zmieniające się
+w czasie, chmury punktów lub mapa terenu.
%chyba nie aż tak ważne
%tf,kamery,konwersje obrazków/strumieni
-\section{Autonomia Aleph 1}
-Co zostało zrobione na przedmiocie:
-\begin{itemize}
- \item Sprzęt (mnóstwo)
- \item Mapa 3d (RTAB\_MAP)
- \item Rozpoznawanie klawiatur/piłek tenisowych
- \item Symulator
- \item kilka sieci obraz->kierownica
- \item wrappery/konwertery różnych protokołów/formatów
-\end{itemize}
+% \section{Autonomia Aleph 1}
+%Co zostało zrobione na przedmiocie:
+%\begin{itemize}
+% \item Sprzęt (mnóstwo)
+% \item Mapa 3d (RTAB\_MAP)
+% \item Rozpoznawanie klawiatur/piłek tenisowych
+% \item Symulator
+% \item kilka sieci obraz->kierownica
+% \item wrappery/konwertery różnych protokołów/formatów
+%\end{itemize}
diff --git a/Chapters/chapter2.tex b/Chapters/chapter2.tex
index b53b09b..f048612 100644
--- a/Chapters/chapter2.tex
+++ b/Chapters/chapter2.tex
@@ -1,4 +1,4 @@
-\chapter{Sieć pod symulator}
+\chapter{Trenowanie sieci i zbieranie danych}
W celu autonomicznej jazdy wytrenowałem konwolucyjną sieć neuronową (CNN)
przetwarzającą obraz z kamery bezpośrednio w porządaną prędkość liniową
oraz obrotową. Takie podejście pozwala szybko zbierać dane uczące, wystarczy
@@ -17,26 +17,41 @@ tylko nagrać obraz z kamery oraz prędkość nadaną przez kierowcę.
\label{model}
\caption{Architektura sieci}
\end{figure}
+
Wersja sterująca w symulatorze powstała, żeby odrzucić modele, które nie radzą
sobie w tak prostych warunkach. Dodatkowo zbieranie danych oraz testowanie
modelu jest łatwiejsze, ponieważ nie wymaga przygotowywania sprzętu, oraz
opuszczenie toru przez model jest nieszkodliwe w porównaniu do opuszczenia
drogi przez fizycznego łazika.
-\section{Dlaczego taka (a nie mniejsza)}
-W sieci pięciokrotnie pojawia się sekwencja warstwa konwolucyjna -> dropout
-całych warstw ->max pooling.
-Celem poolingu jest zmniejszenie liczby parametrów oraz zapobieganie
-przetrenowaniu. Max pooling dzieli obraz na bloki ustalonego rozmiaru i
-dla każdego z nich wyznacza maksimum, w ten sposób rozmiar 'feature maps'
-wielokrotnie się zmniejsza.
+Architektura sieci pochodzi z rozwiązania chauffeur w konkursie udacity self driving car\footnote
+{ Repozytorium dostępne pod\href{https://github.com/udacity/self-driving-car/tree/master/steering-models/community-models}
+{https://github.com/udacity/self-driving-car/tree/master/steering-models/community-models}},
+ale została zaadaptowana do interfejsu symulatora oraz łazika (oprócz obrotu
+potrafi też zadać prędkość). Konwersja z rosbaga (format nagrań ROSa) do
+naszego formatu oraz sam symulator zostały wykonane przez innych członków projektu.
+
-Dlaczego tylko 1 dense
+\section{Trening na symulatorze}
+Nagrania do nauki na symulatorze zostały wykonane przeze mnie i dwóch innych
+uczestników projektu. Łączna długość nagrań wynosi około 50 minut, z czego 5
+minut zostało przeznaczone na zbiór walidacyjny, a reszta była zbiorem uczącym.
-\section{Dane}
-Jak długie przejazdy, i ile ich: 2 po 20 minut
+Obrazy pochodzą z 3 kamer, jedna skierowana na wprost, a pozostałe były obrócone
+o 20 stopni względem środkowej. Podczas uczenia wykorzystywany był obraz ze wszystkich
+trzech kamer. Dla kamery środkowej porządanym wynikiem były nagrane dane z sterowania,
+natomiast dla kamery lewej wynik był nieznacznie zaburzony w prawo, i analogicznie
+dla trzeciej kamery.
+Dodatkowo obraz z kamery środkowej był dodany w postaci symetrycznego odbicia
+ze zmienionym kierunkiem skrętu.
-Co gdyby zmniejszyć rozdzielczość ewaluowanych obrazkow do 16x8: jest ok
+\section{Trening z nagrań łazika}
+Do treningu zostało wykorzystane około 150GB nagrań z łazika, zawierających
+obraz z kamery oraz informacje o sterowaniu, jest to kilkanaście objazdów
+po podziemnym garażu. Na większości ujęć widać kratkę zazwyczaj zgodną z kierunkiem
+jazdy, ale zakręcjącą pod kątem prostym. Około 6GB danych zostało wykorzystanych jako
+zbiór walidacyjny.
-Jak wzbogacane: obrazy z 3 kamer + flip na środkowej
+Nagrania pochodzą z jednej fizycznej kamery. Dla każdego ujęcia zostało
+dodane jego odbicie lustrzane z przeciwnym kątem skrętu.
diff --git a/Chapters/chapter3.tex b/Chapters/chapter3.tex
index 000eec0..e18e293 100644
--- a/Chapters/chapter3.tex
+++ b/Chapters/chapter3.tex
@@ -1,22 +1,86 @@
-\chapter{Sieć pod Łazik}
-TODO: obrazki aktywacji dla przeuczonej sieci
+\chapter{Wyniki sieci}
+Wytrenowana sieć potrafi przejechać zarówno cały tor na symulatorze jak i
+podziemny garaż instytutu. Na dodatek sieć trenowana pod symulator uczyła się,
+tylko jeździć przeciwnie do ruchu wskazówek zegara, a po ustawieniu modelu w przeciwnym
+kierunku potrafi przejechać cały tor bezproblemowo.
-Po co wgl był ten symulator? - jakby siec nie działała na symulatorze
-to raczej nie zadziała na prawdziwych danych
+\section{Na co zwraca uwagę}
+Aktywność sieci dla obrazków została wygenerowana za pomocą metody
+Integrated Gradients\footnote{\href{https://arxiv.org/abs/1703.01365}{https://arxiv.org/abs/1703.01365}}.
-\section{Co trzeba było dodać/zmienić}
-Obsługa rosa i rosbagów
+Co było oczywiste w przypadku symulatora,sieć zwraca głównie uwagę na miejsca,
+gdzie pojawiają się granice drogi\ref{sim_act}. Co ciekawe reaguje też na ścianę
+tworzącą horyzont, ponieważ zmienia wygląd w zależności od odległości i może
+pomóc w orientacji (na tej trasie).
+\begin{figure}
+ \centering
+ \fbox{
+ \scalebox{0.5}{\includegraphics{img/sim_img.png}}
+ }
+ \label{sim_img}
+ \caption{Obraz z symulatora}
+\end{figure}
+\begin{figure}
+ \centering
+ \fbox{
+ \scalebox{0.5}{\includegraphics{img/sim_img_act.png}}
+ }
+ \label{sim_act}
+ \caption{Na co sieć patrzy, symulator}
+\end{figure}
+\begin{figure}
+ \centering
+ \fbox{
+ \scalebox{0.5}{\includegraphics{img/real_img.png}}
+ }
+ \label{real_img}
+ \caption{Obraz z nagrania}
+\end{figure}
+\begin{figure}
+ \centering
+ \fbox{
+ \scalebox{0.5}{\includegraphics{img/real_img_act.png}}
+ }
+ \label{real_act}
+ \caption{Na co sieć patrzy, nagranie}
+\end{figure}
-\section{Problemy}
-Przetestowanie jest bardziej ryzykowne
+Z kolei dla łazika intensywność w najbardziej aktywnym miejscu jest dużo mniejsza,
+co oznacza że nie sugeruje się tylko jednym miejscem. Ale mimo tego najbardziej
+zwraca uwagę na kratkę na podłodze, która mogła by wystarczyć do nawigacji.
-Pominięcie sporej ilości nagrań i mierzenie MSE na nich
+\section{W porównaniu do nagrania}
+Na wykresie \ref{plot_ang} widać że sieć (pomarańczowy kolor), mniej gwałtownie
+zmienia szybkość obrotu niż kierowca (kolor niebieski). Ale w podobnych momentach
+zauważa, że należy skręcić.
+\begin{figure}
+ \centering
+ \fbox{
+ \scalebox{0.5}{\includegraphics{img/real_data_ang.png}}
+ }
+ \label{plot_ang}
+ \caption{Prędkość obrotowa: sieć vs kierowca}
+\end{figure}
-\section{Dane}
-Jak długie przejazdy, i ile ich: 180GB z jednego dnia, łącznie 240GB
+\section{Wpływ architektury}
+W przypadku sieci pod symulator, usunięcie niektórych warstw konwolucyjnych
+pozwalało modelowi utrzymać się na torze, a taka sama zredukowana architektura
+nie radziła sobie dobrze w przypadku nagrań z prawdziwego łazika. Natomiast
+usunięcie nieliniowości z warstw konwolucyjnych tak okaleczyła zdolności sieci,
+że nie potrafiła się utrzymać na wirtualnym torze.
-Mamy bufor głębokości dodatkowo
+Z kolei usunięcie dropoutu, bardzo szybko powodowało overfitting i radziła sobie
+dobrze tylko na danych uczących. Z kolei dodanie warstw liniowych na końcu nie
+poprawiało, ani nie pogorszało zbytnio wydajności sieci, przynajmniej dla
+nagrań z symulatora. Widocznie większość interesujących cech już jest znaleziona
+w ramach konwolucji, i dla tak prostych danych nie pomaga zwiększenie modelu.
-Skupialiśmy się na tym żeby widział kratkę (kąty proste)
+Co ciekawe w przypadku wytrenowanego już modelu do symulatora zredukowanie
+rozdzielczości obrazów dziesięciokrotnie w każdym wymiarze(z rozdzielczości
+320x160 do 32x16),
+i zwykłe przeskalowanie w górę przed zewaluowaniem wystarczy żeby urzymać się
+na torze.
+Na dodatek sieć uczona na obrazie kolorowym bezproblemowo działa, gdy
+zredukuje się obraz do skali szarości a następnie powtórzy kanał trzykrotnie.
diff --git a/Chapters/chapter4.tex b/Chapters/chapter4.tex
index 02adb80..b34809a 100644
--- a/Chapters/chapter4.tex
+++ b/Chapters/chapter4.tex
@@ -1,9 +1,18 @@
\chapter{Co dalej}
-RNN - sam wyciągnie kontekst
+Najprostszym następnym krokiem jest zwiększenie danych o dodatkowy wymiar, i nauczenie takiej
+sieci decyzji na podstawie $k$ (niekoniecznie) ostatnich zdjęć. Innym prostym rozwiązaniem,
+które można z tym połączyć jest zmiana perspektywy kamery na zdjęcie z góry.
-Na wersji sim-only - funkcja kosztu w zależności od odległości od trasy, może nagradzać szybkie przejazdy bo inaczej będzie stać w miejscu
-Da się podciągnąć dla prawdziwej ale trzeba by jakoś użyć odo.
+Bardziej ambitnym pomysłem jest wytrenowanie rekurencyjnej sieci neuronowej (RNN),
+gdyby ją dobrze nauczyć sama wyciągnie kontekst. Ale problemem przy jej trenowaniu
+będzie fakt, że prostą strategią dla takiej sieci jest powtarzanie ostatniego wypisanego
+wyniku, a to dlatego że prędkość jest ciągła.
+
+Kolejnym rozwiązaniem jest reinforced learning, sieć karało by się za
+każdą interwencję lub wyjechanie poza trasę. Niestety problemem tutaj jest
+fakt, że jak błąd prawdziwego pojazdu może być kosztowny lub niebezpieczny.
+
+Oczywiście pozostają też rozwiązania nie używające sieci neuronowych, można
+przykładowo stworzyć program pilnujący aby łazik nie wjechał w przeszkodę.
-Reinforced learning - kara za każdą interwencję (może nie 0-1 tylko proporcjonalna od
-róznicy outputów)
diff --git a/iithesis.pdf b/iithesis.pdf
index 7efbe21..a098392 100644
--- a/iithesis.pdf
+++ b/iithesis.pdf
Binary files differ
diff --git a/iithesis.tex b/iithesis.tex
index 93b977c..ac52529 100755
--- a/iithesis.tex
+++ b/iithesis.tex
@@ -46,7 +46,6 @@
\input{abstracts}
\begin{document}
-TODO: Zmienić kierunek na isim
\input{Chapters/chapter1}
\input{Chapters/chapter2}
\input{Chapters/chapter3}
@@ -57,17 +56,5 @@ TODO: Zmienić kierunek na isim
\end{thebibliography}
\renewcommand\appendixtocname{Dodatki}
\bookmarksetupnext{level=part}
-\begin{appendices}
-\addtocontents{toc}{\protect\setcounter{tocdepth}{1}}
-\makeatletter
-\addtocontents{toc}{
- \begingroup
- \let\protect\l@chapter\protect\l@section
- \let\protect\l@section\protect\l@subsection
-}
-\makeatother
- \input{Appendices/appendixA}
-\addtocontents{toc}{\endgroup}
-\end{appendices}
\end{document}
diff --git a/img/real_data_ang.png b/img/real_data_ang.png
index 8094f49..40b716b 100644
--- a/img/real_data_ang.png
+++ b/img/real_data_ang.png
Binary files differ
diff --git a/img/real_img.png b/img/real_img.png
new file mode 100644
index 0000000..f2d0b5c
--- /dev/null
+++ b/img/real_img.png
Binary files differ
diff --git a/img/real_img_act.png b/img/real_img_act.png
new file mode 100644
index 0000000..e66e751
--- /dev/null
+++ b/img/real_img_act.png
Binary files differ
diff --git a/img/sim_img.png b/img/sim_img.png
new file mode 100644
index 0000000..c671aa7
--- /dev/null
+++ b/img/sim_img.png
Binary files differ
diff --git a/img/sim_img_act.png b/img/sim_img_act.png
new file mode 100644
index 0000000..a11c04a
--- /dev/null
+++ b/img/sim_img_act.png
Binary files differ