Skip to content

Commit

Permalink
Updates to the System/Subsystems Section (#294)
Browse files Browse the repository at this point in the history
This PR updates the subsystems section of NUbook inline with what is
current. The motion and behaviour pages were very out of date after
moving to the Director.

I've also put in a couple of fixes for references that didn't use the
NUbook bibtex referencing system.

### Preview


<https://deploy-preview-294--nubook.netlify.com/system/subsystems/motion>

<https://deploy-preview-294--nubook.netlify.com/system/subsystems/behaviour>
  • Loading branch information
ysims committed Oct 4, 2023
1 parent eadde05 commit acf8b45
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 49 deletions.
7 changes: 6 additions & 1 deletion src/book/01-team/05-robocup/01-robocup.mdx
Expand Up @@ -6,6 +6,7 @@ description: Introduction to the RoboCup competition.
slug: /team/robocup
authors:
- Ysobel Sims (@ysims)
references: references.bib
---

RoboCup is an annual international robotics competition with the aim of promoting AI and robotics research, by offering a publicly appealing, but formidable challenge. The first RoboCup games where held in 1997 in Nagoya, Japan with 38 teams participating from 11 countries.
Expand All @@ -30,10 +31,14 @@ RoboCupSoccer has five leagues:
- Small Size
- Simulation

The Humanoid League is used to research and investigate dynamic walking and running, kicking the ball with balance and stability, visual perception of the ball, other players, and the field, self-localization, and team play, strategy, etc. [[1]](https://www.robocup.org/leagues/3 'Reference: RoboCup Humanoid League')
The Humanoid League is used to research and investigate dynamic walking and running, kicking the ball with balance and stability, visual perception of the ball, other players, and the field, self-localization, and team play, strategy, etc. <cite>robocuphumanoid</cite>

The Humanoid League is organized into three categories, based on the robot size: Kids Size, Teen Size and Adult Size.

Previously, we competed in the Four Legged League (2002-2007), the Standard Platform League (2008-2011), the Humanoid KidSize League (2012-2017), and the Humanoid TeenSize League (2018-2019). With the removal of the Humanoid TeenSize League after the 2019 competition, NUbots returned to the Humanoid KidSize League (2021-2023). Due to COVID-19, no competition was held in 2020.

NUbots became the Four Legged League world champions in 2006 in Germany. NUbots, in collaboration with the National University of Maynooth from Ireland, won the first Standard Platform League in 2008, as team NUManoid in Suzhou, China.

## References

<References />
5 changes: 5 additions & 0 deletions src/book/01-team/05-robocup/references.bib
@@ -0,0 +1,5 @@
@misc {robocuphumanoid,
title={RoboCup Humanoid League},
url={https://www.robocup.org/leagues/3},
author={{RoboCup Federation}},
}
7 changes: 6 additions & 1 deletion src/book/02-system/01-foundations/07-director.mdx
Expand Up @@ -7,9 +7,10 @@ slug: /system/foundations/director
authors:
- Trent Houliston (@TrentHouliston)
- Ysobel Sims (@ysims)
references: references.bib
---

The Director [[1]](https://arxiv.org/abs/2309.09248) is a framework and algorithm used to control the flow of behaviour on the robots.
The Director <cite>director2023</cite> is a framework and algorithm used to control the flow of behaviour on the robots.
It allows composable behaviours that can take advantage of transition rules to ensure that the robot performs the right task at the right time.

The Director does this by providing a set of new DSL keywords to NUClear that describe what tasks to run, what conditions are required, and how those tasks build on other tasks.
Expand Down Expand Up @@ -440,3 +441,7 @@ Modules in this layer include
- Sequences: Takes a sequence of servo positions and emits them in order
- Groups: Takes a group of servos and emits them together, will only emit Done when all servos are done
- Servos: Takes a single servo and emits it, will only emit Done when the time the servo has to move is over
## References
<References />
8 changes: 8 additions & 0 deletions src/book/02-system/01-foundations/references.bib
@@ -0,0 +1,8 @@
@misc{director2023,
title={The Director: A Composable Behaviour System with Soft Transitions},
author={Ysobel Sims and Trent Houliston},
year={2023},
eprint={2309.09248},
archivePrefix={arXiv},
primaryClass={cs.RO}
}
87 changes: 48 additions & 39 deletions src/book/02-system/02-subsystems/04-motion.mdx
Expand Up @@ -10,19 +10,37 @@ authors:

This page details motion modules within the NUbots main codebase, such as the walk engine and the script engine. Information about modules for running and tuning scripts can be found on the [Behaviour](/system/subsystems/behaviour#script-runner) page.

## Actuation

Actuation is the process of moving the robot's joints. The robot has 20 joints, each with a servo motor. The actuation layer is implemented within the Director system. A Provider for each servo and each limb exists so that only one higher level Provider can take control of a particular servo or limb at a time. If the walk has control of the leg, the kick cannot also take control of the leg. If the kick has a higher priority than the walk, the walk will lose control of the leg and the kick will take control.

```dot
# Actuation layer. The first level are the Inverse Kinematics Providers, the second level are the Group/Limb Providers, and the third level are the Servo Providers.
digraph actuation {
rankdir=LR
"Left Leg IK" -> "Left Leg" -> {"Left Hip Yaw", "Left Hip Roll", "Left Hip Pitch", "Left Knee", "Left Ankle Pitch", "Left Ankle Roll"}
"Right Leg IK" -> "Right Leg" -> {"Right Hip Yaw", "Right Hip Roll", "Right Hip Pitch", "Right Knee", "Right Ankle Pitch", "Right Ankle Roll"}
"Head IK" -> "Head" -> {"Head Yaw", "Head Pitch"}
}
```

The Groups level also includes the Body, Limbs, Legs and Arms Groups. These are more commonly used in the system in the context of Sequences with Scripts.

Sequences contain a list of Group commands that are to be executed sequentially. Once a Director `Done` is received from every servo in the group, then the frame is completed and the next set of commands in the sequence are requested. This concept is the driving force behind the script system.

## Walk Engine

NUbots use an **open loop walk** based on **quintic splines**. This walk engine takes care of the mathematics and control involved in taking steps without falling over. The walk engine does not plan where to walk, only how to walk.

The walk engine will trigger when a [**walkcommand**](https://github.com/NUbots/NUbots/blob/main/shared/message/motion/WalkCommand.proto) is [**emitted**](/system/foundations/nuclear#emit-statements). The walk command gives a vector `[x, y, z]` which represents:
The walk engine will trigger when a [**Walk message**](https://github.com/NUbots/NUbots/blob/main/shared/message/skill/Walk.proto) is [**emitted**](/system/foundations/nuclear#emit-statements) in the [Director system](/system/foundations/director). The walk command gives a vector `[x, y, z]` which represents:

| Variable | Description |
| -------- | ------------------------------------------------------------------------------------------ |
| `x` | velocity in metres per second in the direction of the x axis |
| `y` | velocity in metres per second in the direction of the y axis |
| `z` | yaw in radians per second, positive is counter-clockwise. The 0 point is straight forward. |

The robot's [behaviour](/system/subsystems/behaviour) determines the walk command.
The robot's [behaviour](/system/subsystems/behaviour) determines the walk vector.

### Quintic Spline Walk

Expand Down Expand Up @@ -63,59 +81,50 @@ The `TrajectoryUtils` file uses the `SplineContainer` for walking and kicking. I

The points that make up all these splines are in the [WalkEngine.cpp file](https://github.com/NUbots/NUbots/blob/889d5ec2e91b2dc0ab7be59429e3c21b786b7b65/module/motion/QuinticWalk/src/WalkEngine.cpp#L271). The [configuration parameters](https://github.com/NUbots/NUbots/blob/main/module/motion/QuinticWalk/data/config/QuinticWalk.yaml) affect some of these points. Values are all in [SI units](https://en.wikipedia.org/wiki/International_System_of_Units).

## Script Engine
### Improved Quintic Spline Walk

Scripts are static motions for the robot. They specify what joint angles to move to and how long the robot should take to get to those joint angles. For example, standing up is a script telling the robot to move its joints to the stand position over one second. There can be many of these position specifications in sequence to make the robot do more complex movements like getting up or kicking.
We currently use a modified version of the original quintic walk. The new version is highly simplified and uses different logic for the timing and placement of the torso and feet. It uses the `FootController` module to align the feet with the ground.

To learn how to tune scripts, see the [ScriptTuner guide](/guides/main/tuning-and-running-scripts#script-tuner).
```dot
# The walk pipeline
digraph walk {
"Path Planner" -> "Walk" -> "Foot Controller" -> {"Left IK", "Right IK"}
"Servos..." [style=dashed]
"Left IK" -> "Left Leg" -> "Servos..."
"Right IK" -> "Right Leg" -> "Servos..."
}
```

### Messages
## Kick Engine

To execute a script, we emit an "execute script" message describing the script to execute. This message is received in the ScriptEngine, which executes the appropriate script. These are specified in [Script.h](https://github.com/NUbots/NUbots/blob/96357855b059cd499021552b3e25a4b158828dc5/shared/extension/Script.h) as [ExecuteScriptByName](https://github.com/NUbots/NUbots/blob/96357855b059cd499021552b3e25a4b158828dc5/shared/extension/Script.h#L224) and [ExecuteScript](https://github.com/NUbots/NUbots/blob/96357855b059cd499021552b3e25a4b158828dc5/shared/extension/Script.h#L261).
The kick engine is based off the improved quintic spline walk engine. Splines are created for the torso and kicking foot movements based on configuration values. It is open loop and has similarities to a scripted kick, with a simplified tuning process and spline interpolation rather than linear interpolation.

`ExecuteScriptByName` takes
## Scripts

- a subsumption ID (this is used to determine servo access priority)
- the name of the script/s as a string or a vector of strings
- the duration of the scripts
- the time that these scripts should start executing
Scripts are static motions for the robot. They specify what joint angles to move to and how long the robot should take to get to those joint angles. For example, standing up is a script telling the robot to move its joints to the stand position over one second. There can be many of these position specifications in sequence to make the robot do short movements that may be hard to dynamically implement, such as getting up.

An example of receiving this message is in [ScriptEngine.cpp](https://github.com/NUbots/NUbots/blob/96357855b059cd499021552b3e25a4b158828dc5/module/motion/ScriptEngine/src/ScriptEngine.cpp#L51).
To learn how to tune scripts, see the [ScriptTuner guide](/guides/main/tuning-and-running-scripts#script-tuner).

```cpp
on<Trigger<ExecuteScriptByName>>().then([this](const ExecuteScriptByName& command) {...}
```
### Execution

An example of emitting this message is in [KickScript.cpp](https://github.com/NUbots/NUbots/blob/96357855b059cd499021552b3e25a4b158828dc5/module/behaviour/skills/KickScript/src/KickScript.cpp#L102)
To execute a script, we emit a Director Task message with the appropriate servo Sequence containing the script information. This script information comes from the `load_script` function in the `script` utility.

```cpp
emit(std::make_unique<ExecuteScriptByName>(
id, std::vector<std::string>({"Stand.yaml", "KickRight.yaml", "Stand.yaml"})));
```
The `load_script` function takes a YAML file name (eg `Stand.yaml`), finds and reads the file and creates a servo Sequence representing the script. The Sequence is returned and emitted as a Director Task. The Director Task is then executed by the Director system.

Note these are only the names of the scripts, not the full paths. The names correspond to the names of YAML files in the [scripts folder](https://github.com/NUbots/NUbots/tree/16b4b20faf69c2c12b52e9ffd28c546a612dc033/module/motion/ScriptEngine/data/scripts).
```
In addition to using the name of a script, we can also use [an instance of Script](https://github.com/NUbots/NUbots/blob/96357855b059cd499021552b3e25a4b158828dc5/shared/extension/Script.h#L43) directly. `Script` can be instantiated with all the information for the script to execute, and can be emitted using the `ExecuteScript` message. `ExecuteScript` takes:
emit<Task>(load_script<BodySequence>("Stand.yaml"));
- a subsumption ID (this is used to determine servo access priority)
- a Script or vector of Scripts
- the duration of the scripts
- the time that these scripts should start executing
```

An example of receiving this messages is in [ScriptEngine.cpp](https://github.com/NUbots/NUbots/blob/96357855b059cd499021552b3e25a4b158828dc5/module/motion/ScriptEngine/src/ScriptEngine.cpp#L71)
Scripts can be given a start time. If a script has a start time, it will not start execution until that time. The following would execute the `Stand` script in five seconds.

```cpp
on<Trigger<ExecuteScript>>().then([this](const ExecuteScript& command) {...}
```
An example of emitting this message is in [ScriptTuner.cpp](https://github.com/NUbots/NUbots/blob/96357855b059cd499021552b3e25a4b158828dc5/module/behaviour/tools/ScriptTuner/src/ScriptTuner.cpp#L590)
emit<Task>(load_script<BodySequence>("Stand.yaml", NUClear::clock::now() + std::chrono::seconds(5)));
```cpp
emit(std::make_unique<ExecuteScript>(id, script, NUClear::clock::now()));
```

The [ScriptEngine](https://github.com/NUbots/NUbots/tree/96357855b059cd499021552b3e25a4b158828dc5/module/motion/ScriptEngine) module receives either of these messages and processes the information for the script. It collects the servo positions and time for each frame and modifies them if needed based on the given duration and start time in the message. The information is then emitted as a [ServoCommand](https://github.com/NUbots/NUbots/blob/cbb5d3ebc2a7c56944ec9afe3f70faf7e2900217/shared/message/behaviour/ServoCommand.proto) message.

### Script files

The script files are YAML files specifying a duration and list of servo targets, in a format like the following:
Expand All @@ -125,15 +134,15 @@ The script files are YAML files specifying a duration and list of servo targets,
targets:
- id: HEAD_YAW
position: 0
gain: 30
gain: 10
torque: 100
- id: HEAD_PITCH
position: 0.5
gain: 30
gain: 10
torque: 100
- id: R_HIP_YAW
position: -0.03
gain: 20
gain: 5
torque: 100
```

Expand All @@ -143,7 +152,7 @@ The fields are described in the table below.
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `duration` | An integer in milliseconds. |
| `position` | A float representing the angle of the servo in radians. |
| `gain` | A float representing how much effort the servo will use to get to the target position. Gain is often between 10 and 30. |
| `gain` | A float representing how much effort the servo will use to get to the target position. Gain is often between 5 and 15. |
| `torque` | A float, where 0 represents no torque and 100 represents torque being on. Torque is 100 unless you want that servo relaxed, in which case it will be 0. |
| `id` | One of the servo IDs listed in [ServoID.h](https://github.com/NUbots/NUbots/blob/467f458c687419056e2487fe468c7f22d19a6965/shared/utility/input/ServoID.h#L30). |

Expand Down

0 comments on commit acf8b45

Please sign in to comment.