Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simulator and corresponding lectures #65

Merged
merged 1 commit into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added docs/robot/lekce4/assets/sim.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Lekce 5 - Motory
# Lekce 4 - Motory

V této lekci zkusíme točit motory a pohybovat robotem.

Expand Down
115 changes: 0 additions & 115 deletions docs/robot/lekce4/turtle.md

This file was deleted.

108 changes: 108 additions & 0 deletions docs/robot/lekce5/pen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Lekce 5 - Servo (Kreslení tužkou)

Na Robůtkovi jsou dvě pozice na připojení serva - piny 38 a 21. Pokud jste si podle návodu ke složení robota připevnili servo a tužku, jste připraveni na to kreslit.

## Začátek

Abychom mohli používat servo, musíme ho získat příkazem `#!ts const servo = new Servo(...)`, kde do závorky napíšeme číslo PINu, timer (zde ho nastavíme na 1) a kanál (zde ho nastavíme na 4)

```ts
import { Pins } from "./libs/robutek.js"
import { Servo } from "./libs/servo.js"

const servo = new Servo(Pins.Servo2, 1, 4); // Pins.Servo2 je pin 38
```

Na nastavení pozice serva použijeme funkci `#!ts servo.write()` a do závorek zadáme číslo od 0 do 1023,
které určí úhel otočení.
```ts
servo.write(0); // 0°
servo.write(512); // 90°
servo.write(1023); // 180°
```

## Kreslení tužkou

Tím, že zvedáme nebo pokládáme servo, můžeme ovládat připevněnou tužku.
Abychom si nemuseli pamatovat konkrétní hodnoty pro zvedání tužky, Robůtek má 3 předdefinované konstaty pro ovládání: `Up`, `Down` a `Unload`.
Pokud bychom do něj dávali různé druhy tužek, můžeme si samozřejmě nadefinovat vlastní.

```ts
import { Pins } from "./libs/robutek.js"
import { Servo } from "./libs/servo.js"

const pen = new Servo(Pins.Servo2, 1, 4); // Pins.Servo2 je pin 38
```

Na nastavení pozice tužky použijeme funkci `#!ts pen.write()` a do závorek zadejte číslo on 0 od 1023 nebo jednu z konstant `robutek.PenPos.Up`, `robutek.PenPos.Down` a `robutek.PenPos.Unload`.

```ts
pen.write(robutek.PenPos.Down); // Začne kreslit
pen.write(robutek.PenPos.Up); // Přestane kreslit
pen.write(robutek.PenPos.Unload); // Vytáhne tužku
```

## Zadání A

Vytvořte program, který při zmáčknutí tlačítka zasune pero a druhé tlačítko, které ho vysune.

??? note "Řešení"
```ts
import { Pins } from "./libs/robutek.js"
import * as robutek from "./libs/robutek.js"
import { Servo } from "./libs/servo.js"
import * as gpio from "gpio"

const LBTN_PIN = 2;
const RBTN_PIN = 0;

gpio.pinMode(LBTN_PIN, gpio.PinMode.INPUT);
gpio.pinMode(RBTN_PIN, gpio.PinMode.INPUT);

const pen = new Servo(Pins.Servo2, 1, 4);

gpio.on("falling", LBTN_PIN, () => {
pen.write(robutek.PenPos.Down);
});

gpio.on("falling", RBTN_PIN, () => {
pen.write(robutek.PenPos.Up);
});
```

## Zadání B

Zkombinuj poznatky z lekce 5 s motory s touto, a vytvoř program který nakreslí fixou na papír čtverec po stistku tlačítka.

??? note "Řešení"
```ts
import { Pins } from "./libs/robutek.js"
import * as robutek from "./libs/robutek.js"
import { Servo } from "./libs/servo.js"
import * as gpio from "gpio"

const LBTN_PIN = 2;
const RBTN_PIN = 0;

gpio.pinMode(LBTN_PIN, gpio.PinMode.INPUT);
gpio.pinMode(RBTN_PIN, gpio.PinMode.INPUT);

const pen = new Servo(Pins.Servo2, 1, 4);

gpio.on("falling", LBTN_PIN, async () => {
pen.write(robutek.PenPos.Down); // fixa dolů

robutek.setSpeed(100) // Nastav rychlost na 100

await robutek.move(0, { distance: 300 }) // Ujeď 30 cm
await robutek.rotate(90)
await robutek.move(0, { distance: 300 })
await robutek.rotate(90)
await robutek.move(0, { distance: 300 })
await robutek.rotate(90)
await robutek.move(0, { distance: 300 })
await robutek.rotate(90)

pen.write(robutek.PenPos.Up); // fixa nahoru
});
```
Binary file added docs/robot/lekce6/assets/circles.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/robot/lekce6/assets/square.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 2 additions & 7 deletions docs/robot/lekce4/index.md → docs/robot/lekce6/for.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Lekce 4 - cykly
# Lekce 6 - cykly

V této lekci si představíme cykly, což je nástroj který nám umožňuje opakovat kód podle nějakého pravidla.
Zatím je využijeme pro komunikaci s robotem, v následující lekci si ukážeme jejich použití při řízení robota.
Expand Down Expand Up @@ -28,7 +28,6 @@ Následně definujeme výraz `#!ts i < 3 `, který značí, kdy se cyklus má za
Při prvním průchodu bude tedy `#!ts i = 0` při druhém `#!ts i = 1 ` a při třetím `#!ts i = 2 ` při dalším zvyšování by platilo `#!ts i = 3 ` tam ale už nebude pravdivý výraz ` i < 3 ` a cyklus se tedy ukončí.
Do složených závorek píšeme vykonávaný kód, který se v tomto případě vykoná 3-krát.

Kostru na tento úkol najdete [zde](./project4.zip).

## Zadání A
Ve spojení se znalostmi z minulých lekcí napište program, který po stisku tlačítka vypíše čísla 0 až 9 (pomocí `#!ts console.log(cislo)`), vždy na samostatný řádek.
Expand Down Expand Up @@ -95,7 +94,7 @@ Pokud nechceme za vypsanými znaky nový řádek, místo známého `#!ts console

## Zadání výstupního úkolu V1
Napište kod který který vypíše čísla od 9 do 0.
Nápověda, zadání je velmi podobné jako zadání A jen jdou čísla sestupně namísto vzestupně.
Zadání je velmi podobné jako zadání A, jen jdou čísla sestupně namísto vzestupně. Nekopírujte jen dodaný kód, ale zkuste si jej napsat sami.

## Zadání výstupního úkolu V2
Stejně jako v zadání B budeme do konzole vykreslovat geometrický obrazec, akorát tentokrát to bude trojúhelník jako tenhle:
Expand All @@ -107,7 +106,3 @@ Stejně jako v zadání B budeme do konzole vykreslovat geometrický obrazec, ak
****
*****
```

!!! tip "Pro dobrovolníky"

- Zkuste kreslit různé tvary, a různé typy: např. trojuhelník, který je uvnitř dutý, stromeček, nebo kruh
121 changes: 121 additions & 0 deletions docs/robot/lekce6/turtle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Lekce 6.5 - Cykly znovu a lépe

Tato lekce ukazuje praktické využití cyklů za účelem kreslení obrazců. V předchozích lekcích jsme si ukázali jednoduchou jízdu s robotem a zvedání tužky, a navážeme na to dále.

## Želvička

Tato lekce je určena primárně na práci v [Simulátoru](https://xondika.github.io/sitrusj/). Program obsahuje zjednodušenou verzi reality, ve které nám bude jezdit želvička a přijímat příkazy na základě vnějších podnětů.

Programy nám budou fungovat i na skutečném robotovi. Je však je důležité nejdříve si v simulaci ověřit funkčnost, aby se nám skutečný robot nezačal chovat neočekávaným způsobem a nezpůsobil sobě nebo nám škody.

Program má textové okno, kam můžeme psát příkazy. Nám již známé příkazy jsou:

`robutek.rotate(deg)` - želvička se otočí o `deg` stupňů po směru hodinových ručiček
`robutek.move(direction, options)` - želvička jede některým směrem na základě zadaných parametrů


## Zadání A

V jedné z předchozích lekcí jsme použili znalosti o ovládání motorů a fixy na nakreslení čtverce.
Museli jsme však několikrát pod sebou kopírovat kód na pohyb dopředu a otočení, ačkoliv jsme vykonávali čtyřikrát to stejné. Tentokrát pomocí for cyklu napište kód, díky kterému robot nakreslí čtverec a vrátí se do výchozí polohy.

![](assets/square.png)


??? note "Řešení"
```ts
import * as robutek from "./libs/robutek.js"; // ovládání motorů

let pen = new Servo(robutek.Pins.Servo2, 1, 4);
pen.write(robutek.PenPos.Down); // dáme dolů tužku

robutek.setSpeed(100) // nastavíme rychlost na 100 mm/s

for (let i: number = 0; i < 4; i++) { // chování opakujeme 4x, pro každou stěnu čtverce
await robutek.move(0, { distance: 200 }); // posun dopředu o 20 cm
await robutek.rotate(90); // rotace doprava o 90 stupňů
}
```

<!-- Toto chování můžeme také provést v reakci na událost. Modifikujte program tak, aby želvička projela čtverec až po stisknutí tlačítka. -->

<!-- ??? note "Řešení" -->
<!-- ```ts -->
<!-- import * as gpio from "gpio"; -->
<!-- import * as motors from "motors"; // ovládání motorů -->


<!-- const BTN_PIN = 18; -->
<!-- gpio.pinMode(BTN_PIN, gpio.PinMode.INPUT); // nastaví pin 18 jako vstup -->
<!-- gpio.on("falling", BTN_PIN, () => { // reakce na stisk tlačítka -->
<!-- for (let i: number = 0; i < 4; i++) { // chování opakujeme 4x, pro každou stěnu čtverce -->
<!-- motors.move(10); // posun dopředu o 10 cm -->
<!-- motors.rotate(90); // rotace doprava o 90 stupňů -->
<!-- } -->
<!-- }); -->
<!-- ``` -->

## Zadání B

Napište kód, pomocí kterého nakreslíte několik na sebe navazujících kruhů.
Dá se na to využít zatáčení pomocí `motors.move(1)`.
Vzdálenost, kterou je potřeba ujet si dopočítáme na základě toho, že kola jsou od sebe `82mm` daleko.
Po nakreslení každého kola se můžeme otočit, ale pro plynulý pohyb chceme kreslit každé kolo z jiného směru.
K tomu může pomoct například stavová proměnná, která nám řekne, jestli tentokrát pojedeme doprava, nebo doleva.


![](assets/square.png)


??? note "Řešení"
```ts
import * as robutek from "./libs/robutek.js"; // ovládání motorů

let pen = new Servo(robutek.Pins.Servo2, 1, 4);
pen.write(robutek.PenPos.Down); // dáme dolů tužku

robutek.setSpeed(100) // nastavíme rychlost na 100 mm/s

l et direction: number = 1; // směr otáčení
let circumference: number = 2 * 3.14 * 82; // obvod jednoho kruhu, který robot objede
for (let i: number = 0; i < 4; i++) { // chování opakujeme 4x, pro každou stěnu čtverce
await robutek.move(direction, { distance: circumference * 1.5 }); // chceme projet obvod 1,5x
if( direction == 1 ){
direction = -1;
} else {
direction = 1;
}
}
```


## Výstupní úkol V1 - Trojúhelník

Napište kód, který způsobí, že želvička nakreslí místo čtverce trojúhelník. Rozměry trojúhelníku jsou na vás, jen musí skutečně jít o trojúhelník.

!!! tip "Jak na Trojúhelníky""
Tvar s délkami `a`, `b` a `c` nazýváme trojúhelníkem, pokud splňuje trojúhelníkovou nerovnost:
```math
a + b > c
a + c > b
b + c > a
```

Nejjednodušší trojúhelník je rovnostranný, který bude mít všechny strany stejně dlouhé a 60° vnitřní úhel na každém rohu.

Hned po něm následuje rovnoramenný, který v nejjednodušším případě bude mít 90° úhel mezi kratšími stranami, a 45° mezi krátkou a dlouhou.

Pokud chceme nějaký méně pravidelný trojúhelník, můžeme na výpočet úhlu a délek použít [kosínovu větu](https://cs.wikipedia.org/wiki/Kosinov%C3%A1_v%C4%9Bta).

## Výstupní úkol V2 - Domeček

Propojte dosavadní znalosti do jednoho kódu.
Napište program, který způsobí že si želvička nakreslí domeček z čtverce a trojúhelníkové střechy.

Následně želvička přestane kreslit, a vjede doprostřed domečku, kde zastaví.

### Dobrovolný úkol - Spuštění na vlastním robotovi

Pokud vám program funguje v simulátoru, zkuste si ho nahrát do skutečného robota.
Funguje vám? Pozorujete nějaké rozdíly v jeho chování oproti zjednodušenému prostředí?

Loading
Loading