From acf8b45e9d040902611220a230adc8435c6ae0e6 Mon Sep 17 00:00:00 2001 From: Ysobel Sims <35280100+ysims@users.noreply.github.com> Date: Wed, 4 Oct 2023 11:09:54 +1100 Subject: [PATCH] Updates to the System/Subsystems Section (#294) 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 --- src/book/01-team/05-robocup/01-robocup.mdx | 7 +- src/book/01-team/05-robocup/references.bib | 5 ++ .../02-system/01-foundations/07-director.mdx | 7 +- .../02-system/01-foundations/references.bib | 8 ++ .../02-system/02-subsystems/04-motion.mdx | 87 ++++++++++--------- .../02-system/02-subsystems/06-behaviour.mdx | 55 ++++++++++-- 6 files changed, 120 insertions(+), 49 deletions(-) create mode 100644 src/book/01-team/05-robocup/references.bib create mode 100644 src/book/02-system/01-foundations/references.bib diff --git a/src/book/01-team/05-robocup/01-robocup.mdx b/src/book/01-team/05-robocup/01-robocup.mdx index c0f3d309e..b0e81feee 100644 --- a/src/book/01-team/05-robocup/01-robocup.mdx +++ b/src/book/01-team/05-robocup/01-robocup.mdx @@ -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. @@ -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. robocuphumanoid 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 + + diff --git a/src/book/01-team/05-robocup/references.bib b/src/book/01-team/05-robocup/references.bib new file mode 100644 index 000000000..e36ade20a --- /dev/null +++ b/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}}, +} diff --git a/src/book/02-system/01-foundations/07-director.mdx b/src/book/02-system/01-foundations/07-director.mdx index 973bc6260..7f1539a2b 100644 --- a/src/book/02-system/01-foundations/07-director.mdx +++ b/src/book/02-system/01-foundations/07-director.mdx @@ -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 director2023 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. @@ -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 + + diff --git a/src/book/02-system/01-foundations/references.bib b/src/book/02-system/01-foundations/references.bib new file mode 100644 index 000000000..b89bf99a2 --- /dev/null +++ b/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} +} diff --git a/src/book/02-system/02-subsystems/04-motion.mdx b/src/book/02-system/02-subsystems/04-motion.mdx index 077996b75..376773232 100644 --- a/src/book/02-system/02-subsystems/04-motion.mdx +++ b/src/book/02-system/02-subsystems/04-motion.mdx @@ -10,11 +10,29 @@ 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 | | -------- | ------------------------------------------------------------------------------------------ | @@ -22,7 +40,7 @@ The walk engine will trigger when a [**walkcommand**](https://github.com/NUbots/ | `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 @@ -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>().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( - id, std::vector({"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(load_script("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>().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(load_script("Stand.yaml", NUClear::clock::now() + std::chrono::seconds(5))); -```cpp -emit(std::make_unique(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: @@ -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 ``` @@ -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). | diff --git a/src/book/02-system/02-subsystems/06-behaviour.mdx b/src/book/02-system/02-subsystems/06-behaviour.mdx index 9046033f4..c42def315 100644 --- a/src/book/02-system/02-subsystems/06-behaviour.mdx +++ b/src/book/02-system/02-subsystems/06-behaviour.mdx @@ -8,15 +8,54 @@ authors: - Ysobel Sims (@ysims) --- -The behaviour subsystem includes walk planning, soccer strategies, get up detection, head behaviour, script running and tuning, and kick behaviour. +The behaviour subsystem includes the purpose, strategy and planning layers of the system. These utilise the Director system and will be made up of Providers and Tasks. The behaviour subsystem is responsible for the high-level decision making of the robot. -## Walk Behaviour +## Planning -The [Direct Walk Controller](https://github.com/NUbots/NUbots/tree/main/module/behaviour/skills/DirectWalkController) sends messages to the walk engine. It can send a message to enable or disable the walk engine, stop the walk engine, or send a `WalkCommand` message to the walk engine. +The planning layer is given a straightforward goal and uses mathematics to determine how to achieve that goal using skills. These skills are generally [motions](/system/subsystems/motion), such as kicking, walking and getting up. Examples of planners are the [walk path planner](#walk-path-planner) and the [kick planner](#kick-planner). + +### Walk Path Planner + +There are three main walk path planners. Each are Providers and emit `Walk` Tasks. + +- `WalkTo`: This planner is given a vector position and heading to walk to in robot space. It moves towards the position linearly and rotates to reach the given heading. As it approaches the position to walk to, it decelerates so it stops smoothly. +- `TurnOnSpot`: This planner is given a direction to rotate (clockwise or anti-clockwise) and rotates in that direction on the spot. +- `TurnAroundBall`: This planner assumes the ball is in front of the robot and pivots around it so that the ball is still in front of the robot. It is given a direction to rotate (clockwise or anti-clockwise). This is useful for aligning the robot with the ball and a target, ie the ball or a teammate. + +### Kick Planner + +The kick planner checks if the ball is close enough to kick and if we are aligned towards our target, ie goal or teammate. When these conditions are satisifed, it emits a `Kick` Task. + +### Look Planner + +Looking does not often need planning functionality behind it, as a vector to look to can be given directly to the skill. We do implement a `LookAround` planner that oscillates between points given from the module's configuration file. This is useful for looking around the field for the ball. + +## Strategy + +The strategy modules contain a high-level request that utilises environment information and the planning layer to achieve its goal. The `module/strategy` folder contains these strategies. We list some of these with their functions below. + +- `StandStill`: uses the walk engine to stand still. +- `FindBall`: if the ball is not visible, uses the look and walk planners to find it +- `WalkToBall`: uses ball localisation to emit a Task to the walk path planner. +- `LookAtBall`: uses ball localisation to emit a Task to the look planner to look at the ball. +- `KickToGoal`: uses field localisation to determine when to emit a Task to the kick planner. +- `AlignToGoal`: uses field localisation to determine when to emit a Task to the walk path planner to pivot around the ball to face the goal. + +## Purpose + +The purpose layer determines the overall goal of the robot. For soccer-playing, it contains the logic for soccer positions. These modules form the root of the Director tree. + +### Soccer + +The Soccer purpose uses GameController information to determine how to act. If it is penalised, then it stands still. If it is not penalised, it determines whether to play as a striker, defender or goalie. + +- Striker: An offensive position that attempts to score goals by moving towards the ball and kicking to the goal. +- Defender: A defensive position that attempts to prevent the opponent from scoring goals by moving towards the ball and kicking it away from the goal if the ball is in our half. +- Goalie: A defensive position that attempts to prevent the opponent from scoring goals by staying in the goal area and diving towards the ball if the opponent tries to score. ### Keyboard Walk -The [keyboardwalk module](https://github.com/NUbots/NUbots/tree/main/module/behaviour/strategy/KeyboardWalk) is used for **testing** and **demonstration** purposes. Keyboard walk can use any of the walk engines in the codebase, and acts as an interface for any one of them. +The [keyboardwalk module](https://github.com/NUbots/NUbots/tree/main/module/behaviour/strategy/KeyboardWalk) is a purpose-level module used for **testing** and **demonstration** purposes. Keyboard walk can use any of the walk engines in the codebase, and acts as an interface for any one of them. Keyboard walk uses **keyboard inputs** to control the robot. The inputs available are detailed in the following table. @@ -61,9 +100,9 @@ The module connects to the PS3 controller using bluetooth (or USB) and reacts ba To use this module, build the [PS3Walk role](https://github.com/NUbots/NUbots/blob/main/roles/ps3walk.role) and run the binary. Plug the PS3 controller into the robot using a USB cable. When the controller is connected to the robot, it will be paired, and you can remove the cable. -## Script Runner +### Script Runner -[ScriptRunner](https://github.com/NUbots/NUbots/tree/96357855b059cd499021552b3e25a4b158828dc5/module/behaviour/tools/ScriptRunner) is a module in the behaviour subsystem. It takes the name of one or more script files as arguments and attempts to run the scripts. It does not take file paths, only the file name/s of the script/s to execute. Any role with the ScriptRunner module must also contain the [ScriptEngine](/system/subsystems/motion#script-engine) module. +[ScriptRunner](https://github.com/NUbots/NUbots/tree/96357855b059cd499021552b3e25a4b158828dc5/module/behaviour/tools/ScriptRunner) is a purpose-level module. It takes the name of one or more script files as arguments and attempts to run the scripts. It does not take file paths, only the file name/s of the script/s to execute. When ScriptRunner is executed, it stores the script file names passed to it as a vector of strings. When the green button on the robot is pushed, the scripts are executed in order of appearance, one after the other. ScriptRunner also provides an option to set a delay before the execution of the first script, as well as a delay between the execution of each script. @@ -73,9 +112,9 @@ An example of using ScriptRunner to run a script called `Stand.yaml` is: ./scriptrunner Stand.yaml ``` -## Script Tuner +### Script Tuner -[ScriptTuner](https://github.com/NUbots/NUbots/tree/96357855b059cd499021552b3e25a4b158828dc5/module/behaviour/tools/ScriptTuner) is a module in the behaviour subsystem. Using a command-line argument, it can either create a new script or open an existing script for editing. It uses [curses]() to create a user interface in the terminal. Through this user interface, YAML files are created or edited that specify a script that can then be used by other modules. +[ScriptTuner](https://github.com/NUbots/NUbots/tree/96357855b059cd499021552b3e25a4b158828dc5/module/behaviour/tools/ScriptTuner) is a purpose-level module. Using a command-line argument, it can either create a new script or open an existing script for editing. It uses [curses]() to create a user interface in the terminal. Through this user interface, YAML files are created or edited that specify a script that can then be used by other modules. A script consists of frames (also called targets) which specify the position of one or more servos at a given time. The ScriptTuner interface allows for stepping through and modifying those frames. When a frame is selected in ScriptTuner, a ServoCommand for that frame will be emitted to the robot. By stepping through multiple frames, the entire script can be played back on the robot, allowing the user to preview changes to the script.