- version: 2024.0.1
- status: used for FRC 2024 Crescendo, 2023 Charge Up, 2022 Rapid React, and 2021 Infinite Recharge at home
- comments: We believe this is competition-ready (i.e. we've used this for competition since the 2020-2021 season). This release adds ring field elements, and improved documentation.
- related releases:
- a05annexUtil - the utility library that supports various A05annex projects including this swerve path planner and all of our robot competition code.
- a05annexRobot - our common robot code that includes the MK4 swerve base, NavX, driver and autonomous selection switch panel, autonomous path and driver commands, camera, etc.
- a05annexTemplate - our template, built on the wpilib template that provides a driveable swerve base with NavX, camera, autonomous path and driver selection.
This project is a visual 2D editor for path planning for a swerve drive FRC robot. You read a field description and robot description into this planner as a context for path planning; then draw, tune, add commands, and save paths that can be used as the autonomous programs for a match.
A05annex is committed to using the internationally recognized SI units, so the field, robot, and path descriptions, and path points are in SI units. The +Y axis is always downfield from the driver (as Y is the forward/backward axis of control sticks and the vertical or forward axis when the field map is laid down in front of the driver), Specifically, the driver is at the bottom of the screen. The +X axis is always to the right (common engineering convention). We adopted the convention that the center of the competition field is (0.0,0.0) for red-blue alliance symmetry; and that the left corner closest to the driver is 0,0 for the 2021 at Home field - both of which are reflected in our field descriptions for the 2021, 2022, and 2023 competitions.
version 0.9.6 to 2024.?.? (for 2024 Crescendo):
- version 0.9.6 - added 2024 Crescendo field description, and 2024 robot descriptions;
- version 2024.0.1 - revised version numbering to be consistent with FRC versioning that uses the year as the base. Added documentation for ring shape (for the 2024 note game piece).
version 0.9.0 to 0.9.5 (for 2023 Charged Up):
- added 2023 Charged Up field description, and 2023 robot descriptions;
- added scale for field components to support mirroring the red and blue side of the field;
- added dialog editing of the rotation speed at control points. There is currently no interactive graphical editing of rotation because we have not found a good way to present an editing handle for rotation speed;
- Fixed a timing issue that sometimes threw exceptions when path animation started;
- Fixed error in path point info dialog where Field Y was incorrectly reporting field X, added X, Y, and rotation speed to the reported path point information;
- added saved Idea run configurations;
- improved user documentation.
version 0.8.0 to 0.9.0 (for 2022 Rapid React):
- added stop-and-run commands for control points and scheduled commands for path points. See Running Commands Along The Path;
- robots often have appendages, like a collector or hangar, that extend past to robot periphery and must be considered in path planning - appendages were added to the Robot Description;
- while there is an 'FRC standard field', different competitions like 2020 Infinite Recharge, 2021 At Home, and 2022 Rapid React have configured this to different sizes and/or restricted the portion of the field where autonomous action can happen. To adapt, we moved the field boundary description from the Swerve Path Planner constants to the Field Description as the "arena" description. The -ah command argument was removed because field extents are now in the field description rather than programmed. All field descriptions in ./resources/fields have been updated to include an "arena" description;
- minor changes for better interactive editing feedback and response.
We have finally packaged this as a runnable .jar file. So you now have the option to:
- Download and run from the .jar file;
- Clone the project and run from an IDE, which gives you all of our field, robot, and path data files for reference.
In github you will find an 2024.0.1 release of the SwervePathPlanning-2024.0.1-all.jar which you can run at the command line as:
% java -jar SwervePathPlanning-2024.0.1-all.jar
See notes in the next section about command line arguments. While this is a running program, it lacks data for field, robot, or path descriptions; so, you may want to clone the project (or just download and expand the .zip just so you have all of our past field, robot, and path descriptions as sample data.
Even though we have packaged this as a runnable .jar file, you may want to
clone the repository and open it in your favorite IDE (Intellij IDEA or
Visual Studio) and create a run target for ServePathPlanner
(if you are using Idea, the run targets
will be loaded when you load the project). The gradle build file will resolve the
dependencies, build, and run the program.
When you run the program it will initialize with a default view of the most recent competition field
without any field elements. You can add some
commandline arguments to the run target to get your desired field and robot to load automatically.
Run with the -h
or --help
command line option to get program help:
usage: PathPlanner [-h] [-r ROBOT] [-f FIELD]
Swerve Drive Path Planner
named arguments:
-h, --help show this help message and exit
-r ROBOT, --robot ROBOT specify a robot description file
-f FIELD, --field FIELD specify a field description file
Our fields, robots, and paths from previous years are in the resources folder of the project.
The path planner uses an implementation of the Kochanek-Bartels Spline modified for interactive editing of the tangent vector to implicitly control bias and tension. There is no continuity control because we want our robot paths to be continuous. The original reference for this spline can be found at Interpolating Splines with Local Tension, Continuity, and Bias Control.
When control points are created the tangent (derivatives) at that control point and surrounding control points are computed/recomputed using the [Cardinal-Spline](https://en.wikipedia.org/wiki/Cubic_Hermite_spline) formulation with the default tension specified by a program constant. The tangent is adjusted using a control handle which intuitively manipulates the shape of the spline at the control point to implicitly edit tension and bias.
A path is created by dropping successive control points along the path onto the diagram of the field. Once the control points have been dropped, the path is edited and adjusted by: modifying positions and path derivatives at the control points; adding control points; removing control points; and attaching action commands to the path.
When the path planner is started it shows, by default, the full 2022 field boundary with no field elements (see Field Description for loading a specific field and elements); and will use a default robot chassis that is 0.9m long and 0.5m wide; and 1.1m long amd 0.7m long with bumpers (see Robot Description for loading a description of your robot).
The display starts in path creation mode. Each time you click on the field a control point will be created at that position. A double-click will end the path at the control point created there and switch to path edit mode. Alternately, you can right-click to get a context-sensitive menu, and select End Path to end the path at the last created control point, and switch to path edit mode.
An animation of the robot following the path can be played in two ways:
- From the main menu, under Path, select Play Path
- From the context menu (right-click anywhere to get the context menu), select Play Path
Once you create a path, really a first guess at the path by dropping a few control points, you go immediately
into path tuning (editing). Generally, the questions and adjustments are around:
- Is this really the path I meant, and, can I fix it?;
- Is the robot capable of following the path, and if not, how do I fix it?;
- Is the robot facing the right direction, and if not, how do I fix it?;
- How do I tell the robot to do something in addition to following the path?;
- How can I optimize timing or speed for a faster (better) path?
Expand this section to get answers for these questions.
A control point is a position on the field that the path will pass through at a specified time with a specified velocity, direction, and rotation speed. Each time you drop a new control point it is, by default, 1 second further along the path than the last control point. At the control point you will see editing handles for: position on the field; direction and velocity; and field orientation of the robot as shown below.
As you move the cursor you will always get the field position feedback with the cursor. If you are over an editing handle, the handle will be surrounded by a green circle. In the figure above, the cursor is above the control point position handle. When you are above a handle (it has a green circle) you can left-click and drag the handle to edit that parameter (field position, direction and velocity, robot heading) at that control point.
NOTE that as you edit the control point, the robot path will reflect those edits. The robot path will be colored to describe things you should consider:
- white - this is a valid robot path;
- red - this path is asking the robot to perform beyond its capabilities - specifically, you are asking at least one module to go faster than is possible;
- orange - this path is in danger of crashing (or will crash) into the field perimeter.
We all do some testing, drop some points, create a path, and say "Good experiment, delete that and let's start over". This is how we do that:
- From the main menu, under Path, select Clear Path
- From the context menu (right-click anywhere to get the context menu), select Clear Path
There are 2 primary approaches to reshaping a path:
- Edit (move, change direction and/or velocity and heading) at control points of the existing path;
- Add or remove control points.
In the previous What is a Control Point section, the handles are your way to interactively edit the curve around a control point. Specifically:
- position handle - moves the control point, the point the path goes though, on the field;
- direction/velocity handle - shapes the curve around the point;
- robot heading handle - changes the heading of the robot as it goes through that control point.
Often you will find that as you edit and reshape your path you will be moving too many control points and want to delete control points that are superfluous; or, You need finer control somewhere along the path, and you want to add a control point. Here is how you do that:
- Removing a Control Point:
- right click on the field position handle of the control point;
- from the context menu, select Delete Control Point. The control point will be deleted, and the timing for all other control points will remain unchanged.
- Adding a Control Point:
- right click on the path point where you wnt to add a control point;
- from the context menu, select Insert Control Point. A control point will be added at that path point with the timing and other parameters of that path point. This should produce minimal disturbance of the current path and give you additional control point for path tuning.
There are 2 ways to adjust path timing:
- Re-time a control point in the path;
- Re-time the entire path.
When you initially drop control points to define a path, each new control point is set to be 1 second from the last. Often, you will need a couple control points close together to control motion around some field obstacle, and the 1 second spacing between control points is not at all what you want. You can change the time for an individual control point, which will reset the timing for all subsequent points so they have the same relative timing.
For example, suppose my robot needs to move forward 2m, then take a .25m left jog, and move forward again. I create a path with a start point, a 2nd control point immediately before the jog, a 3rd control point immediately after the jog, and then a 4th control point another 2m forward. These 4 points are assigned an initial timing of 0sec, 1sec, 2sec, and 3sec respectively. When you play the path you will see the robot slow to a crawl between control points 2 and 3 - not at all what you wanted.
What you really want is for control points 2 and 3 to be closer together in time so the robot maintains its speed as it makes the jog, so instead of control point 3 being crossed in 2sec, you want to cross it in 1.3sec. Let's change the time the robot crosses point 3 to 1.3sec:
- right click on the field position handle of the 3rd control point;
- from the context menu, select Info, this will bring up a control point information dialogue;
- in the control point information dialogue, edit the At Time from 2 to 1.3, and apply this change. The 3rd control point and all subsequent points have now had their time adjusted, which should be reflected when you play the path.
It is common to start path planning with a path that is slower than the best the robot could achieve to make tuning easier, and make it less damaging to the robot and test arena if the path does not go as expected. Once the path is working pretty well, we often want to turn up the speed and continue to tune until we get maximum robot performance. The path planner provides a speed multiplier to accommodate this need. The speed multiplier defaults to 1.0. To change the speed multiplier, from the main menu, under Path select Speed Multiplier to bring up a dialogue for changing the multiplier.
Note that when you change the speed multiplier, the red path highlights for paths that are beyond the capability of the robot will change to reflect the new speed profile, encouraging you to tune control points to keep the path within the robot capabilities.
In the 2021 At Home Challenges, the obstacle course challenges merely required a path. For the 2022
Rapid React competition it became obvious we needed the paths to include other actions (commands) that needed to
run at various points on the path (like start/stop-collector, or aim-and-shoot). So the
AutonomousPathCommand
run on the robot is really a dynamically configured (configured when the path is
executed) Command Group.
Two types of commands are supported:
- A Command that is scheduled to execute at a specif point along the path the robot is following, e.g.
start/stop the collector rollers;
- A command that happens at a control point where the robot stops, the path follower relinquishes
control of the swerve drive, and path following resumes at the completion
of the command. An example of this would be a command that aims the shooter at a target, spins-up
the shooter rollers, and takes a shot.
To be written
To be written
Paths are saved in .json
files that can be loaded to the robot for execution by the
AutonomousPathCommand
.
The path is saved as a list of control points in a dictionary with these keys:
- "title": (optional, string) A title or name for the path, primarily used as file documentation to refresh you on the path this file represents.
- "description": (optional, string) A more verbose description if the path, again primarily used as file documentation to refresh you on the path this file represents.
- "controlPoints": (required, list) The list of control points. A control point is a dictionary
containing these fields:
- "fieldX": (optional, double, default=0.0) The field X position in meters.
- "fieldY": (optional, double, default=0.0) The field Y position in meters.
- "fieldHeading": (optional, double, default=0.0) The field heading in radians.
- "time": (optional, double, default=0.0) The time at which this control point should be reached.
- "derivativesEdited": (optional, boolean, default=false) Whether the derivatives of the
control point velocities have been explicitly set (usually by manipulating the direction/velocity handle for
the control point). If
false
, then the X,Y velocities at the control point are set algorithmically at load and when the control point is moved. Iftrue
then the X,Y velocities specified here are used for the control point. - "field_dX": (optional, double, default=0.0) The field X velocity in meters per second.
- "field_dY": (optional, double, default=0.0) The field Y velocity in meters per second.
- "HeadingDerivativeEdited": (optional, boolean, default=false) Whether the derivative of the
control point heading has been explicitly set. If
false
, then the heading derivative at the control point is set algorithmically. Iftrue
then dHeading specified here is used for the control point. - "field_dHeading": (optional, double, default=0.0) The field angular velocity in radians per second. Currently, ignored as the derivative is always generated from the headings of the adjacent control points.
- "robotActionCommand": (optional, string) The action command to run once the robot stops at this control point. This command may require the a05annex/src/subsystems/DriveSubsystem. If this command does not finish, the rest of the path will not be run. If not specified, no robot action will be run at this control point.
- "robotActionDuration": (conditional, double) Required if robotActionCommand is specified. This is the expected duration (in seconds) of the robotActionCommand and is used only in the pat planner to pause path following at the control point for this time in order to simulate the actual timing when the path is played for planning.
- "speedMultiplier": (optional, string, default=1.0) The speed multiplier for the path. If greater than 1.0 the robot will be moving faster along the path.
- "robotScheduledActions": (optional, list) The list of scheduled actions. A scheduled action is a
dictionary containing these fields:
- "robotActionCommand": (required, string) The action command to be scheduled at robotScheduledActionTime. This command must not require the a05annex/src/subsystems/DriveSubsystem.
- "robotScheduledActionTime": (required, double) The time along the path when the robotActionCommand will be scheduled to run.
This is the path description for a 2m diameter calibration path (see the
./resources/paths/test_circle_2m.json
path):
{
"description": "2m diameter test circle.",
"title": "The path for a 2 meter diameter test circle with the robot facing the center of the circle.",
"controlPoints": [
{
"fieldY": 0.0,
"fieldX": 0.0,
"fieldHeading": 0.0,
"time": 0.0
},
{
"fieldY": 1.0,
"fieldX": -1.0,
"fieldHeading": 1.5708,
"time": 1.0
},
{
"fieldY": 2.0,
"fieldX": 0.0,
"fieldHeading": 3.1416,
"time": 2.0
},
{
"fieldY": 1.0,
"fieldX": 1.0,
"fieldHeading": 4.7124,
"time": 3.0
},
{
"fieldY": 0.0,
"fieldX": 0.0,
"fieldHeading": 6.2832,
"time": 4.0
}
]
}
When loaded into the path planner, the path looks like this:
Note that the path is defined using positions, velocities, and time. When the path is processed by the robot code that information is translated to drive commands.
To be written.
The robot is described in a .json
file read into the path planner and displayed as the robot during
the path planning, as well as providing the drive geometry and max speed for the modules of the swerve
drive.
Having a good description of the robot is helpful in identifying when the planned path exceeds the
capability of the robot (i.e. it just cannot go that fast), and detecting collisions or near collisions
between the robot and game elements.
The robot description has "title" and "description" elements, and the actual geometry of the robots is divided into 4 sections:
- "title": (optional, string) A title or name for the robot, primarily used as file documentation to refresh you on the robot this file represents.
- "description": (optional, string) A more verbose description if the robot, again primarily used as file documentation to refresh you on the robot this file represents.
- "drive": (optional, dictionary) describes the geometry of the drive
- "length": (optional, double, default=0.7) The length of the drive (pivot axis to pivot axis) in meters.
- "width": (optional, double, default=0.3) The width of the drive (pivot axis to pivot axis) in meters.
- "maxSpeed": (optional, double, default=3.0) The maximum module speed (meters/sec)
- "chassis": (optional, dictionary) describes the geometry of the chassis (it is currently assumed the drive
and chassis share the same centroid)
- "length": (optional, double, default=0.9) The length of the chassis in meters.
- "width": (optional, double, default=0.5) The width of the chassis in meters.
- "bumpers": (optional, dictionary)
- "length": (optional, double, default=1.1) The length of robot with bumpers in meters.
- "width": (optional, double, default=0.7) The width of the robot with bumpers in meters.
- "appendages": (optional, dictionary)
This is a robot file which describes our 2023 competition swerve base:
{
"title": "2023 competition base.",
"description": "This is the black anodized competition base for 2023 A05 annex, FRC team 6831",
"drive": {
"length": 0.5461,
"width": 0.5461,
"maxSpeed": 3.136
},
"chassis": {
"length": 0.712,
"width": 0.712
},
"bumpers": {
"length": 0.8636,
"width": 0.8636
}
}
Note that the only use for drive.maxSpeed is in determining whether the robot is capable of executing the specified path.
The field is described in a .json
file read into the path planner and displayed as the background
field context during path planning.
The Path Planner initializes displaying the field axes ([0.0,0.0] is center field),
and the standard field outline. The field description adds the game elements for the season-specific game, and
may change the field outline and display the portion of the field that is of interest in path planning.
To simplify field description there are sections of the description for;
- field arena where you describe field outline and the view that is of interest in autonomous path planning
- game components where you describe game elements like the scoring pieces, scoring targets, scoring piece depots, etc.;
- and a field section that lets you position components and describe which alliance (if any) they belong to.
The field is described in a .json file read into the planner and displayed as the context for planning move paths. The field description file has 4 main elements:
- "title": (optional, string) A title or name for the field, primarily used as file documentation to refresh you on the field this file represents.
- "description": (optional, string) A more verbose description if the field, again primarily used as file documentation to refresh you on the field this file represents.
- "arena": (optional, dictionary) a description of the arena bounds and view that is of interest. if
not specified, the default *"field" is the 2022 field, and the default "view" is the
entire field.
- "extent": (optional, list) The extent is specified by a list of 4 doubles that are the min-X, min-Y, max-X and max-Y extents of the field. The default extent is the 2022 field as: [-4.115, -8.23, 4.115, 8.23]. Past fields were the 2021 Infinite Recharge At Home as: [0.0, 0.0, 4.572, 9.144]; and 2020 Infinite Recharge as: [-4.105, -7.99, 4.015, 7.99].
- "view": (optional, list) Autonomous activity is often restricted to path of the field, and this is the min-X, min-Y, max-X and max-Y of the part of the field you are interested in. This defaults
- to the full field if not specified.
- "components": (required, list) The list of field components (elements or assembles) that are
generally specific to the competition for the year, and often appear multiple times on the field. Within
this list are dictionaries describing the components as:
- "name": (required, string) The name of the component. This name will be used in the field description to specify components to be added to the field and must be unique in the list of components.
- "lineColor": (optional, string, default="white") The outline color or null if no outline should be drawn, see Color Description for valid color values.
- "fillColor": (optional, string, default=null) The fill color or null if the geometry should not be filled, see Color Description.
- "shapes": (required, list) A list of shapes which will be rendered using the "lineColor" and "fillColor" directives. Each shape is described by a dictionary that has a "type" specifier and other keys specific to that type. See Shapes Descriptions for the formats of the shape types that are currently supported.
- "field": The drawing of the field. By default, the path planner draws the field axes and outline.
This section describes the things that should be drawn on the field, specifically: components as describes in
the previous section and additional field geometry. Components are specified by name, an optional alliance color,
and positioning translation and/or rotation.
- "components": The list of components to be drawn on the field. Within this list are
dictionaries describing the field placement of components as:
- "component": (required, string) The name of the component which must have been defined in the "components" section of the field description.
- "alliance": (optional, string, default=null) If this component is being drawn as an alliance specific game element, specify the alliance as "red" or "blue".
- "translate": (optional, [x,y], default=[0.0,0.0]) The translation for this component (in meters). NOTE: rotations are applied before translations.
- "rotate": (optional, double, default=0.0) The rotation for this component (in radians). NOTE: rotations are applied before translations.
- "scale": (optional, [x,y], default=[1.0,1.0])) A scale multiplier for this component. Typically this is used to mirror components to the other end of the field. NOTE: scale is applied before translation and rotation.
- "components": The list of components to be drawn on the field. Within this list are
dictionaries describing the field placement of components as:
The example description is the part of the description of the 2020 Infinite Recharge field.
Things to note:
- In the "arena" key, a "view" is specified that will show only the far half of the field. Remove the "view" to see the entire field (as shown in th image after the example description).
- The "start line" component is just a line across the field at the center of the field. When used in the "field" description it is used once with a translation to the blue and of the field and a second time with a translation to the red end of the field.
- The "ball pickup" safe zone component is described by its position at the red end of the field, but is given the "alliance" color. When drawn on the "field" it is drawn once where the "alliance" is "red", and drawn again rotated at 90°(3.1416 radians) where the "alliance" is "blue" letting us define a single component used for both alliances.
{
"title": "Infinite Recharge 2019-2020",
"description": "The Infinite Recharge arena with only start lines, pickup, and some power cells.",
"arena": {
"extent": [-4.105, -7.99, 4.105, 7.99],
"view": [-4.105, 0.0, 4.105, 7.99]
},
"components": [
{
"name": "power cell",
"lineColor": "yellow",
"fillColor": "yellow",
"shapes": [
{
"type": "circle",
"center": [ 0.0, 0.0 ],
"radius": 0.0889
}
]
},
{
"name": "start line",
"lineColor": "white",
"fillColor": "white",
"shapes": [
{
"type": "rect",
"lower left": [ -4.1050, -0.0254 ],
"upper right": [ 4.1050, 0.0254 ]
}
]
},
{
"name": "ball pickup",
"lineColor": "alliance",
"fillColor": "alliance",
"shapes": [
{
"type": "polygon",
"points": [
[-2.4626,7.9900],
[-2.3968,7.9900],
[-1.7006,7.2998],
[-1.0104,7.9900],
[-0.9386,7.9900],
[-1.7006,7.2280]
]
}
]
}
],
"field": {
"components": [
{
"component": "power cell",
"translate": [ -3.4001, 0.0]
},
{
"component": "power cell",
"translate": [ -3.4001, -0.9144]
},
{
"component": "power cell",
"translate": [ -3.4001, -1.8288 ]
},
{
"component": "start line",
"translate": [ 0.0000, 4.9766 ]
},
{
"component": "start line",
"translate": [ 0.0000, -4.9766 ]
},
{
"component": "ball pickup",
"alliance": "red"
},
{
"component": "ball pickup",
"alliance": "blue",
"rotate": 3.1416
}
]
}
}
When loaded this field looks like this:
Let's explore the field description file to understand this representation. Components are playing pieces that can be anywhere on the field (power cells), or fixed game elements (start lines, pickup areas). Components can be alliance neutral (power cells, start lines), or alliance specific (pickup areas). The field is described by locating components on the field.
The power cells are defined with a local axis system there (0,0) is the center of the power cell. The color is defined as yellow (it is neutral, and is not specific to either alliance). Power cells are translated (moved to) specific locations on the game grid when laying out the field.
The start line is specifically placed on the field (a field element), and is symmetrically located on the red-blue sides of the field - though it has no alliance-specific meaning. The start line is defined for one end of the field in the color white. A 3.14radian (180°) rotation reflects it at the opposite end of the field.
The ball pickup (power cell pickup) is alliance specific - i.e. only the specified alliance can pick up balls
there, and it is a penalty for the opposing alliance to encroach on this space. Note that the component is defined
relative to the red alliance side of the field, the color is specified as alliance
, and when drawn, it is the red
alliance when not transformed, and the blue
alliance when rotated 3.14radian (180°) to the blue alliance side.
Colors are defined by name. We use a combination of standard Java names and custom competition-specific colors defined for field artifacts.
We could have built an interface for describing color by RGB components, but, instead we used the defined Java Color names for simplicity and readability, and to allow us to use alliance as the name of a component colored by the alliance it belongs to. The recognized colors are:
- "alliance": Use the alliance color when the component is drawn or filled. This should be used for any components that represent alliance specific field markings, goals, pieces, etc. When the component is drawn into the field, the alliance color will be specified.
- "white": Use white when the component is drawn or filled.
- "red": Use red when the component is drawn or filled.
- "blue": Use blue when the component is drawn or filled.
- "light-gray": Use light gray when the component is drawn or filled.
- "gray": Use gray when the component is drawn or filled.
- "dark-gray": Use dark gray when the component is drawn or filled.
- "black": Use black gray when the component is drawn or filled.
- "orange": Use orange when the component is drawn or filled.
- "green": Use green when the component is drawn or filled.
- "cyan": Use cyan when the component is drawn or filled.
- "green-zone": The color for the green zone for Infinite Recharge at Home.
- "yellow-zone": The color for the yellow zone for Infinite Recharge at Home.
- "blue-zone": The color for the blue zone for Infinite Recharge at Home.
- "purple-zone": The color for the purple zone (reintroduction zone) for Infinite Recharge at Home.
- "red-zone": The color for the red zone for Infinite Recharge at Home.
Shapes are generally very simple descriptions of different types of geometries. Shape representations are intended to be extended (i.e. new types of shapes added) if required to represent the game arena for the season's competition.
Each shape is represented by a dictionary with a "type" key describing the shape type, and then type-specific keys and values. These are the shape types, and the corresponding keys that describe the currently supported shapes:
- "circle" - A circle of some radius centered at some location:
- "center": (required, [x,y]) The local X and Y coordinates, in meters, of the center of the center of the circle. This is generally (0.0,0.0) and the position of the circle on the field is specified when the circle is added to the field. More specifically, this is often used with a circular/spherical game piece which can be placed anywhere on the field.
- "radius": (required, double) The radius, in meters.
- "rect" - An axis-aligned rectangle defined by lower-left and upper-right coordinates:
- "lower left":
- "upper right":
- "polygon" - An arbitrary closed polygon specified by a set of points. It is assumed that
there is a closing line segment between the first and last point:
- "points": A list of points describing the polygon, each point is described as a list containing the [x,y] local X and Y coordinates, in meters, of the point. The points describe a path that will be automatically closed.
- "ring" - A ring of some inner and outer diameter centered at some location:
- "center": (required, [x,y]) The local X and Y coordinates, in meters, of the center of the center of the ring. This is generally (0.0,0.0) and the position of the ring on the field is specified when the ring is added to the field. More specifically, this is often used with a ring game piece which can be placed anywhere on the field.
- "ID": (required, double) the inner diameter of the ring, in meters.
- "OD": (required, double) the outer diameter of the ring, in meters.