Skip to content

Commit

Permalink
docs: Add drawing lecture and overall outline
Browse files Browse the repository at this point in the history
  • Loading branch information
xondika committed May 25, 2024
1 parent 3bd30b7 commit 29a32a7
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 51 deletions.
39 changes: 39 additions & 0 deletions docs/lekce.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Táborové lekce: želvička 2024

Technický blok:
Instalace Jaculus a IDE (simulátor?)
Bezdrát, ovládání přes bt (?)
Mechanická výroba (?): skládání robota a mechanické zvedání tužky, nárazníky?
Bločky?
Diferenciální řízení
Senzorika

Základy programování:
Struktura programu
Proměnné a podmínky
Události (první tři asi lze převzít z minulého tábora)
Řídicí struktury (tady by se to pěkně ukazovalo v simulátoru s kreslící želvičkou)
Řetězce
Rekurze (?)
OOP (?)

Základy algoritmiky:
Graf
Fronta, zásobník
Hledání nejkratší cesty

Jízda v bludišti a po čáře - úvodní lekce

Projekty: skupinky, soutěž o nejlepší čas

Simulátor specifikace:
- 2D vykreslování
- Schopnost kreslit čáry a překážky, export a import JSON
- Řízení robota: z klávesnice nebo jako popis instrukcí
+ Šipky pro zrychlení: pravá-levá zvedne rychlost jednoho z motorů, dopředu a dozadu sníží rychlost obou současně (?)
+ Pseudokód (JavaScript?) specifikující chování robota (e.g. když narazím na čáru nebo detekuju zeď - změním směr, nebo pomocí cyklů (událostí) kreslím obrázek)
- Senzorika:
+ Senzory čáry tak jak jsou na robotovi, přepínání mezi krajními a čárovými jedním tlačítkem
+ Lidar: dám si ho na robota jak chci, ručně nasměruji, potom mi při požadavku čtení vrátí vzdálenost zdi kterou našel.
Ve směru překážky mi vrací normální rozdělení kolem skutečné hodnoty, ve větší vzdálenosti s nějakou pravděpodobností selže.
Hodnoty bych dal nastavitelné (pro nás, abychom to upravili na základě skutečných hodnot), ale dětem už bych je zafixoval a schoval.
15 changes: 9 additions & 6 deletions docs/robot/lekce1/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ V této lekci si představíme Jaculus, nainstalujeme si programovací prostřed

## Instalace

Pro práci s Jaculem je nutné nainstalovat několik programů.
Na našich robotech běží program, který se jmenuje Jaculus.
Tento program nám umožní jednoduše psát instrukce (programy), které nahrajeme do robota.
Tyto programy budou specifikovat, jak se robot má chovat, a umožní nám s ním komunikovat.
Aby nám všechno správně fungovalo, musíme nejprve nainstalovat několik programů.

### Node.js

Node.js je program, který nám umožní nahrávat kód do Jacula a komunikovat s ním.
`node.js` je knihovna, která nám umožní stáhnout nástroje na používání Jacula.

1. Stáhneme si [Node.js](https://nodejs.org/en/download) (nejnovější stabilní verzi - LTS)
2. Nainstalujeme jej dle výchozího nastavení (není potřeba nic měnit).
Expand All @@ -22,10 +25,10 @@ Visual Studio Code je programovací prostředí, které nám umožní psát kód

### Jaculus

Jaculus je program, který nám umožní nahrávat kód do Jacula a komunikovat s ním.
Nyní už se můžeme vrhnout na samotnou instalaci [`Jacula`](https://jaculus.org/getting-started/).

1. Po instalaci Nodu **restartujeme** aplikaci Visual Studio Code.
2. V horním menu VSCode vyberte záložku `Terminal` a zvolíme `New Terminal`.
1. Po instalaci `node` **restartujeme** aplikaci Visual Studio Code.
2. V horním menu VSCode vybereme záložku `Terminal` a zvolíme `New Terminal`.
3. Do terminálu zadáme příkaz vypsaný níže. Na `Linuxu` bude nejspíše potřeba `sudo` práva.

```bash
Expand Down Expand Up @@ -187,4 +190,4 @@ Ve zdrojovém kódu jsou komentáře (`// tohle je komentář`), které nám pop

const ledStrip = new SmartLed(LED_PIN, LED_COUNT, LED_WS2812); // připojí pásek na pin 48, s 1 ledkou a typem WS2812
...
```
```
16 changes: 11 additions & 5 deletions docs/robot/lekce2/index.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# Lekce 2 - RGB LED + tlačítko + události

V této lekci si ukážeme ovládání RGB LED umístěné na ESP32 a práci s událostmi řízenými tlačítkem nebo časem.
V této lekci si napíšeme své první programy.

Jelikož je TypeScript (JavaScript) imperativní, vykonávájí se příkazy v takovém pořadí, v jakém jsou zapsány.
Ukážeme si ovládání RGB LED umístěné na ESP32 a práci s událostmi řízenými tlačítkem nebo časem.

TypeScript (JavaScript) je imperativní programovací jazyk. Znamená to, že se vykoná vše co do programu napíšeme,
v takovém pořadí jak jsme to zapsali. Programy mají řadu věcí co v nich umíme zapsat, nám zatím budou stačit
nejzákladnější příkazy: i velice jednoduchý program už může mít viditelný výsledek.

[Stáhnout ZIP s prázdným projektem](./blank_project.zip){ .md-button .md-button--primary }

Expand Down Expand Up @@ -82,7 +86,9 @@ Pomocí událostí rozsvítíme při stisknutí tlačítka (GPIO 0) RGB LED na E

## Zadání C

Dvakrát za sekundu vypíšeme stav zmáčknutí tlačítka (0 nebo 1). Opakování dosáhneme pomocí `setInterval()`. Stav daného tlačítka získáme pomocí `#!ts gpio.read(číslo pinu)`.
Dvakrát za sekundu vypíšeme stav zmáčknutí tlačítka (0 nebo 1). Stav daného tlačítka získáme pomocí `#!ts gpio.read(číslo pinu)`.

Vzpomeňme si z prvního programu, že opakování dosáhneme pomocí `setInterval()`, a informaci vypíšeme pomocí `#!ts console.log()`.

??? note "Řešení"
```ts
Expand All @@ -97,10 +103,10 @@ Dvakrát za sekundu vypíšeme stav zmáčknutí tlačítka (0 nebo 1). Opaková
}, 500); // čas opakování se udává v milisekundách (500 ms je 0,5 sekundy)
```

## Zadání výstupního úkolu V1
## Výstupní úkol V1 - Pozdrav

Při stisknutí tlačítka (GPIO 0) vypíšeme pozdrav.

## Zadání výstupního úkolu V2
## Výstupní úkol V2 - Změna barvy

Při stisknutí tlačítka (GPIO 0) rozsvítíme RGB LED na ESP32 (`GPIO 48`) jednou barvou a při puštění barvu změníme na jinou.
8 changes: 4 additions & 4 deletions docs/robot/lekce3/index.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Lekce 3 - proměnné a podmínky

V imperativním programování si držíme stav pomocí **proměnných**. Proměnné jsou pojmenované hodnoty,
které mají nějakou hodnotu, můžeme je měnit, a opakovaně používat v různých částech kódu.
které můžeme měnit, a opakovaně používat v různých částech kódu.

Proměnná má svůj typ, který určuje, jaké hodnoty může proměnná mít. Proměnnou vytvoříme pomocí
klíčového slova `let`.
Expand Down Expand Up @@ -122,7 +122,7 @@ Pomocí jedné proměnné se stavem a podmínky každou sekundu buď rozsvítím

## Zadání B

Pomocí funkce `colors.rainbow` budeme procházet duhu. Jde o funkci, která dostane číslo od 0 do 360,
Pomocí funkce `colors.rainbow` budeme procházet duhu. Jde o funkci (o těch si povíme trochu více později), která dostane číslo od 0 do 360,
a na základě toho vrátí barvu na barevném spektru. V daném intervalu (např. 100 ms) budeme postupně zvyšovat číslo a nastavovat barvu LEDky na `colors.rainbow(cislo)`. Pokud naše číslo přesáhne hodnotu `360`, musíme ho
opět nastavit na `0`.

Expand Down Expand Up @@ -185,9 +185,9 @@ Pokud při stisku tlačítka svítí poslední LED, zhasneme ji, a rozsvítíme
});
```

## Výstupní úkol V1
## Výstupní úkol V1 - Knightrider

Knightrider: svítící LED "běhá" s danou rychlostí od začátku do konce pásky.
Svítící LED "běhá" s danou rychlostí od začátku do konce pásky.
Jakmile dorazí na konec, změní směr, a posouvá se opačným směrem.

V našem případě bude stačit, když se bude pohybovat pouze jedna LEDka.
Expand Down
47 changes: 11 additions & 36 deletions docs/robot/lekce4/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Lekce 4 - 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.

(Nejsem si jistý jak moc tady tu lekci chceme. Přijde mi to méně zajímavé než jezdit s želvičkou, ale když jsem se to snažil dát do jedné lekce, přišla mi moc dlouhá.)

Máme primárně dva typy cyklů:

- `#!ts for` pro případ kdy víme kolikrát se cyklus má opakovat
Expand All @@ -19,9 +23,12 @@ Do kulatých závorek píšeme tři věci:
- výraz který určuje počet opakování
- nakonec jednoduchou operaci která se provede při každém průchodu cyklem jako poslední operace

Tedy zakládáme proměnnou `#!ts i` s výchozí hodnotou `#!ts 0`, následně definujeme výraz `#!ts i < 3 ` a na konci cyklu zvýšíme `#!ts i ` o jedna.
Tedy vytváříme proměnnou `#!ts i` s výchozí hodnotou `#!ts 0`, která bude existovat po dobu toho, co se vykonává cyklus.
Ačkoliv v běžném životě počítáme věci od `1`, v informatice častěji začínáme `0`. Může zde však být cokoliv.

Následně definujeme výraz `#!ts i < 3 `, který značí, kdy se cyklus má zastavit. Na konci cyklu zvýšíme `#!ts i ` o jedna.
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.
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).

Expand All @@ -35,7 +42,7 @@ Kod napište tak aby bylo jednoduché ho upravit na výpis jakéhokoli jiného i

const BTN_PIN = 18;

gpio.pinMode(BTN_PIN, gpio.PinMode.INPUT_PULLUP); // nastaví pin nula jako vstup
gpio.pinMode(BTN_PIN, gpio.PinMode.INPUT); // nastaví pin 18 jako vstup

gpio.on("falling", BTN_PIN, () => { // událost, která proběhne při stisknutí tlačítka připojeného na pin 0
console.log("Stisknuto, začínáme počítat");
Expand All @@ -47,7 +54,7 @@ Kod napište tak aby bylo jednoduché ho upravit na výpis jakéhokoli jiného i
```

## Cyklus while
Pokud nevíme kolikrát se má cyklus opakovat použijeme místo cyklu `#!ts for ` cyklus `#!ts while `.
Pokud nevíme, kolikrát se má cyklus opakovat, použijeme místo cyklu `#!ts for ` cyklus `#!ts while `.

Do kulatých závorek teď píšeme jen výraz který určuje jestli se cyklus vykoná znovu nebo ne.
Kód, který se má vykonávat, dokud platí podmínka, vypadá takto:
Expand All @@ -56,40 +63,8 @@ while (condition - podmínka) {
// náš kód
}
```
<!-- V podobných případech se nám bude často hodit funkce `#!ts await sleep(t)`, která zařídí že kód posečká zadaný čas (zadaný čas je v ms neboli v tisícinách sekundy). -->


<!-- Napište kód který bude blikat ledkou pokud je stisknuté tlačítko.
## Zadání C
...
??? note "Řešení"
```ts
import { SmartLed, LED_WS2812 } from "smartled";
import * as colors from "./libs/colors.js"
import * as gpio from "gpio";
const LED_PIN = 48;
const LED_COUNT = 1;
const BTN_PIN = 18;
const ledStrip = new SmartLed(LED_PIN, LED_COUNT, LED_WS2812); // připojí pásek na pin 48, s 1 ledkou a typem WS2812

gpio.pinMode(BTN_PIN, gpio.PinMode.INPUT_PULLUP); // nastaví pin nula jako vstup

gpio.on("falling", 0, async () => { // event, který proběhne při stisknutí tlačítka připojeného na pin 0
while (gpio.read(BTN_PIN) == 0) { // dokud je tlačítko stisknuté
ledStrip.set(0, colors.red);
ledStrip.show();
await sleep(500); // nastavíme červenou barvu a počkáme půl sekundy
ledStrip.set(0, colors.off);
ledStrip.show();
await sleep(500); // vypneme LED a počkáme půl sekundy
}
});
```
-->

## Zadání B
Nyní napište kód který do konzole vypíše čtverec složený z hvězdiček (znaku `*`),
Expand Down
105 changes: 105 additions & 0 deletions docs/robot/lekce4/turtle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Lekce 4.5 - želvička

Tato lekce přímo navazuje na předchozí, a ukazuje praktické použití cyklů.

## Želvička

Cykly si vyzkoušíme v programu `Želvička (TODO název?)`. 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ů.

// TODO Obrázek a link na simulátor

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. Zatím jsou pro nás zajímavé příkazy (TODO přesná specifikace):

`motors.rotate(deg)` - želvička se otočí o `deg` stupňů po směru hodinových ručiček
`motors.move(dist)` - želvička se pohne dopředu o `dist` centimetrů

Zatím pro jednoduchost uvažujme, že se želvička umí buď otáčet, nebo jet dopředu, ale ne obojí zároveň. V kapitole (TODO diferenciální řízení) si ukážeme pokročilejší způsob jak ji řídit.
Jízdu obloukem zatím budeme řešit tak, že opakovaně popojedeme o maličký kousek, a poté se trošku otočíme.

## Zadání A

Napište program, který z výchozí pozice želvičky vyjede o kousek dopředu, objede čtverec, a vrátí se zase zpět.

// TODO gif? nebo prostě ukázat na lekci

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

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ňů
}
```

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ňů
}
});
```

### Kreslení

Želvička kromě jízdy umí i kreslit. Má v sobě tužku, kterou může buď zvednout, nebo položit.
Slouží na to příkaz:

`motors.draw(pravdivostní hodnota)` - Tato funkce určuje, jestli má želvička kreslit, nebo ne. Hodnota `true` nám říká, že máme tužku položenou na zemi (tj. kreslíme), hodnota `false` že nekreslíme.

This comment has been minimized.

Copy link
@JakubAndrysek

JakubAndrysek May 25, 2024

Member

@xondika asi by se mi víc líbilo něco jako pen.draw(pravdivostní hodnota) nebo přímo přes servo (nevím už jak se volá). Ale to je drobnost.


Na skutečném robotovi nám kreslení bude fungovat po nainstalování fixy podle (TODO manuální konstrukce).

## Zadání B

Vraťme se k předchozímu příkladu. Abychom věděli, že želvička skutečně projela čtverec, necháme ji nakreslit ho. Dopíšeme tedy program tak, aby po stisku tlačítka položila tužku, nakreslila čtverec, a následně tužku zase zvedla.

??? 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
motors.draw(true);
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ňů
}
motors.draw(false);
});
```

## 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 "Trojúhelníková nerovnost (nechť `a`, `b`, `c` jsou délky stran)""
```math
a + b > c
a + c > b
b + c > a
```

Na zjištění úhlu, o který je potřeba se otočit, můžeme použít kosínovu větu (Dodat jako knihovní funkci, tak jako barvičky).


## 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í.

0 comments on commit 29a32a7

Please sign in to comment.