{"id":24520356,"url":"https://github.com/a05annex/swervepathplanning","last_synced_at":"2025-10-31T10:15:41.914Z","repository":{"id":41157194,"uuid":"286652841","full_name":"A05annex/SwervePathPlanning","owner":"A05annex","description":"An interactive visual path planning tool for swerve drive robots.","archived":false,"fork":false,"pushed_at":"2025-05-13T21:46:14.000Z","size":1678,"stargazers_count":13,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-13T23:07:09.827Z","etag":null,"topics":["frc","path-planner","swerve-drive"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/A05annex.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-08-11T05:21:24.000Z","updated_at":"2025-02-23T09:40:30.000Z","dependencies_parsed_at":"2024-01-10T07:29:20.612Z","dependency_job_id":"30779591-d4ad-4f04-b0b8-0c4fd869e25d","html_url":"https://github.com/A05annex/SwervePathPlanning","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/A05annex/SwervePathPlanning","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A05annex%2FSwervePathPlanning","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A05annex%2FSwervePathPlanning/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A05annex%2FSwervePathPlanning/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A05annex%2FSwervePathPlanning/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/A05annex","download_url":"https://codeload.github.com/A05annex/SwervePathPlanning/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/A05annex%2FSwervePathPlanning/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267685010,"owners_count":24127704,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-29T02:00:12.549Z","response_time":2574,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["frc","path-planner","swerve-drive"],"created_at":"2025-01-22T02:22:06.193Z","updated_at":"2025-10-31T10:15:36.887Z","avatar_url":"https://github.com/A05annex.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"* **version:** 2025.0.0\n* **status:** used for FRC **2025 REEFSCAPE**, **2024 Crescendo**, **2023 Charge Up**, **2022 Rapid React**,\n  and **2021 Infinite Recharge at home**\n* **comments:** We believe this is competition-ready (i.e. we've used this for competition since the 2020-2021\n  season). This release adds the 2025 REEFSCAPE field as bot a full and half field.\n* **related releases:**\n  * [a05annexUtil](https://github.com/A05annex/a05annexUtil) - the utility library that supports various A05annex\n    projects including this swerve path planner and all of our robot competition code.\n  * [a05annexRobot](https://github.com/A05annex/a05annexRobot) - our common robot code that includes the MK4 swerve\n    base, NavX, driver and autonomous selection switch panel, autonomous path and driver commands, camera, etc.\n  * [a05annexTemplate](https://github.com/A05annex/a05annexTemplate) - our template, built on the wpilib template\n    that provides a driveable swerve base with NavX, camera, autonomous path and driver selection.\n\n# 6831 A05annex: Swerve Path Planning\n\n![alt text](./resources/swerve-path-planner.jpg \"Swerve Path Planner\")\nThis project is a visual 2D editor for path planning for a swerve drive FRC robot. You read a field description\nand robot description into this planner as a context for path planning; then draw, tune, add commands, and\nsave paths that can be used as the autonomous programs for a match.\n\nA05annex is committed to using the internationally recognized SI units, so the field, robot, and path\ndescriptions, and path points are in SI units. The +Y axis is always downfield from the driver (as Y is\nthe forward/backward axis of control sticks and the vertical or forward axis when the field map is laid\ndown in front of the driver), Specifically, the driver is at the bottom of the screen. The +X axis is\nalways to the right (common engineering convention). We adopted\nthe convention that the center of the competition field is (0.0,0.0) for red-blue alliance symmetry; and\nthat the left corner closest to the driver is 0,0 for the 2021 at Home field - both of which are reflected\nin our field descriptions for the 2021, 2022, 2023, 2024, and 2025 competitions.\n\n## Change Log\n\n\u003cdetails\u003e\n  \u003csummary\u003eversion 2025.0.0 to 2025.?.? (for \u003cb\u003e2025 REEFSCAPE\u003c/b\u003e):\u003c/summary\u003e\n\n  * **version 2025.0.0** - added \u003cb\u003e2025 REEFSCAPE\u003c/b\u003e field description.\n\u003c/details\u003e\n\u003cdetails\u003e\n  \u003csummary\u003eversion 0.9.6 to 2024.0.1 (for \u003cb\u003e2024 Crescendo\u003c/b\u003e):\u003c/summary\u003e\n\n  * **version 2024.0.2** - revised operation of 'clear path' so there is now a confirmation dialogue. The context\n    menu was reorganized to be more consistent with the main menu 'edit' item.\n  * **version 2024.0.1** - revised version numbering to be consistent with FRC versioning that uses the year as the\n    base. Added documentation for ring shape (for the 2024 *note* game piece).\n  * **version 0.9.6** - added \u003cb\u003e2024 Crescendo\u003c/b\u003e field description, and 2024 robot descriptions;\n\u003c/details\u003e\n\u003cdetails\u003e\n  \u003csummary\u003eversion 0.9.0 to 0.9.5 (for \u003cb\u003e2023 Charged Up\u003c/b\u003e):\u003c/summary\u003e\n\n  * added \u003cb\u003e2023 Charged Up\u003c/b\u003e field description, and 2023 robot descriptions;\n  * added \u003ctt\u003escale\u003c/tt\u003e for field components to support mirroring the red and blue side of the field;\n  * added dialog editing of the rotation speed at control points. There is currently no interactive graphical\n    editing of rotation because we have not found a good way to present an editing handle for rotation speed;\n  * Fixed a timing issue that sometimes threw exceptions when path animation started;\n  * Fixed error in path point info dialog where Field Y was incorrectly reporting field X, added X, Y, and rotation\n    speed to the reported path point information;\n  * added saved Idea run configurations;\n  * improved user documentation.\n\u003c/details\u003e\n\u003cdetails\u003e\n  \u003csummary\u003eversion 0.8.0 to 0.9.0 (for \u003cb\u003e2022 Rapid React\u003c/b\u003e):\u003c/summary\u003e\n\n  * added *stop-and-run* commands for control points and *scheduled commands* for path points. See\n    [Running Commands Along The Path](#Running-Commands-Along-The-Path);\n  * robots often have *appendages*, like a collector or hangar, that extend past to robot periphery\n    and must be considered in path planning - appendages were added to\n    the [Robot Description](#Robot-Description);\n  * while there is an 'FRC standard field', different competitions like **2020 Infinite Recharge**,\n    **2021 At Home**, and **2022 Rapid React** have configured this to different sizes and/or\n    restricted the portion of the field where autonomous action can happen. To adapt, we moved the field boundary\n    description from the *Swerve Path Planner* constants to the [Field Description](#Field-Description)\n    as the \u003ctt\u003e\"arena\"\u003c/tt\u003e description. The \u003ctt\u003e-ah\u003c/tt\u003e command argument was removed because field\n    extents are now in the field description rather than programmed. All field descriptions\n    in \u003ctt\u003e./resources/fields\u003c/tt\u003e have been updated to include an \u003ctt\u003e\"arena\"\u003c/tt\u003e description;\n  * minor changes for better interactive editing feedback and response.\n\u003c/details\u003e\n\n## Download and/or Run\n\nWe have finally packaged this as a runnable *.jar* file. So you now have the\noption to:\n* Download and run from the *.jar* file;\n* Clone the project and run from an IDE, which gives you all of our field, robot,\n  and path data files for reference.\n\n### Just Download and Run\n\nIn github you will find an 2025.0.0 release of the *SwervePathPlanning-2025.0.0-all.jar*\nwhich you can run at the command line as:\n```\n% java -jar SwervePathPlanning-2025.0.0-all.jar\n```\nSee notes in the next section about command line arguments. While this is a running\nprogram, it lacks data for field, robot, or path descriptions; so, you may want to\nclone the project (or just download and expand the *.zip* just so you have all of our past\nfield, robot, and path descriptions as sample data.\n\n### Clone Source and Run\nEven though we have packaged this as a runnable *.jar* file, you may want to\nclone the repository and open it in your favorite IDE (Intellij IDEA or\nVisual Studio) and create a run target for `ServePathPlanner` (if you are using Idea, the run targets\nwill be loaded when you load the project). The gradle build file will resolve the\ndependencies, build, and run the program.\n\nWhen you run the program it will initialize with a default view of the most recent competition field\nwithout any field elements. You can add some\ncommandline arguments to the run target to get your desired field and robot to load automatically.\nRun with the `-h`\nor `--help` command line option to get program help:\n```\nusage: PathPlanner [-h] [-r ROBOT] [-f FIELD]\n\nSwerve Drive Path Planner\n\nnamed arguments:\n-h, --help                  show this help message and exit\n-r ROBOT, --robot ROBOT     specify a robot description file\n-f FIELD, --field FIELD     specify a field description file\n```\nOur fields, robots, and paths from previous years are in the \u003ctt\u003eresources\u003c/tt\u003e folder of the project.\n\n## Path Spline\n\n\u003cdetails\u003e\n  \u003csummary\u003eThe path planner uses an implementation of the\n  \u003ca href=\"https://en.wikipedia.org/wiki/Kochanek%E2%80%93Bartels_spline\"\u003eKochanek-Bartels Spline\u003c/a\u003e modified\n  for interactive editing of the tangent vector to implicitly control bias and tension. There is no\n  continuity control because we want our robot paths to be continuous. The original reference for this\n  spline can be found at\n  \u003ca href=\"https://www.engr.colostate.edu/ECE455/Readings/TCB.pdf\"\u003e\n  Interpolating Splines with Local Tension, Continuity, and Bias Control\u003c/a\u003e.\n  \u003c/summary\u003e\n\u003cbr\u003e\nWhen control points are created the tangent (derivatives) at that control point and surrounding\ncontrol points are computed/recomputed using the [Cardinal-Spline](https://en.wikipedia.org/wiki/Cubic_Hermite_spline)\nformulation with the default tension specified by a program constant. The tangent is adjusted using a\ncontrol handle which intuitively manipulates the shape of the spline at the control point to implicitly\nedit tension and bias.\n\u003c/details\u003e\n\n## Creating and Editing a Path\n\n\u003cdetails\u003e\u003csummary\u003e\nA path is created by dropping successive \u003ci\u003econtrol points\u003c/i\u003e along the path onto the diagram of the field. Once the\ncontrol points have been dropped, the path is edited and adjusted by: modifying positions and path derivatives\nat the control points; adding control points; removing control points; and attaching action commands to the\npath.\u003c/summary\u003e\n\n### Initial Path Creation\n\nWhen the path planner is started it shows, by default, the full 2022 field boundary\nwith no field elements (see \u003ca href=\"#Field-Description\"\u003eField Description\u003c/a\u003e for loading a specific field\nand elements); and will use a default robot chassis that is 0.9m long and 0.5m wide; and 1.1m\nlong amd 0.7m long with bumpers (see \u003ca href=\"#Robot-Description\"\u003eRobot Description\u003c/a\u003e for loading\na description of your robot).\n\u003cp\u003e\nThe display starts in \u003ci\u003epath creation mode\u003c/i\u003e. Each time you click on the field a control point will be\ncreated at that position. A \u003ci\u003edouble-click\u003c/i\u003e will end the path at the control point created there\nand switch to \u003ci\u003epath edit\u003c/i\u003e mode. Alternately, you can \u003ci\u003eright-click\u003c/i\u003e to get a\ncontext-sensitive menu, and select \u003cb\u003eEnd Path\u003c/b\u003e to end the path at the last created control point,\nand switch to \u003ci\u003epath edit\u003c/i\u003e mode.\n\n### Playing the Path\n\nAn animation of the robot following the path can be *played* in two ways:\n\u003cul\u003e\n\u003cli\u003eFrom the main menu, under \u003cb\u003ePath\u003c/b\u003e, select \u003cb\u003ePlay Path\u003c/b\u003e\u003c/li\u003e\n\u003cli\u003eFrom the context menu (right-click anywhere to get the context menu), select \u003cb\u003ePlay Path\u003c/b\u003e\u003c/li\u003e\n\u003c/ul\u003e\nThis will animate the robot following the path at actual speed/timing.\n\n### Editing the Path\n\n\u003cdetails\u003e\u003csummary\u003e\nOnce you create a path, really a first guess at the path by dropping a few control points, you go immediately\ninto path tuning (editing). Generally, the questions and adjustments are around:\n\u003cul\u003e\n\u003cli\u003eIs this really the path I meant, and, can I fix it?;\u003c/li\u003e\n\u003cli\u003eIs the robot capable of following the path, and if not, how do I fix it?;\u003c/li\u003e\n\u003cli\u003eIs the robot facing the right direction, and if not, how do I fix it?;\u003c/li\u003e\n\u003cli\u003eHow do I tell the robot to do something in addition to following the path?;\u003c/li\u003e\n\u003cli\u003eHow can I optimize timing or speed for a faster (better) path?\u003c/li\u003e\n\u003c/ul\u003e\nExpand this section to get answers for these questions.\n\u003c/summary\u003e\n\n#### What is a Control Point?\n\nA control point is a position on the field that the path will pass through at a specified time with a specified\nvelocity, direction, and rotation speed. Each time you drop a new control point it is, by default, 1 second further along the\npath than the last control point. At the control point you will see editing handles for: position on the field;\ndirection and velocity; and field orientation of the robot as shown below.\n![alt text](./resources/ControlPoint.jpg \"Control Point Editing\")\n\nAs you move the cursor you will always get the *field position* feedback with the cursor. If you are over an\nediting handle, the handle will be surrounded by a green circle. In the figure above, the cursor is above the\ncontrol point position handle. When you are above a handle (it has a green circle) you can left-click and\ndrag the handle to edit that parameter (field position, direction and velocity,\nrobot heading) at that control point.\n\nNOTE that as you edit the control point, the robot path will reflect those edits. The robot path will be colored\nto describe things you should consider:\n* **white** - this is a valid robot path;\n* **red** - this path is asking the robot to perform beyond its capabilities - specifically, you are asking at\n  least one module to go faster than is possible;\n* **orange** - this path is in danger of crashing (or will crash) into the field perimeter.\n\n### Clearing a Bad Path and Restarting Path Creation\n\nWe all do some testing, drop some points, create a path, and say \"Good experiment, delete that and let's start\nover\". This is how we do that:\n\u003cul\u003e\n\u003cli\u003eFrom the main menu, under \u003cb\u003ePath\u003c/b\u003e, select \u003cb\u003eClear Path\u003c/b\u003e\u003c/li\u003e\n\u003cli\u003eFrom the context menu (right-click anywhere to get the context menu), select \u003cb\u003eClear Path\u003c/b\u003e\u003c/li\u003e\n\u003c/ul\u003e\nThis will clear any loaded or created path from the path planner, and you will lose any edits made since the last\ntime you saved the path. The path planner will be placed in path creation mode and you can start dropping cointrol\npoints for the new path.\n\n### Reshaping the path\n\n\u003cdetails\u003e\u003csummary\u003eThere are 2 primary approaches to reshaping a path:\n\u003cul\u003e\n\u003cli\u003eEdit (move, change direction and/or velocity and heading) at control points of the existing path;\u003c/li\u003e\n\u003cli\u003eAdd or remove control points.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/summary\u003e\n\n#### Editing a Control Point\n\nIn the previous \u003ca href=\"#What-is-a-Control-Point\"\u003eWhat is a Control Point\u003c/a\u003e section, the handles are your\nway to interactively edit the curve around a control point. Specifically:\n\u003cul\u003e\n\u003cli\u003e\u003ci\u003eposition handle\u003c/i\u003e - moves the control point, the point the path goes though, on the field;\u003c/li\u003e\n\u003cli\u003e\u003ci\u003edirection/velocity handle\u003c/i\u003e - shapes the curve around the point;\u003c/li\u003e\n\u003cli\u003e\u003ci\u003erobot heading handle\u003c/i\u003e - changes the heading of the robot as it goes through that control point.\u003c/li\u003e\n\u003c/ul\u003e\nIt is useful to play with these on a test path to get a better idea how the handles control and shape the path.\n\n#### Adding and Removing Control Points\n\nOften you will find that as you edit and reshape your path you will be moving too many control points and want to\ndelete control points that are superfluous; or, You need finer control somewhere along the path, and you want to\nadd a control point. Here is how you do that:\n\u003cul\u003e\n\u003cli\u003eRemoving a Control Point:\n\u003cul\u003e\n\u003cli\u003eright click on the \u003ci\u003efield position handle\u003c/i\u003e of the control point;\u003c/li\u003e\n\u003cli\u003efrom the context menu, select \u003cb\u003eDelete Control Point\u003c/b\u003e. The control point will be deleted, and\nthe timing for all other control points will remain unchanged.\u003c/li\u003e\n\u003c/ul\u003e\u003c/li\u003e\n\u003cli\u003eAdding a Control Point:\n\u003cul\u003e\n\u003cli\u003eright click on the path point where you wnt to add a control point;\u003c/li\u003e\n\u003cli\u003efrom the context menu, select \u003cb\u003eInsert Control Point\u003c/b\u003e. A control point will be added at that path\npoint with the timing and other parameters of that path point. This should produce minimal disturbance of\nthe current path and give you additional control point for path tuning.\u003c/li\u003e\n\u003c/ul\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003c/details\u003e\n\n### Editing Timing along the Path\n\n\u003cdetails\u003e\u003csummary\u003e\nThere are 2 ways to adjust path timing:\n\u003cul\u003e\n\u003cli\u003eRe-time a control point in the path;\u003c/li\u003e\n\u003cli\u003eRe-time the entire path.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/summary\u003e\n\n#### Re-timing a Single Control Point\n\nWhen you initially drop control points to define a path, each new control point is set to be 1 second from the\nlast. Often, you will need a couple control points close together to control motion around some field obstacle,\nand the 1 second spacing between control points is not at all what you want. You can change the time for an individual\ncontrol point, which will reset the timing for all subsequent points so they have the same relative timing.\n\nFor example, suppose my robot needs to move forward 2m, then take a .25m left jog, and move forward again. I create a\npath with a start point, a 2nd control point immediately before the jog, a 3rd control point immediately after the\njog, and then a 4th control point another 2m forward. These 4 points are assigned an initial timing of 0sec, 1sec,\n2sec, and 3sec respectively. When you play the path you will see the robot slow to a crawl between control points 2\nand 3 - not at all what you wanted.\n\nWhat you really want is for control points 2 and 3 to be closer together in time so the robot maintains its speed\nas it makes the jog, so instead of control point 3 being crossed in 2sec, you want to cross it in 1.3sec. Let's\nchange the time the robot crosses point 3 to 1.3sec:\n\u003cul\u003e\n\u003cli\u003eright click on the \u003ci\u003efield position handle\u003c/i\u003e of the 3rd control point;\u003c/li\u003e\n\u003cli\u003efrom the context menu, select \u003cb\u003eInfo\u003c/b\u003e, this will bring up a control point information dialogue;\u003c/li\u003e\n\u003cli\u003ein the control point information dialogue, edit the \u003cb\u003eAt Time\u003c/b\u003e from 2 to 1.3, and \u003cb\u003eapply\u003c/b\u003e this\nchange. The 3rd control point and all subsequent points have now had their time adjusted, which should\nbe reflected when you play the path.\u003c/li\u003e\n\u003c/ul\u003e\n\n#### Re-timing the Entire Path\n\nIt is common to start path planning with a path that is slower than the best the robot could achieve to\nmake tuning easier, and make it less damaging to the robot and test arena if the path does not go as\nexpected. Once the path is working pretty well, we often want to turn up the speed and continue to tune\nuntil we get maximum robot performance. The path planner provides a speed multiplier to accommodate this\nneed. The speed multiplier defaults to 1.0. To change the speed multiplier, from the main menu, under \u003cb\u003ePath\u003c/b\u003e\nselect \u003cb\u003eSpeed Multiplier\u003c/b\u003e to bring up a dialogue for changing the multiplier.\n\nNote that when you change the speed multiplier, the red path highlights for paths that are beyond the capability\nof the robot will change to reflect the new speed profile, encouraging you to tune control points to keep the\npath within the robot capabilities.\n\n\u003c/details\u003e\n\n\u003c/details\u003e\n\n### Running Commands Along The Path\n\u003cdetails\u003e\u003csummary\u003e\nIn the \u003cb\u003e2021 At Home Challenges\u003c/b\u003e, the obstacle course challenges merely required a path. For the \u003cb\u003e2022\nRapid React\u003c/b\u003e competition it became obvious we needed the paths to include other actions (commands) that needed to\nrun at various points on the path (like \u003ci\u003estart/stop-collector\u003c/i\u003e, or \u003ci\u003eaim-and-shoot\u003c/i\u003e). So the\n\u003ccode\u003eAutonomousPathCommand\u003c/code\u003e run on the robot is really a dynamically configured (configured when the path is\nexecuted) Command Group.\n\nTwo types of commands are supported:\n\u003cul\u003e\n\u003cli\u003eA Command that is scheduled to execute at a specif point along the path the robot is following, e.g.\n  start/stop the collector rollers;\u003c/li\u003e\n\u003cli\u003eA command that happens at a control point where the robot stops, the path follower relinquishes\n  control of the swerve drive, and path following resumes at the completion\n  of the command. An example of this would be a command that aims the shooter at a target, spins-up \n  the shooter rollers, and takes a shot.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/summary\u003e\n\n#### Scheduled Commands ####\n\n\u003ci\u003eTo be written\u003c/i\u003e\n\n#### Stop-And-Run Commands ####\n\n\u003ci\u003eTo be written\u003c/i\u003e\n\n\u003c/details\u003e\n\n\u003c/details\u003e\n\n## Path Description Format\n\n\u003cdetails\u003e\n  \u003csummary\u003ePaths are saved in \u003ccode\u003e.json\u003c/code\u003e files that can be loaded to the robot for execution by the\n  \u003ccode\u003eAutonomousPathCommand\u003c/code\u003e.\n  \u003c/summary\u003e\n\nThe path is saved as a list of control points in a dictionary with these keys:\n- **\u003ctt\u003e\"title\"\u003c/tt\u003e**: (optional, string) A title or name for the path, primarily used as file documentation\n  to refresh you on the path this file represents.\n- **\u003ctt\u003e\"description\"\u003c/tt\u003e**: (optional, string) A more verbose description if the path, again primarily used as file\n  documentation to refresh you on the path this file represents.\n- **\u003ctt\u003e\"controlPoints\"\u003c/tt\u003e**: (required, list) The list of control points. A control point is a dictionary\n  containing these fields:\n  - **\u003ctt\u003e\"fieldX\"\u003c/tt\u003e**: (optional, double, default=0.0) The field X position in meters.\n  - **\u003ctt\u003e\"fieldY\"\u003c/tt\u003e**: (optional, double, default=0.0) The field Y position in meters.\n  - **\u003ctt\u003e\"fieldHeading\"\u003c/tt\u003e**: (optional, double, default=0.0) The field heading in radians.\n  - **\u003ctt\u003e\"time\"\u003c/tt\u003e**: (optional, double, default=0.0) The time at which this control point should be reached.\n  - **\u003ctt\u003e\"derivativesEdited\"\u003c/tt\u003e**: (optional, boolean, default=\u003ctt\u003efalse\u003c/tt\u003e) Whether the derivatives of the\n    control point velocities have been explicitly set (usually by manipulating the direction/velocity handle for\n    the control point). If \u003ccode\u003efalse\u003c/code\u003e, then the X,Y velocities at the control point are set\n    algorithmically at load and when the control point is moved. If \u003ccode\u003etrue\u003c/code\u003e then the X,Y velocities specified\n    here are used for the control point.\n  - **\u003ctt\u003e\"field_dX\"\u003c/tt\u003e**: (optional, double, default=0.0) The field X velocity in meters per second.\n  - **\u003ctt\u003e\"field_dY\"\u003c/tt\u003e**: (optional, double, default=0.0) The field Y velocity in meters per second.\n  - **\u003ctt\u003e\"HeadingDerivativeEdited\"\u003c/tt\u003e**: (optional, boolean, default=\u003ctt\u003efalse\u003c/tt\u003e) Whether the derivative of the\n    control point heading has been explicitly set. If \u003ccode\u003efalse\u003c/code\u003e, then the heading derivative at the control\n    point is set algorithmically. If \u003ccode\u003etrue\u003c/code\u003e then dHeading specified here is used for the control point.\n  - **\u003ctt\u003e\"field_dHeading\"\u003c/tt\u003e**: (optional, double, default=0.0) The field angular velocity in\n    radians per second. Currently, ignored as the derivative is always generated from the headings of the adjacent\n    control points.\n  - **\u003ctt\u003e\"robotActionCommand\"\u003c/tt\u003e**: (optional, string) The action command to run once the robot stops\n    at this control point. This command may require the **\u003ctt\u003ea05annex/src/subsystems/DriveSubsystem\u003c/tt\u003e**. If\n    this command does not finish, the rest of the path will not be run. If not specified, no robot action will\n    be run at this control point.\n  - **\u003ctt\u003e\"robotActionDuration\"\u003c/tt\u003e**: (conditional, double) Required if **\u003ctt\u003erobotActionCommand\u003c/tt\u003e** is\n    specified. This is the expected duration (in seconds) of the **\u003ctt\u003erobotActionCommand\u003c/tt\u003e** and is used\n    only in the pat planner to pause path following at the control point for this time in order to simulate\n    the actual timing when the path is played for planning.\n- **\u003ctt\u003e\"speedMultiplier\"\u003c/tt\u003e**: (optional, string, default=1.0) The speed multiplier for the path. If greater than\n  1.0 the robot will be moving faster along the path.\n- **\u003ctt\u003e\"robotScheduledActions\"\u003c/tt\u003e**: (optional, list) The list of scheduled actions. A scheduled action is a\n  dictionary containing these fields:\n  - **\u003ctt\u003e\"robotActionCommand\"\u003c/tt\u003e**: (required, string) The action command to be scheduled at\n    **\u003ctt\u003erobotScheduledActionTime\u003c/tt\u003e**. This command must not require the\n    **\u003ctt\u003ea05annex/src/subsystems/DriveSubsystem\u003c/tt\u003e**.\n  - **\u003ctt\u003e\"robotScheduledActionTime\"\u003c/tt\u003e**: (required, double) The time along the path when the\n    **\u003ctt\u003erobotActionCommand\u003c/tt\u003e** will be scheduled to run.\n  \n\n  \n#### Path Description Examples\n\n\u003cdetails\u003e\n\u003csummary\u003e\nThis is the path description for a 2m diameter calibration path (see the\n\u003ccode\u003e./resources/paths/test_circle_2m.json\u003c/code\u003e path):\n\u003c/summary\u003e\n\n```json\n{\n  \"description\": \"2m diameter test circle.\",\n  \"title\": \"The path for a 2 meter diameter test circle with the robot facing the center of the circle.\",\n  \"controlPoints\": [\n    {\n      \"fieldY\": 0.0,\n      \"fieldX\": 0.0,\n      \"fieldHeading\": 0.0,\n      \"time\": 0.0\n    },\n    {\n      \"fieldY\": 1.0,\n      \"fieldX\": -1.0,\n      \"fieldHeading\": 1.5708,\n      \"time\": 1.0\n    },\n    {\n      \"fieldY\": 2.0,\n      \"fieldX\": 0.0,\n      \"fieldHeading\": 3.1416,\n      \"time\": 2.0\n    },\n    {\n      \"fieldY\": 1.0,\n      \"fieldX\": 1.0,\n      \"fieldHeading\": 4.7124,\n      \"time\": 3.0\n    },\n    {\n      \"fieldY\": 0.0,\n      \"fieldX\": 0.0,\n      \"fieldHeading\": 6.2832,\n      \"time\": 4.0\n    }\n  ]\n}\n```\nWhen loaded into the path planner, the path looks like this:\u003cbr\u003e\n![alt text](./resources/2m_circle_path.jpg \"2m circle path\")\n\u003cp\u003e\nNote that the path is defined using positions, velocities, and time. When the path is processed by the robot\ncode that information is translated to drive commands.\n\n\u003c/details\u003e\n\u003c/details\u003e\n\n### Using a Path Description in the Robot Autonomous\n\n*To be written.*\n\n## Robot Description\n\n\u003cdetails\u003e\n  \u003csummary\u003eThe robot is described in a \u003ccode\u003e.json\u003c/code\u003e file read into the path planner and displayed as the robot during\n  the path planning, as well as providing the drive geometry and max speed for the modules of the swerve\n  drive.\n  \u003c/summary\u003e\nHaving a good description of the robot is helpful in identifying when the planned path exceeds the\ncapability of the robot (i.e. it just cannot go that fast), and detecting collisions or near collisions\nbetween the robot and game elements.\n\n### Robot Description Format\n\nThe robot description has **\u003ctt\u003e\"title\"\u003c/tt\u003e** and **\u003ctt\u003e\"description\"\u003c/tt\u003e** elements, and the actual geometry\nof the robots is divided into 4 sections:\n- **\u003ctt\u003e\"title\"\u003c/tt\u003e**: (optional, string) A title or name for the robot, primarily used as file documentation to refresh\n  you on the robot this file represents.\n- **\u003ctt\u003e\"description\"\u003c/tt\u003e**: (optional, string) A more verbose description if the robot, again primarily used as file\n  documentation to refresh you on the robot this file represents.\n- **\u003ctt\u003e\"drive\"\u003c/tt\u003e**: (optional, dictionary) describes the geometry of the drive\n  - **\u003ctt\u003e\"length\"\u003c/tt\u003e**: (optional, double, default=0.7) The length of the drive (pivot axis to pivot axis) in meters.\n  - **\u003ctt\u003e\"width\"\u003c/tt\u003e**: (optional, double, default=0.3) The width of the drive (pivot axis to pivot axis) in meters.\n  - **\u003ctt\u003e\"maxSpeed\"\u003c/tt\u003e**: (optional, double, default=3.0) The maximum module speed (meters/sec)\n- **\u003ctt\u003e\"chassis\"\u003c/tt\u003e**: (optional, dictionary) describes the geometry of the chassis (it is currently assumed the drive\n  and chassis share the same centroid)\n  - **\u003ctt\u003e\"length\"\u003c/tt\u003e**: (optional, double, default=0.9) The length of the chassis in meters.\n  - **\u003ctt\u003e\"width\"\u003c/tt\u003e**: (optional, double, default=0.5) The width of the chassis in meters.\n- **\u003ctt\u003e\"bumpers\"\u003c/tt\u003e**: (optional, dictionary)\n  - **\u003ctt\u003e\"length\"\u003c/tt\u003e**: (optional, double, default=1.1) The length of robot with bumpers in meters.\n  - **\u003ctt\u003e\"width\"\u003c/tt\u003e**: (optional, double, default=0.7) The width of the robot with bumpers in meters.\n- **\u003ctt\u003e\"appendages\"\u003c/tt\u003e**: (optional, dictionary)\n\n### Example Robot Description file\n\n\u003cdetails\u003e\n  \u003csummary\u003e\n  This is a robot file which describes our 2023 competition swerve base:\n  \u003c/summary\u003e\n\n```json\n{\n  \"title\": \"2023 competition base.\",\n  \"description\": \"This is the black anodized competition base for 2023 A05 annex, FRC team 6831\",\n  \"drive\": {\n    \"length\": 0.5461,\n    \"width\": 0.5461,\n    \"maxSpeed\": 3.136\n  },\n  \"chassis\": {\n    \"length\": 0.712,\n    \"width\": 0.712\n  },\n  \"bumpers\": {\n    \"length\": 0.8636,\n    \"width\": 0.8636\n  }\n}\n```\n\nNote that the only use for **\u003ctt\u003edrive.maxSpeed\u003c/tt\u003e** is in determining whether the robot is capable\nof executing the specified path.\n\n\u003c/details\u003e\n\u003c/details\u003e\n\n## Field Description\n\n\u003cdetails\u003e\n  \u003csummary\u003e\n  The field is described in a \u003ccode\u003e.json\u003c/code\u003e file read into the path planner and displayed as the background\n  field context during path planning.\n  \u003c/summary\u003e\nThe Path Planner initializes displaying the field axes ([0.0,0.0] is center field),\nand the standard field outline. The field description adds the game elements for the season-specific game, and\nmay change the field outline and display the portion of the field that is of interest in path planning.\n\nTo simplify field description there are sections of the description for;\n- field \u003ctt\u003earena\u003c/tt\u003e where you describe field outline and the view that is of interest in autonomous path planning\n- game \u003ctt\u003ecomponents\u003c/tt\u003e where you describe game elements like the scoring pieces, scoring targets, scoring\n  piece depots, etc.;\n- and a \u003ctt\u003efield\u003c/tt\u003e section that lets you position components and describe which\n  alliance (if any) they belong to.\n\n### Field Description Format\n\nThe field is described in a \u003ctt\u003e.json\u003c/tt\u003e file read into the planner and displayed as the context\nfor planning move paths. The field description file has 4 main elements:\n- **\u003ctt\u003e\"title\"\u003c/tt\u003e**: (optional, string) A title or name for the field, primarily used as file documentation\n  to refresh you on the field this file represents.\n- **\u003ctt\u003e\"description\"\u003c/tt\u003e**: (optional, string) A more verbose description if the field, again primarily used as file\n  documentation to refresh you on the field this file represents.\n- **\u003ctt\u003e\"arena\"\u003c/tt\u003e**: (optional, dictionary) a description of the arena bounds and view that is of interest. if \n  not specified, the default *\u003ctt\u003e\"field\"\u003c/tt\u003e is the 2022 field, and the default \u003ctt\u003e\"view\"\u003c/tt\u003e is the\n  entire field.\n  - **\u003ctt\u003e\"extent\"\u003c/tt\u003e**: (optional, list) The extent is specified by a list of 4 doubles that are the\n    min-X, min-Y, max-X and max-Y extents of the field. The default extent is the 2022 field as:\n    \u003ctt\u003e[-4.115, -8.23, 4.115, 8.23]\u003c/tt\u003e. Past fields were the 2021 Infinite Recharge At Home as:\n    \u003ctt\u003e[0.0, 0.0, 4.572, 9.144]\u003c/tt\u003e; and 2020 Infinite Recharge as: \n    \u003ctt\u003e[-4.105, -7.99, 4.015, 7.99]\u003c/tt\u003e.\n  - **\u003ctt\u003e\"view\"\u003c/tt\u003e**: (optional, list) Autonomous activity is often restricted to path of the field, and\n    this is the min-X, min-Y, max-X and max-Y of the part of the field you are interested in. This defaults\n  - to the full field if not specified.\n- **\u003ctt\u003e\"components\"\u003c/tt\u003e**: (required, list) The list of field components (elements or assembles) that are\n  generally specific to the competition for the year, and often appear multiple times on the field. Within\n  this list are dictionaries describing the components as:\n  - **\u003ctt\u003e\"name\"\u003c/tt\u003e**: (required, string) The name of the component. This name will be used in the field\n    description to specify components to be added to the field and must be unique in the list of components.\n  - **\u003ctt\u003e\"lineColor\"\u003c/tt\u003e**: (optional, string, default=\u003ctt\u003e\"white\"\u003c/tt\u003e) The outline color or \u003ctt\u003enull\u003c/tt\u003e if\n    no outline should be drawn, see [Color Description](#Color-Description) for valid color values.\n  - **\u003ctt\u003e\"fillColor\"\u003c/tt\u003e**:  (optional, string, default=\u003ctt\u003enull\u003c/tt\u003e) The fill color or \u003ctt\u003enull\u003c/tt\u003e if\n    the geometry should not be filled, see [Color Description](#Color-Description).\n  - **\u003ctt\u003e\"shapes\"\u003c/tt\u003e**: (required, list) A list of shapes which will be rendered using the \u003ctt\u003e\"lineColor\"\u003c/tt\u003e and\n    \u003ctt\u003e\"fillColor\"\u003c/tt\u003e directives. Each shape is described by a dictionary that has a \u003ctt\u003e\"type\"\u003c/tt\u003e specifier\n    and other keys specific to that type. See [Shapes Descriptions](#Shape-Descriptions) for the formats of the\n    shape types that are currently supported.\n- **\u003ctt\u003e\"field\"\u003c/tt\u003e**: The drawing of the field. By default, the path planner draws the field axes and outline.\n  This section describes the things that should be drawn on the field, specifically: components as describes in\n  the previous section and additional field geometry. Components are specified by name, an optional alliance color,\n  and positioning translation and/or rotation.\n  - **\u003ctt\u003e\"components\"\u003c/tt\u003e**: The list of components to be drawn on the field. Within this list are\n  dictionaries describing the field placement of components as:\n    - **\u003ctt\u003e\"component\"\u003c/tt\u003e**: (required, string) The name of the component which must have been defined in the\n      \u003ctt\u003e\"components\"\u003c/tt\u003e section of the field description.\n    - **\u003ctt\u003e\"alliance\"\u003c/tt\u003e**: (optional, string, default=\u003ctt\u003enull\u003c/tt\u003e) If this component is being drawn as\n      an alliance specific game element, specify the alliance as \u003ctt\u003e\"red\"\u003c/tt\u003e or \u003ctt\u003e\"blue\"\u003c/tt\u003e.\n    - **\u003ctt\u003e\"translate\"\u003c/tt\u003e**: (optional, [*x*,*y*], default=[0.0,0.0]) The translation for this component (in\n      meters). NOTE: rotations are applied before translations.\n    - **\u003ctt\u003e\"rotate\"\u003c/tt\u003e**: (optional, double, default=0.0) The rotation for this component (in radians). NOTE:\n      rotations are applied before translations.\n    - **\u003ctt\u003e\"scale\"\u003c/tt\u003e**: (optional, [*x*,*y*], default=[1.0,1.0])) A scale multiplier for this component. Typically\n      this is used to mirror components to the other end of the field. NOTE:\n      scale is applied before translation and rotation.\n\n\n### Example Field Description file\n\n\u003cdetails\u003e\n  \u003csummary\u003e\n  The example description is the part of the description of the 2020 Infinite Recharge field.\n  \u003c/summary\u003e\n\nThings to note:\n* In the \u003ctt\u003e\"arena\"\u003c/tt\u003e key, a \u003ctt\u003e\"view\"\u003c/tt\u003e is specified that will show only the far half of the\n  field. Remove the \u003ctt\u003e\"view\"\u003c/tt\u003e to see the entire field (as shown in th image after the example description).\n* The \u003ctt\u003e\"start line\"\u003c/tt\u003e component is just a line across the field at the center of the field. When used\n  in the \u003ctt\u003e\"field\"\u003c/tt\u003e description it is used once with a translation to the blue and of the field and\n  a second time with a translation to the red end of the field.\n* The \u003ctt\u003e\"ball pickup\"\u003c/tt\u003e safe zone component is described by its position at the red end of the field, but \n  is given the \u003ctt\u003e\"alliance\"\u003c/tt\u003e color. When drawn on the \u003ctt\u003e\"field\"\u003c/tt\u003e it is drawn once where the\n  \u003ctt\u003e\"alliance\"\u003c/tt\u003e is \u003ctt\u003e\"red\"\u003c/tt\u003e, and drawn again rotated at 90\u0026deg;(3.1416 radians) where the\n  \u003ctt\u003e\"alliance\"\u003c/tt\u003e is \u003ctt\u003e\"blue\"\u003c/tt\u003e letting us define a single component used for both alliances.\n\n```json\n{\n  \"title\": \"Infinite Recharge 2019-2020\",\n  \"description\": \"The Infinite Recharge arena with only start lines, pickup, and some power cells.\",\n  \"arena\": {\n    \"extent\": [-4.105, -7.99, 4.105, 7.99],\n    \"view\": [-4.105, 0.0, 4.105, 7.99]\n  },\n  \"components\": [\n    {\n      \"name\": \"power cell\",\n      \"lineColor\": \"yellow\",\n      \"fillColor\": \"yellow\",\n      \"shapes\": [\n        {\n          \"type\": \"circle\",\n          \"center\": [ 0.0, 0.0 ],\n          \"radius\": 0.0889\n        }\n      ]\n    },\n    {\n      \"name\": \"start line\",\n      \"lineColor\": \"white\",\n      \"fillColor\": \"white\",\n      \"shapes\": [\n        {\n          \"type\": \"rect\",\n          \"lower left\": [ -4.1050, -0.0254 ],\n          \"upper right\": [ 4.1050, 0.0254 ]\n        }\n      ]\n    },\n    {\n      \"name\": \"ball pickup\",\n      \"lineColor\": \"alliance\",\n      \"fillColor\": \"alliance\",\n      \"shapes\": [\n        {\n          \"type\": \"polygon\",\n          \"points\": [\n            [-2.4626,7.9900],\n            [-2.3968,7.9900],\n            [-1.7006,7.2998],\n            [-1.0104,7.9900],\n            [-0.9386,7.9900],\n            [-1.7006,7.2280]\n          ]\n        }\n      ]\n    }\n  ],\n  \"field\": {\n    \"components\": [\n      {\n        \"component\": \"power cell\",\n        \"translate\": [ -3.4001, 0.0]\n      },\n      {\n        \"component\": \"power cell\",\n        \"translate\": [ -3.4001, -0.9144]\n      },\n      {\n        \"component\": \"power cell\",\n        \"translate\": [ -3.4001, -1.8288 ]\n      },\n      {\n        \"component\": \"start line\",\n        \"translate\": [ 0.0000, 4.9766 ]\n      },\n      {\n        \"component\": \"start line\",\n        \"translate\": [ 0.0000, -4.9766 ]\n      },\n      {\n        \"component\": \"ball pickup\",\n        \"alliance\": \"red\"\n      },\n      {\n        \"component\": \"ball pickup\",\n        \"alliance\": \"blue\",\n        \"rotate\": 3.1416\n      }\n    ]\n  }\n}\n```\nWhen loaded this field looks like this:\n![alt text](./resources/exampleField.jpg \"Example Field\")\n\nLet's explore the field description file to understand this representation. Components are playing\npieces that can be anywhere on the field (power cells), or fixed game elements (start lines, pickup areas).\nComponents can be alliance neutral (power cells, start lines), or alliance specific (pickup areas). The field\nis described by locating components on the field.\n\nThe power cells are defined with a local axis system there (0,0) is the center of the power cell. The color\nis defined as yellow (it is neutral, and is not specific to either alliance). Power cells are translated (moved to)\nspecific locations on the game grid when laying out the field.\n\nThe start line is specifically placed on the field (a field element), and is symmetrically located on the red-blue\nsides of the field - though it has no alliance-specific meaning. The start line is defined for one end of the field\nin the color white. A 3.14radian (180\u0026deg;) rotation reflects it at the opposite end of the field.\n\nThe ball pickup (power cell pickup) is alliance specific - i.e. only the specified alliance can pick up balls\nthere, and it is a penalty for the opposing alliance to encroach on this space. **Note** that the component is defined\nrelative to the red alliance side of the field, the color is specified as `alliance`, and when drawn, it is the `red`\nalliance when not transformed, and the `blue` alliance when rotated 3.14radian (180\u0026deg;) to the blue alliance side.\n\u003c/details\u003e\n\u003c/details\u003e\n\n## Color Description\n\n\u003cdetails\u003e\n  \u003csummary\u003eColors are defined by name. We use a combination of standard Java names and custom\n  competition-specific colors defined for field artifacts.\u003c/summary\u003e\n\nWe could have built an interface for describing color by RGB components, but, instead we used the defined\nJava [Color](https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Color.html) names for\nsimplicity and readability, and to allow us to use \u003ctt\u003ealliance\u003c/tt\u003e as the name of a component\ncolored by the alliance it belongs to. The recognized colors are:\n- **\u003ctt\u003e\"alliance\"\u003c/tt\u003e**: Use the alliance color when the component is drawn or filled. This should be used\n  for any components that represent alliance specific field markings, goals, pieces, etc. When the\n  component is drawn into the field, the alliance color will be specified.\n- **\u003ctt\u003e\"white\"\u003c/tt\u003e**: Use white when the component is drawn or filled.\n- **\u003ctt\u003e\"red\"\u003c/tt\u003e**: Use red when the component is drawn or filled.\n- **\u003ctt\u003e\"blue\"\u003c/tt\u003e**: Use blue when the component is drawn or filled.\n- **\u003ctt\u003e\"light-gray\"\u003c/tt\u003e**: Use light gray when the component is drawn or filled.\n- **\u003ctt\u003e\"gray\"\u003c/tt\u003e**: Use gray when the component is drawn or filled.\n- **\u003ctt\u003e\"dark-gray\"\u003c/tt\u003e**: Use dark gray when the component is drawn or filled.\n- **\u003ctt\u003e\"black\"\u003c/tt\u003e**: Use black gray when the component is drawn or filled.\n- **\u003ctt\u003e\"orange\"\u003c/tt\u003e**: Use orange when the component is drawn or filled.\n- **\u003ctt\u003e\"green\"\u003c/tt\u003e**: Use green when the component is drawn or filled.\n- **\u003ctt\u003e\"cyan\"\u003c/tt\u003e**: Use cyan when the component is drawn or filled.\n- **\u003ctt\u003e\"green-zone\"\u003c/tt\u003e**: The color for the green zone for Infinite Recharge at Home.\n- **\u003ctt\u003e\"yellow-zone\"\u003c/tt\u003e**: The color for the yellow zone for Infinite Recharge at Home.\n- **\u003ctt\u003e\"blue-zone\"\u003c/tt\u003e**: The color for the blue zone for Infinite Recharge at Home.\n- **\u003ctt\u003e\"purple-zone\"\u003c/tt\u003e**: The color for the purple zone (reintroduction zone) for Infinite Recharge at Home.\n- **\u003ctt\u003e\"red-zone\"\u003c/tt\u003e**: The color for the red zone for Infinite Recharge at Home.\n\u003c/details\u003e\n\n## Shape Descriptions\n\n\u003cdetails\u003e\n  \u003csummary\u003eShapes are generally very simple descriptions of different types of geometries. Shape representations are\n  intended to be extended (i.e. new types of shapes added) if required to represent the game\n  arena for the season's competition.\u003c/summary\u003e\n\nEach shape is represented by a dictionary with a \u003ctt\u003e\"type\"\u003c/tt\u003e key\ndescribing the shape type, and then type-specific keys and values. These are the shape types, and the\ncorresponding keys that describe the currently supported shapes:\n- **\u003ctt\u003e\"circle\"\u003c/tt\u003e** - A circle of some radius centered at some location:\n  - **\u003ctt\u003e\"center\"\u003c/tt\u003e**: (required, [*x*,*y*]) The local X and Y coordinates, in meters, of the center\n    of the center of the circle. This is generally (0.0,0.0) and the position of the circle on the\n    field is specified when the circle is added to the field. More specifically, this is often used with a\n    circular/spherical game piece which can be placed anywhere on the field.\n  - **\u003ctt\u003e\"radius\"\u003c/tt\u003e**: (required, double) The radius, in meters.\n- **\u003ctt\u003e\"rect\"\u003c/tt\u003e** - An axis-aligned rectangle defined by lower-left and upper-right coordinates:\n  - **\u003ctt\u003e\"lower left\"\u003c/tt\u003e**:\n  - **\u003ctt\u003e\"upper right\"\u003c/tt\u003e**:\n- **\u003ctt\u003e\"polygon\"\u003c/tt\u003e** - An arbitrary closed polygon specified by a set of points. It is assumed that\n  there is a closing line segment between the first and last point:\n  - **\u003ctt\u003e\"points\"\u003c/tt\u003e**: A list of points describing the polygon, each point is described as a list\n    containing the [*x*,*y*] local X and Y coordinates, in meters, of the point. The points describe a\n    path that will be automatically closed.\n- **\u003ctt\u003e\"ring\"\u003c/tt\u003e** - A ring of some inner and outer diameter centered at some location:\n  - **\u003ctt\u003e\"center\"\u003c/tt\u003e**: (required, [*x*,*y*]) The local X and Y coordinates, in meters, of the center\n    of the center of the ring. This is generally (0.0,0.0) and the position of the ring on the\n    field is specified when the ring is added to the field. More specifically, this is often used with a\n    ring game piece which can be placed anywhere on the field.\n  - **\u003ctt\u003e\"ID\"\u003c/tt\u003e**: (required, double) the inner diameter of the ring, in meters.\n  - **\u003ctt\u003e\"OD\"\u003c/tt\u003e**: (required, double) the outer diameter of the ring, in meters.\n\u003c/details\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa05annex%2Fswervepathplanning","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fa05annex%2Fswervepathplanning","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fa05annex%2Fswervepathplanning/lists"}