diff --git a/lab04/README.md b/lab04/README.md
index 6c5f90e1768114bcf48bf0e910205145d76b545c..7f5a788eaed3fc0dd267a1f703ff3eae98c21061 100644
--- a/lab04/README.md
+++ b/lab04/README.md
@@ -1,75 +1,149 @@
 # Przygotowanie przestrzeni roboczej
 Połącz się ze zdalnym środowiskiem i ściągnij swoje repozytorium do przestrzeni roboczej catkin_ws.
-
-
+ 
+ 
 # Transformacje pomiędzy układami współrzędnych
-Przed przystapieniem do omawiania nawigacji ważnym jest aby rozumieć jak wiele układów współrzędnych znajduje się w platformie robotycznej, jak są one ze sobą połączone oraz jak określać położenie i orientacje względem poszczególnych układów współrzędnych. 
-
+Przed przystąpieniem do omawiania nawigacji ważnym jest aby rozumieć jak wiele układów współrzędnych znajduje się w platformie robotycznej, jak są one ze sobą połączone oraz jak określać położenie i orientację względem poszczególnych układów współrzędnych. 
+ 
 Działanie zależności pomiędzy układami współrzędnych zostanie zwizualizowane na przykładzie manipulatora o 5 stopniach swobody. 
-
+ 
 ![model_katana](img/model_katana.png "model_katana")
-
+ 
 W systemie ROS możemy wizualizować roboty i elementy środowiska przy pomocy opisu URDF. Na niniejszym laboratorium jednak nie zostanie on wyjaśniony. Jeśli chcesz dowiedzieć jak tworzy się pliki URDF i jak stworzyć model własnego robota, to tu znajdziesz więcej informacji [link](http://wiki.ros.org/urdf/Tutorials) (tutorial opisuje jak stworzyć prosty model robota R2D2).
-
+ 
 W skrócie pliki URDF pozwalają opisać jak złożony jest robot. Z jakich złożony jest elementów i jak są one połączone ze sobą. 
-
+ 
 Aby uruchomić naszą wizualizację potrzebujemy pliku launch.
-
+ 
 ```xml
 <launch>
   <param name="robot_description" command="$(find xacro)/xacro.py '$(find katana_description)/urdf/katana_300_6m180.urdf.xacro'" />
     <node pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" name="joint_state_publisher">
     </node>
-
+ 
     <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher">
         <param name="ignore_timestamp" value="false"/>
     </node>
-
+ 
     <node pkg="tf" type="static_transform_publisher" name="katana_base_link_to_box" args="0 0.5 0 0 0 0 /katana_base_link /box 100"/>
 </launch>
 ```
 Został on już stworzony w pakiecie "laboratorium_pliki_dodatkowe". 
-
+ 
 Po pierwsze musimy załadować opis naszego robota jako parametr pod nazwą **robot_description**. 
-
-Następnie uruchamiamy trzy node'y. Pierwszy odpowaiada za publikowanie stanu poszczególnych przegubów robota. Po uruchomieniu zobaczysz okno z interfejsem, który pozwoli na zmianę pozycji poszczególnych przegubów robota. Jeśli posiadalibyśmy prawdziwego robota, którego chcielibyśmy wizualizować, wtedy jego sterownik publikowałby aktualne stany poszczególnych przegubów.  
-
+ 
+Następnie uruchamiamy trzy node'y. Pierwszy odpowiada za publikowanie stanu poszczególnych przegubów robota. Po uruchomieniu zobaczysz okno z interfejsem, który pozwoli na zmianę pozycji poszczególnych przegubów robota. Jeśli posiadalibyśmy prawdziwego robota, którego chcielibyśmy wizualizować, wtedy jego sterownik publikowałby aktualne stany poszczególnych przegubów.  
+ 
 Kolejny node na podstawie pliku urdf oraz danych publikowanych przez **joint_state_publisher** uaktualnia pozycje wizualizowanych elementĂłw robota.
-
+ 
 Ostatni node **static_transform_publisher** publikuje stałe przekształcenie (odsunięcie o 0.5 m w osi y) pomiędzy układem współrzędnych **katana_base_link**, a **box**. Ma on symulować położenie przykładowego elementu i posłuży do lepszego wyjaśnienia omawianego zagadnienia.  
-
+ 
 Uruchom plik launch **wizualizacja_urdf** z paketu **laboratorium_pliki_dodatkowe**. Następnie uruchom program RVIZ i dodaj wizualizacje modelu robota, tf oraz zmień stały układ współrzędnych na **katana_base_link**.
-
+ 
 @@@@@@
-
-
+ 
+ 
 **Zadanie 1:** Przy pomocy **joint_state_publisher** obróć poszczególne przeguby robota i zobacz jak zmienia się wizualizacja. Zmień stały układ współrzędnych (Fixed frame) na wybrany układ zaczynający się od nazwy **katana_motor**. Sprawdź jak teraz zmienia się wizualizacja przy ruchach przegubów. 
-
-
+ 
+ 
 ![model_tf](img/model_tf.png "model_tf")
-
-Jak widać robot złożony jest z wielu układów współrzędnych połączonych ze sobą. Każdy kolejny układ współrzędnych jest zaczepiony w poprzednim i względem niego jest ukreślana jego pozycja. Taki sposób organizacji wszystkich układów współrzędnych pozwala nam w łatwy sposób wyliczyć, gdzie np. znajduje się końcówka robota względem podstawy lub dowolnego innego obiektu np. pudełka o układnie współrzędnych **box**. Wszystkie połączenia pomiędzy układami współrzędnych są zorganizowane w postaci struktury drzewa. Aktualną strukturę możemy zobaczyć przy pomocy narzędzia rqt i TF Tree.
-
+ 
+Jak widać robot złożony jest z wielu układów współrzędnych połączonych ze sobą. Każdy kolejny układ współrzędnych jest zaczepiony w poprzednim i względem niego jest określana jego pozycja. Taki sposób organizacji wszystkich układów współrzędnych pozwala nam w łatwy sposób wyliczyć, gdzie np. znajduje się końcówka robota względem podstawy lub dowolnego innego obiektu np. pudełka o układzie współrzędnych **box**. Wszystkie połączenia pomiędzy układami współrzędnych są zorganizowane w postaci struktury drzewa. Aktualną strukturę możemy zobaczyć przy pomocy narzędzia rqt i TF Tree.
+ 
 **Zadanie 2:** Uruchom program rqt przy pomocy komendy ``` rqt ``` w terminalu. Następnie włącz wizualizacje TF Tree (Plugins -> Visualization -> TF Tree).
-
-Po uruchomieniu TF Tree możesz zobaczyć jak cała struktura jest zorgranizowana. Dodatkowo, dzięki temu narzędziu możemy sprawdzić czy na pewno wszystko jest ze sobą połączone. Jeśli któryś z elementów nie będzie połączony z resztą to dane z takiego elementu nie mogą być odniesione do innych np. jeśli nie wprowadzimy jak zamontowany jest lidar na robocie to będziemy wiedzieć jak dalego znajduje się przeszkoda od lidaru, ale nie będziemy wiedzieć jak blisko znajduje się od np. przedniego zderzaka robota. 
-
+ 
+Po uruchomieniu TF Tree możesz zobaczyć jak cała struktura jest zorganizowana. Dodatkowo, dzięki temu narzędziu możemy sprawdzić czy na pewno wszystko jest ze sobą połączone. Jeśli któryś z elementów nie będzie połączony z resztą to dane z takiego elementu nie mogą być odniesione do innych np. jeśli nie wprowadzimy jak zamontowany jest lidar na robocie to będziemy wiedzieć jak daleko znajduje się przeszkoda od lidaru, ale nie będziemy wiedzieć jak blisko znajduje się od np. przedniego zderzaka robota. 
+ 
 ![tf_tree](img/tf_tree.png "tf_tree")
-
-W dowolnej chwili możemy sprawdzić aktualne przesunięcie (transformacje) pomiędzy dwoma dowolnymi układami współrzędnych. Możomy to zrobić przy pomocy komendy:
+ 
+W dowolnej chwili możemy sprawdzić aktualne przesunięcie (transformacje) pomiędzy dwoma dowolnymi układami współrzędnych. Możemy to zrobić przy pomocy komendy:
 ```bash
 rosrun tf tf_echo <nazwa układu współrzędnych> <nazwa układu współrzędnych>
 ```
-
+ 
 @@@@@@@@@@
-
+ 
 ![tf_echo](img/tf_echo.png "tf_echo")
-
-Program tf co sekundę pokazuje nam odległość i zmianę orinetacji pomiędzy dwoma układami współrzędnych. Przesunięcie określone jest kolejno w osiach X,Y,Z. Natomiast zmiana orientacji podana jest w trzech różnych jednostkach.
-
-
+ 
+Program tf co sekundę pokazuje nam odległość i zmianę orientacji pomiędzy dwoma układami współrzędnych. Przesunięcie określone jest kolejno w osiach X,Y,Z. Natomiast zmiana orientacji podana jest w trzech różnych jednostkach.
+ 
+ 
 **Zadanie 3:** Uruchom tf_echo pomiędzy układami współrzędnych **katana_gripper_tool_frame** i **box**, a następnie ustaw końcówkę robota na tyle blisko układu współrzędnych **box**, aby odległość w żadnej osi nie przekraczała 0.2 m.
-
-
  
-
+-----------
+ 
+Przechodząc do pojazdów, standardowa struktura układów współrzędnych i ich nazewnictwo przedstawia się następująco:
+ 
+![mobile_robot_standard_tf](img/mobile_robot_standard_tf.png "mobile_robot_standard_tf")
+ 
+Standardowo wszystkie elementy umieszczone na robocie są ostatecznie połączone z układem **base_link**. Następnie układ **base_link** jest połączony z układem **base_footprint**, który jest rzutem na płaszczyznę układu **base_stabilized**, ale zwykle pomija się układ **base_stabilized** i zwykle się go nie tworzy.
+ 
+Kolejne połączenie jest tworzone pomiędzy **base_footprint**, a **odom**. Tym razem jest to już połączenie odpowiedzialne za lokalizację. Tak jak poprzednie układy współrzędnych były raczej statyczne względem siebie, tak **base_footprint** i **odom** już nie. Transformacja ta obrazuje przesunięcie robota względem punktu początkowego (początkiem układu współrzędnych odom) i zwykle wykorzystywane są do tego metody przyrostowe. Co ważne w systemie ROS przyjęte jest, że w tej transformacji nie mogą występować przeskoki w pozycji (pozycja musi zmieniać się w sposób ciągły). 
+ 
+Ostatnim zaprezentowanym połączeniem jest pomiędzy **odom** i **map**. To połączenie pozwala pokazać, gdzie robot znajduje się na mapie. Tu mogą już występować przeskoki w pozycji tzn. transformacja pomiędzy **map** i **odom** jest tak dobierana aby końcowa pozycja robota względem mapy była zgodna z rzeczywistością (dokonuje tego zwykle algorytm SLAM). 
+ 
+Czasami stosuje się jeszcze układ współrzędnych **earth**, która jest już ostatecznym układem współrzędnych i zwykle odnosi się do koordynatów GPS. Ten układ współrzędnych pozwala nam na odniesienie względem siebie kilku map i przypisać im rzeczywistą pozycję na "Świecie"
+ 
+------
+ 
+Jeśli znamy już całą konwencję tworzenia i nazewnictwa układów współrzędnych, możemy przejść do nawigacji zliczeniowej.
+Zwykle pozycja w nawigacji zliczeniowej robotów mobilnych jest określana na podstawie enkoderów umieszczonych na kołach. Wiedząc jak obróciły się koła możemy obliczyć pozycję robota na podstawie poniższych wzorów:
+ 
+![odom_wzor](img/odom_wzor.png "odom_wzor")
+ 
+ 
+W systemie ROS obliczaniem odometri zakmuje się program obsługujący fizyczne enkodery, natomiast już w systemie posługujemy się wadomością Odometry ([dokumnetacja](http://docs.ros.org/en/melodic/api/nav_msgs/html/msg/Odometry.html)). Zawiera ona zarówno aktualną pozycję jak i prędkość. Dodatkowo oba parametry są opatrzone macierzą kowariancji, która reprezentuje niepewność każdego z pomiarów. 
+ 
+Uruchom symulację robota turtlebot:
+```bash
+export TURTLEBOT3_MODEL=waffle
+roslaunch turtlebot3_gazebo turtlebot3_world.launch
+```
+ 
+Uruchom RVIZ
+```bash
+export TURTLEBOT3_MODEL=waffle
+roslaunch turtlebot3_gazebo turtlebot3_gazebo_rviz.launch
+```
+ 
+Uruchom program sterujący robotem
+```bash
+export TURTLEBOT3_MODEL=waffle
+roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch
+```
+ 
+**Zadanie 4:** Uruchom program rqt i zobacz jak wyglądają zależności pomiędzy układami współrzędnych w tym robocie.
+ 
+Przejdź do programu RVIZ, zmień ustawienie widoku na **ThirdPersonFollower**, zbliż kamerę do robota. Włącz wizualizację TF i włącz widoczność tylko następujących układów **base_link**, **base_scan**, **base_link**, **wheel_right_link**, **wheel_left_link**, **odom**. Zmniejsz rozmiar zwizualizowanych układów współrzędnych "Marker scale", tak aby nie przysłaniały modelu robota. 
+ 
+@@@@@@@@@
+ 
+**Zadanie 5:** Podejrzyj co dzieje się na topicu **/odom**. Obserwując robota jak i topic **/odom** przejedź około 1 m do przodu symulowanym robotem. 
+ 
+**Zadanie 6:** Zmień stały układ współrzędnych "Fixed Frame" z **odom** na **base_scan**. Przejedź ponownie robotem jakąś odległość w dowolnym kierunku. Jak teraz prezentowane są dane w programie RVIZ?
+ 
+@@@@ TU jeszcze pokazać jak układy przeskakują @@@@@
+ 
+------
+![orientation](img/orientation.png "orientation")
+ 
+Oprócz pozycji często potrzebujemy również orientacji robota. Orientację w trzech osiach możemy uzyskać dzięki żyroskopowi, akcelerometrowi i magnetometrowi. Magnetometr jest bardzo podatny na zakłócenia, szczególnie w pomieszczeniach i wymaga dobrej kalibracji, aby działał poprawnie. Z tego powodu zwykle używa się jedynie żyroskopu i akcelerometru. Akcelerometr pozwala nam wyliczyć dokładny kąt Pitch i Roll na podstawie wektora grawitacji jednak tylko przy wolniejszych zmianach. Dzięki żyroskopowi jesteśmy w stanie natomiast nadążać, za szybkimi zmianami jednak wyliczanie orientacji na jego podstawie polega na całkowaniu prędkości kątowych w każdej osi, co skutkuje ciągle narastającym błędem. Łącząc dane z akcelerometru i żyroskopu możemy śledzić szybkie zmiany orientacji, a zarazem zniwelować narastające błędy dzięki wektorowi grawitacji, ale niestety odnosi się to tylko do kątów Roll i Pitch, ponieważ obrót w osi Z (kąt Yaw) nie wpływa na odczyt wektora grawitacji. Z tego powodu kąt Yaw uzyskuje się jedynie z żyroskopu i jest on obarczony narastającym błędem. Aby zniwelować ten błąd używa się magnetometru, który wskazuje biegun magnetyczny ziemi. Można również wykorzystać inne metody określania kąta Yaw, jak np. użycie dwóch odbiorników GPS zamontowanych na dwóch krańcach pojazdu. 
+ 
+W następnym ćwiczeniu posłużymy się sterownikiem pixhawk, który został podłączony do komputera przewodem USB.
+ 
+![pixhawk](img/pixhawk.png "pixhawk")
+ 
+Na kontrolerze pixhawk zainstalowane jest oprogramowanie Ardupilot, pozwalające na sterowanie pojazdami autonomicznymi ([dokumentacja](https://ardupilot.org/ardupilot/)). 
+ 
+Istnieje wiele akcesoriów do układu pixhawk, które zwiększają jego możliwości jak:
+- odbiornik RC
+- GPS
+- Zewnętrzny magnetometr
+- Radiokomunikacja 
+- ...
+ 
+Na pokładzie pixhawka mamy do dyspozycji żyroskop, akcelerometr, magnetometr oraz barometr. Na potrzeby tego ćwiczenia wykorzystamy akcelerometr i żyroskop, aby określić orientację kontrolera.
+ 
+Aby odczytać dane z kontrolera możemy wykorzystać dwie metody:
+- program stacji bazowej np. [QGroundControl](http://qgroundcontrol.com/) czy [Mission Planner](https://ardupilot.org/planner/). W przypadku systemu Windows zalecam używanie programu Mission Planner, ponieważ posiada on dużo użytecznych funkcjonalności. Niestety jest on dostępny jedynie na systemy Windows, dlatego na potrzeby laboratorium użyjemy QGroundControl. Nie mniej jednak program QGroundControl jest również bardzo użytecznym programem, a zainstalować możemy go nawet na telefonie z systemem Android. 
+- bezpośrednio przy pomocy protokołu mavlink. Tą metodę stosuje się gdy do sterownika podłączamy komputer, który ma nadzorować jego pracę i wydawać mu komendy, tak jak w naszym przypadku. 
diff --git a/lab04/img/mobile_robot_standard_tf.png b/lab04/img/mobile_robot_standard_tf.png
new file mode 100644
index 0000000000000000000000000000000000000000..0b688fc5bea614150dc6b9cbaced8b5009939dcd
Binary files /dev/null and b/lab04/img/mobile_robot_standard_tf.png differ
diff --git a/lab04/img/odom_wzor.png b/lab04/img/odom_wzor.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a6630744a3fc4abd03b463bbc3e5ddf8eb7cfe7
Binary files /dev/null and b/lab04/img/odom_wzor.png differ
diff --git a/lab04/img/orientation.png b/lab04/img/orientation.png
new file mode 100644
index 0000000000000000000000000000000000000000..3ba49ec695abd7bac15344c3aa862e6728a38623
Binary files /dev/null and b/lab04/img/orientation.png differ
diff --git a/lab04/img/pixhawk.png b/lab04/img/pixhawk.png
new file mode 100644
index 0000000000000000000000000000000000000000..3d015f09a7f67f3df6fa906040b5fe54c894a280
Binary files /dev/null and b/lab04/img/pixhawk.png differ