Skip to content

Commit 9c7b07f

Browse files
Migrate from .ipynb to MyST text notebooks (.md)
- Replace basic_lessons/*.ipynb with MyST text notebooks (.md) from unstable/ - Add new lesson0_tutorial (virtual environment setup) to basic_lessons - Remove unstable/ directory (lessons promoted to stable) - Remove convert_to_myst.py (no longer needed) - Update myst.yml: point TOC to .md files, add lesson0, remove unstable section - Update basic_lessons/README.md: reflect new format and add lesson0 - Update GitHub Actions workflow: add PR trigger, rename to 'MyST Book' - Update AGENTS.md: reflect new MyST text notebook structure
1 parent 10fb422 commit 9c7b07f

30 files changed

Lines changed: 88 additions & 5712 deletions

.github/workflows/notebook_to_html.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
# This is a basic workflow to help you get started with Actions
2-
3-
name: Jupyter Book
1+
name: MyST Book
42

53
# Controls when the workflow will run
64
on:
75
# Triggers the workflow on push or pull request events but only for the "main" branch
86
push:
97
branches: [ "main" ]
8+
pull_request:
9+
branches: [ "main" ]
1010

1111
# Allows you to run this workflow manually from the Actions tab
1212
workflow_dispatch:
1313

1414

15-
1615
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
1716
jobs:
1817
# This workflow contains a single job called "build"
@@ -22,7 +21,7 @@ jobs:
2221

2322
# To prevent github actions from eating up too many enterprise minutes
2423
timeout-minutes: 5
25-
24+
2625
# https://github.com/actions/starter-workflows/blob/55eb18560f57898549b12afa6defe7cc79705d6a/pages/static.yml#L13
2726
permissions:
2827
contents: read

AGENTS.md

Lines changed: 54 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2,99 +2,60 @@
22

33
## Overview
44

5-
**Open Executable Books in Robotics** is a collection of Jupyter notebooks teaching kinematic modelling and control of serial-link robotic manipulators. The project is licensed under [CC-BY-NC-SA 4.0](LICENSE) and hosted at <https://github.com/MarinhoLab/OpenExecutableBooksRobotics>.
5+
**Open Executable Books in Robotics** is a collection of MyST text notebooks teaching kinematic modelling and control of serial-link robotic manipulators. The project is licensed under [CC-BY-NC-SA 4.0](LICENSE) and hosted at <https://github.com/MarinhoLab/OpenExecutableBooksRobotics>.
66

77
---
88

99
## Repository Structure
1010

1111
| Path | Purpose |
1212
|------|---------|
13-
| `basic_lessons/` | Canonical source: `.ipynb` notebooks (5 tutorials + 5 exercise answer keys) |
14-
| `unstable/` | Work-in-progress text-only MyST notebooks (`.md` with `{code-cell}` directives) |
13+
| `basic_lessons/` | Canonical source: MyST text notebooks (`.md` with `{code-cell}` directives) — 6 tutorials + 5 exercise answer keys |
1514
| `other/` | Supplementary content (e.g. `dqrobotics.md`) |
16-
| `convert_to_myst.py` | Script: converts `basic_lessons/*.ipynb``unstable/*.md` |
17-
| `myst.yml` | MyST project config (root): LaTeX macros, TOC (including unstable section), site options |
18-
| `unstable/myst.yml` | Standalone MyST project config for unstable-only builds (optional) |
19-
| `build_html.sh` | Build script for `jupyter-book` (legacy pipeline) |
15+
| `myst.yml` | MyST project config (root): LaTeX macros, TOC, site options |
16+
| `build_html.sh` | Build script for `jupyter-book` |
2017
| `conf.py` | MyST parser extensions (`dollarmath`) |
21-
| `_build/` | Build artifacts (excluded from git via `unstable/.gitignore`) |
18+
| `_build/` | Build artifacts (excluded from git) |
2219

2320
---
2421

25-
## Modifying `.ipynb` Files
22+
## Modifying MyST Text Notebooks
2623

27-
Jupyter notebooks are JSON files. Every cell's `source` field is a **list of strings**, where **each string must end with `\n`** (trailing newline). This is critical:
24+
Lessons are [MyST text notebooks](https://mystmd.org/guide/notebooks-with-markdown) — plain Markdown files with `{code-cell}` directives. They are version-control friendly and human-readable.
2825

29-
### Correct format (renders properly in Jupyter):
30-
```json
31-
"source": [
32-
"# L1 A quick Python refresher\n",
33-
"\n",
34-
"*License: CC-BY-NC-SA 4.0*\n",
35-
"\n",
36-
"### Prerequisites\n",
37-
"The user of this notebook is expected to have prior knowledge in\n"
38-
]
39-
```
40-
41-
### Broken format (renders as one concatenated line):
42-
```json
43-
"source": [
44-
"# L1 A quick Python refresher",
45-
"",
46-
"*License: CC-BY-NC-SA 4.0*",
47-
""
48-
]
49-
```
26+
### Structure
5027

51-
### When editing notebooks programmatically:
52-
1. Load with `json.load()`, modify `cell['source']` entries.
53-
2. **Every source line must end with `\n`** before writing back.
54-
3. Save with `json.dump(nb, f, indent=1)` (single-space indent is standard).
55-
4. Clear execution state on code cells to avoid stale output:
56-
```python
57-
cell['outputs'] = []
58-
cell['execution_count'] = None
59-
```
60-
61-
### When editing notebooks manually:
62-
- Use a notebook editor (Jupyter, VSCode, or nbconvert) rather than raw text edits.
63-
- If editing raw JSON, always verify trailing `\n` on source lines.
64-
65-
### Cell types:
66-
| Type | Purpose |
67-
|------|---------|
68-
| `markdown` | Text, equations, images, headings |
69-
| `code` | Python cells (numpy, math) |
70-
| `raw` | Raw LaTeX macro definitions (`\providecommand`) |
71-
72-
### LaTeX macros:
73-
Custom macros (`\myvec`, `\mymatrix`, `\quat`, `\dual`) are defined in two places:
74-
1. As **raw cells** in each notebook (for Jupyter/LaTeX rendering)
75-
2. In **`myst.yml`** under `project.math` (for MyST rendering)
28+
Each `.md` lesson file begins with YAML frontmatter declaring the kernel:
7629

30+
```yaml
31+
---
32+
kernelspec:
33+
name: python3
34+
display_name: 'Python 3'
7735
---
36+
```
7837

79-
## Converting to MyST Text Notebooks
38+
Code cells are delimited with `{code-cell}` directives:
8039

81-
Run the converter script to regenerate `unstable/*.md` from the canonical notebooks:
40+
````markdown
41+
````{code-cell}
42+
import numpy as np
43+
x = np.array([1, 2, 3])
44+
````
45+
````
8246

83-
```bash
84-
python3 convert_to_myst.py
85-
```
47+
### Editing guidelines
8648

87-
This script:
88-
- Copies images (`Lesson4.png`, `Lesson4.svg`) to `unstable/`
89-
- Converts markdown cells as-is, code cells as ` ````{code-cell}```` directives
90-
- Strips raw cells and LaTeX macro markdown cells (handled by `myst.yml`)
91-
- Fixes `attachment:` image syntax → plain relative paths
92-
- Handles both trailing-newline and no-trailing-newline source formats
49+
- Edit `.md` files directly — they are plain text.
50+
- Every lesson should follow the header format convention (see below).
51+
- Keep code cells focused and self-contained.
52+
- LaTeX equations use inline `$...$` or display `$$...$$` syntax with the `dollarmath` MyST extension enabled in `conf.py`.
53+
- Custom macros (`\myvec`, `\mymatrix`, `\quat`, `\dual`) are defined in `myst.yml` under `project.math`.
9354

94-
### MyST Compatibility Notes
55+
### Image references
9556

96-
- **`%%capture` magic is not supported** in MyST text notebooks. The converter may produce cells containing `%%capture` (a Jupyter magic that suppresses output). These must be removed manually from the generated `.md` files, as MyST does not support this magic and the cell will fail to execute.
97-
- After regenerating with `convert_to_myst.py`, check all unstable `.md` files for `%%capture` and remove those lines.
57+
- Use relative paths: `![alt](Lesson4.png)` (relative to `basic_lessons/`)
58+
- Images (`Lesson4.png`, `Lesson4.svg`) live alongside the lesson files in `basic_lessons/`.
9859

9960
---
10061

@@ -116,31 +77,27 @@ pip install jupyter-book --pre
11677

11778
### Build Commands
11879

119-
**MyST build (root — includes all lessons + unstable):**
120-
```bash
121-
myst build --html
122-
```
123-
- `--execute` runs all code cells and caches results in `_build/execute/`
124-
- `--html` produces HTML output in `_build/html/`
125-
- Site format (JSON) goes to `_build/site/`
126-
127-
**MyST build (unstable only — optional):**
128-
```bash
129-
cd unstable
130-
myst build --execute --html
131-
```
132-
133-
**Legacy jupyter-book build (root):**
80+
**jupyter-book build (CI pipeline):**
13481
```bash
13582
chmod +x build_html.sh
13683
./build_html.sh
13784
```
138-
- Requires `BASE_URL` env variable for correct link resolution
85+
- Installs `jupyter-book --pre` (Jupyter Book 2.0 alpha)
86+
- Sets `BASE_URL` for correct link resolution
87+
- Runs `python -m jupyter book build --html --execute`
13988
- Outputs to `_build/html/`
14089

90+
**MyST build (local development):**
91+
```bash
92+
pip install mystmd jupyter-server ipykernel
93+
myst build --html
94+
```
95+
- `--execute` runs all code cells and caches results in `_build/execute/`
96+
- `--html` produces HTML output in `_build/html/`
97+
14198
### CI/CD
14299

143-
The GitHub Actions workflow (`.github/workflows/notebook_to_html.yml`) runs on pushes/PRs to `main`:
100+
The GitHub Actions workflow (`.github/workflows/notebook_to_html.yml`) runs on pushes to `main` and on pull requests:
144101
1. Runs `./build_html.sh` (jupyter-book pipeline)
145102
2. Uploads `_build/html/` as Pages artifact
146103
3. Deploys to GitHub Pages
@@ -173,9 +130,8 @@ Thank you! Please report it at https://github.com/MarinhoLab/OpenExecutableBooks
173130
- `\dual{}` for dual numbers
174131

175132
### Image references:
176-
- In `.ipynb`: `![alt](Lesson4.png)` (relative to `basic_lessons/`)
177-
- In `.md` (unstable): same — images are copied to `unstable/`
178-
- Avoid `attachment:` prefix in MyST notebooks
133+
- Use relative paths: `![alt](Lesson4.png)` (relative to `basic_lessons/`)
134+
- Images live alongside the lesson files in `basic_lessons/`.
179135

180136
### Language:
181137
- **UK English** spelling (e.g. *behaviour*, *modelling*, *summarised*)
@@ -192,18 +148,17 @@ Thank you! Please report it at https://github.com/MarinhoLab/OpenExecutableBooks
192148

193149
### Files excluded from version control:
194150
- `venv/` — Python virtual environment
195-
- `_build/` — Build artifacts (both root and `unstable/`)
196-
- `unstable/.gitignore` already excludes `unstable/_build/`
151+
- `_build/` — Build artifacts
197152

198153
---
199154

200155
## Adding a New Lesson
201156

202-
1. Create `basic_lessons/lesson<N>_tutorial.ipynb` and `basic_lessons/lesson<N>_exercise_answers.ipynb`
203-
2. Follow the header format convention above
204-
3. Add LaTeX macro raw cell (or markdown cell with `vscode` language metadata)
205-
4. Update `myst.yml` → add new file to `project.toc` list
206-
5. Run `python3 convert_to_myst.py` to regenerate `unstable/`
207-
6. Update `myst.yml` → add new unstable `.md` file to the "Unstable" section in `project.toc`
208-
7. Test: `myst build --html` from the repository root
157+
1. Create `basic_lessons/lesson<N>_tutorial.md` (and optionally `basic_lessons/lesson<N>_exercise_answers.md`)
158+
2. Add YAML frontmatter with kernelspec at the top of the file
159+
3. Follow the header format convention above
160+
4. Use `{code-cell}` directives for Python code blocks
161+
5. Update `myst.yml` → add new file(s) to `project.toc` list
162+
6. Update `basic_lessons/README.md` → add the new lesson to the contents table
163+
7. Test: `./build_html.sh` from the repository root
209164
8. Open PR with descriptive title and body

basic_lessons/README.md

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# The Basics of Kinematic Modelling and Control of Serial-link Manipulators Using `numpy`
22

3-
In this five-lesson tutorial, we start from the very basics of scalar and matricial operations in Python using `numpy`,
3+
In this six-lesson tutorial, we start from the very basics of setting up your Python environment,
4+
then cover scalar and matricial operations in Python using `numpy`,
45
all the way until the basics of kinematic control. Until kinematic control, most is based on [@spong2020robot].
56

67
# Using this book
78

8-
Each lesson is a [Jupyter notebook](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html). Each lesson can be
9+
Each lesson is a [MyST text notebook](https://mystmd.org/guide/notebooks-with-markdown). Each lesson can be
910
opened and executed with popular IDEs, such as [VSCode](https://code.visualstudio.com) and [PyCharm](https://www.jetbrains.com/pycharm/).
1011
The reader is expected to follow it sequentially.
1112

@@ -14,8 +15,19 @@ The reader is expected to follow it sequentially.
1415

1516
| Number | Title and Link | Content |
1617
|--------|------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
17-
| 1 | [](./lesson1_tutorial.ipynb) | Basic operations in Python and `numpy` |
18-
| 2 | [](./lesson2_tutorial.ipynb) | Learn about elements and operations in $\mathbb{R}^n$, $SO(n)$, and $SE(n)$ with $n\in{\{2,3\}}$ related to positions, orientations, and poses, respectively. |
19-
| 3 | [](./lesson3_tutorial.ipynb) | Learn about the composition of rigid body motion in series to obtain the forward kinematics model of a robotic manipulator, mapping their configuration space $\myvec{q}\in\mathbb{R}^n$ into their task space $\myvec{x}\in\mathbb{R}^m$. |
20-
| 4 | [](./lesson4_tutorial.ipynb) | Learn about the first-order differential mapping $\dot{\myvec{x}}=\mymatrix{J}\dot{\myvec{q}}$ between joint space and task space velocities through the calculation of the Jacobian $\mymatrix{J}$. |
21-
| 5 | [](./lesson5_tutorial.ipynb) | Employ the previous knowledge in all previous lessons to employ a Lyapunov-stable control law to move a manipulator in task space using configuration-space signals. |
18+
| 0 | [](./lesson0_tutorial.md) | Setting up the virtual environment and installing all required dependencies. |
19+
| 1 | [](./lesson1_tutorial.md) | Basic operations in Python and `numpy` |
20+
| 2 | [](./lesson2_tutorial.md) | Learn about elements and operations in $\mathbb{R}^n$, $SO(n)$, and $SE(n)$ with $n\in{\{2,3\}}$ related to positions, orientations, and poses, respectively. |
21+
| 3 | [](./lesson3_tutorial.md) | Learn about the composition of rigid body motion in series to obtain the forward kinematics model of a robotic manipulator, mapping their configuration space $\myvec{q}\in\mathbb{R}^n$ into their task space $\myvec{x}\in\mathbb{R}^m$. |
22+
| 4 | [](./lesson4_tutorial.md) | Learn about the first-order differential mapping $\dot{\myvec{x}}=\mymatrix{J}\dot{\myvec{q}}$ between joint space and task space velocities through the calculation of the Jacobian $\mymatrix{J}$. |
23+
| 5 | [](./lesson5_tutorial.md) | Employ the previous knowledge in all previous lessons to employ a Lyapunov-stable control law to move a manipulator in task space using configuration-space signals. |
24+
25+
### Exercise Answers
26+
27+
| Lesson | Link |
28+
|--------|------|
29+
| L1 | [](./lesson1_exercise_answers.md) |
30+
| L2 | [](./lesson2_exercise_answers.md) |
31+
| L3 | [](./lesson3_exercise_answers.md) |
32+
| L4 | [](./lesson4_exercise_answers.md) |
33+
| L5 | [](./lesson5_exercise_answers.md) |
File renamed without changes.

0 commit comments

Comments
 (0)