{
    "componentChunkName": "component---src-components-page-template-jsx",
    "path": "/guides/main/maintaining-subsystems",
    "result": {"data":{"mdx":{"id":"6cc935db-8e8e-5b4f-a213-e2c67234a2d3","body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"section\": \"Guides\",\n  \"chapter\": \"Main Codebase\",\n  \"title\": \"Maintaining Subsystems\",\n  \"description\": \"How to maintain subsystems within the main codebase.\",\n  \"slug\": \"/guides/main/maintaining-subsystems\",\n  \"authors\": [\"Ysobel Sims (@ysims)\"]\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"This page details how to maintain various subsystems within the main codebase.\"), mdx(\"h2\", {\n    \"id\": \"odometry\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#odometry\",\n    \"aria-label\": \"odometry permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Odometry\"), mdx(\"h3\", {\n    \"id\": \"webots-live-error-tracking\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#webots-live-error-tracking\",\n    \"aria-label\": \"webots live error tracking permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Webots Live Error Tracking\"), mdx(\"p\", null, \"The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"nugus_controller\"), \" in Webots has functionality to send live odometry ground truth data to the robot. To use this\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"/guides/tools/webots-setup\"\n  }, \"Set up Webots and compile the NUWebots code\"), \" (you do not need the RoboCup set up).\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Run the \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"kid.wbt\"), \" world in Webots.\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Run \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"webots/keyboardwalk\"), \" in NUbots. \", mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"/guides/main/getting-started\"\n  }, \"See the Getting Started page to set up the NUbots codebase\"), \".\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Run \", mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"/guides/main/getting-started#get-build-and-run-nusight\"\n  }, \"NUsight\"), \" or \", mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://github.com/NUbots/NUbots/tree/main/module/network/PlotJuggler/README.md\"\n  }, \"PlotJuggler\"), \" and observe the graphs for the robot's prediction, the ground truth and the error of the torso's real rotation and translation relative to world.\")), mdx(\"h2\", {\n    \"id\": \"vision\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#vision\",\n    \"aria-label\": \"vision permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Vision\"), mdx(\"p\", null, \"The accuracy of the vision system is reliant on the accuracy of odometry and kinematics because they affect the placement of the mesh and green horizon. It is important that these systems work reasonable well otherwise the robot may have issues detecting objects.\"), mdx(\"p\", null, \"If you are using Webots, you can turn on odometry ground truth in the SensorFilter module. Go to the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SensorFilter.yaml\"), \" configuration file and set the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"filtering_method\"), \" to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"GROUND_TRUTH\"), \". This will use the ground truth odometry from Webots instead of the odometry from the robot. This is useful for testing the vision system without having to worry about odometry errors.\"), mdx(\"h3\", {\n    \"id\": \"dataset-generation\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#dataset-generation\",\n    \"aria-label\": \"dataset generation permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Dataset Generation\"), mdx(\"p\", null, \"Synthetic and semi-synthetic training data for vision can be generated using \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/system/tools/nupbr\"\n  }, \"NUpbr\"), \". Pre-generated datasets for training the Visual Mesh are on the \", mdx(\"abbr\", {\n    title: \"Network-Attached Storage\"\n  }, \"NAS\"), \" in the lab.\"), mdx(\"h4\", {\n    \"id\": \"nupbr\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#nupbr\",\n    \"aria-label\": \"nupbr permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"NUpbr\"), mdx(\"p\", null, \"NUpbr is a Physically Based Rendering tool created in Blender. It creates semi-synthetic images with corresponding \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://paperswithcode.com/task/semantic-segmentation\"\n  }, \"segmentation masks\"), \" for training.\"), mdx(\"p\", null, \"Information on NUpbr is available on the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/system/tools/nupbr\"\n  }, \"NUbook page\"), \", \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/guides/tools/nupbr-guide\"\n  }, \"NUbook guide\"), \" and the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/NUbots/NUpbr\"\n  }, \"NUpbr GitHub repository\"), \".\"), mdx(\"h4\", {\n    \"id\": \"setting-up-the-data\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#setting-up-the-data\",\n    \"aria-label\": \"setting up the data permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Setting Up The Data\"), mdx(\"p\", null, \"The Visual Mesh requires raw images, segmentation masks and metadata, as outlined on the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/Fastcode/VisualMesh/blob/main/readme/quickstart.md#gathering-the-data\"\n  }, \"Quick Start Guide\"), \". NUpbr can provide all of these as output, and premade data is available on the NAS. The data then needs to be converted to the tfrecord format using a script on the Visual Mesh repository. \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/Fastcode/VisualMesh/blob/main/readme/quickstart.md#building-the-dataset\"\n  }, \"The Quick Start Guide\"), \" describes how to use it.\"), mdx(\"h3\", {\n    \"id\": \"the-visual-mesh\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#the-visual-mesh\",\n    \"aria-label\": \"the visual mesh permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"The Visual Mesh\"), mdx(\"h4\", {\n    \"id\": \"training-and-testing\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#training-and-testing\",\n    \"aria-label\": \"training and testing permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Training and Testing\"), mdx(\"p\", null, \"Go to the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/guides/tools/visualmesh\"\n  }, \"NUbook Visual Mesh Getting Started guide\"), \" to find out how to train and test a network, with an example dummy dataset.\"), mdx(\"h4\", {\n    \"id\": \"exporting-configuration\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#exporting-configuration\",\n    \"aria-label\": \"exporting configuration permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Exporting Configuration\"), mdx(\"p\", null, \"The resulting network should be exported to a \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://yaml.org/\"\n  }, \"yaml\"), \" file and added to the NUbots codebase, by completing the following steps.\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Create a base configuration file. Example yaml files can be found \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/Fastcode/VisualMesh/blob/main/example/model.yaml\"\n  }, \"in the Visual Mesh repository\"), \" and \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/NUbots/NUbots/blob/main/module/vision/VisualMesh/data/config/VisualMesh.yaml\"\n  }, \"in the NUbots repository\"), \".\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Export the weights of your trained Mesh to this configuration file using the following command, where \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"<output_dir>\"), \" is the directory of the configuration file:\"), mdx(\"pre\", {\n    parentName: \"li\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-bash\"\n  }, \"./mesh.py export <output_dir>\\n\"))), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Add this configuration file to the NUbots repository in the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/NUbots/NUbots/tree/main/module/vision/VisualMesh/data/config/networks\"\n  }, \"VisualMesh module\"), \". Replace or add a configuration file depending on the use case of the Mesh - \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"RobocupNetwork.yaml\"), \" is for soccer playing on the real robot and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"WebotsNetwork\"), \" is for soccer playing in the Webots simulator. View the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/guides/general/git\"\n  }, \"Git Guide\"), \" for information on using Git and submitting this change in a pull request.\"))), mdx(\"h3\", {\n    \"id\": \"camera-calibration\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#camera-calibration\",\n    \"aria-label\": \"camera calibration permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Camera Calibration\"), mdx(\"p\", null, \"The vision system cannot work optimally if the cameras are not calibrated correctly. \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/system/subsystems/input\"\n  }, \"The input page\"), \" describes the camera parameters that can be calibrated.\"), mdx(\"p\", null, \"An automatic camera calibration tool is available in the NUbots repository. See the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/guides/main/camera-calibration\"\n  }, \"camera calibration guide\"), \" to find out how to use this tool.\"), mdx(\"h3\", {\n    \"id\": \"testing\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#testing\",\n    \"aria-label\": \"testing permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Testing\"), mdx(\"p\", null, \"After updating the Visual Mesh in the NUbots repository, it should be tested before merging. Refer to the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/guides/main/getting-started\"\n  }, \"Getting Started guide\"), \" for assistance for the following steps.\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Build the code, ensuring \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ROLE_test-visualmesh\"), \" is set to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ON\"), \" in \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"./b configure -i\"), \", and install it to the robot. Ensure the new configuration file is installed by using the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"-cu\"), \" or \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"-co\"), \" options when installing - check out the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/system/foundations/build-system#install\"\n  }, \"Build System page\"), \" to find out more about options when installing onto the robot.\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"When your new Visual Mesh is installed onto the robot, connect to the robot using:\"), mdx(\"pre\", {\n    parentName: \"li\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-bash\"\n  }, \"ssh nubots@<address>\\n\"))), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Ensure the robot is sending vision data:\"), mdx(\"pre\", {\n    parentName: \"li\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-bash\"\n  }, \"nano config/NetworkForwarder.yaml\\n\")), mdx(\"p\", {\n    parentName: \"li\"\n  }, \"CompressedImage, Balls, Goals and GreenHorizon should be on. Run NUsight using \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"yarn prod\"), \" and navigate to the NUsight page in your browser. More on NUsight can be found on \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/system/tools/nusight\"\n  }, \"the NUsight NUbook page\"), \". If you have not already set up and built NUsight, refer to the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/guides/main/getting-started\"\n  }, \"Getting Started page\"), \".\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Run the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"test/visualmesh\"), \" role\"), mdx(\"pre\", {\n    parentName: \"li\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-bash\"\n  }, \"./test/visualmesh\\n\"))), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Wait for the cameras to load and then watch the Vision tab in NUsight. To determine if the output is correct, consult the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/system/subsystems/vision\"\n  }, \"vision page\"), \" for images of the expected output.\"))), mdx(\"p\", null, \"To see the Visual Mesh itself in NUsight, you will need to enable the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"message.vision.VisualMesh\"), \" message in the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"NetworkForwarder.yaml\"), \" file. Most of the time the networking should work, but sometimes there may be issues since the Visual Mesh data is large. If there are issues with seeing the Visual Mesh output in NUsight, you will need to log the data and run it back in NUsight using DataPlayback. Use the steps in the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/guides/main/data-recording-playback\"\n  }, \"DataLogging and DataPlayback guide\"), \" to record and playback data. Adjust the instructions for our purpose using the following hints:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"In step 1 of Recording Data, use the \", mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://github.com/NUbots/NUbots/blob/main/roles/test/visualmesh.role\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"a\"\n  }, \"test/visualmesh\")), \" role to record the data.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"In step 2 of Recording Data and step 4 of Playing Back Data, set \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"message.output.CompressedImage\"), \" to \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"true\"), \" and add \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"message.vision.VisualMesh: true\"), \" in both \", mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://github.com/NUbots/NUbots/blob/main/module/support/logging/DataLogging/data/config/DataLogging.yaml\"\n  }, \"DataLogging.yaml\"), \" and \", mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://github.com/NUbots/NUbots/blob/main/module/support/logging/DataPlayback/data/config/DataPlayback.yaml\"\n  }, \"DataPlayback.yaml\"), \".\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"In steps 1, 2 and 5 of Playing Back Data, use the \", mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://github.com/NUbots/NUbots/blob/main/roles/data/playback.role\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"a\"\n  }, \"playback\")), \" role to playback the data, without changes.\")), mdx(\"h3\", {\n    \"id\": \"tuning-detectors\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#tuning-detectors\",\n    \"aria-label\": \"tuning detectors permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Tuning Detectors\"), mdx(\"p\", null, \"Potentially, the Visual Mesh had positive results after training, but when used on a robot it performed poorly. In this case, the detectors may need tuning.\"), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/NUbots/NUbots/blob/main/module/vision/BallDetector/data/config/BallDetector.yaml\"\n  }, \"BallDetector.yaml\"), \" and \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/NUbots/NUbots/blob/main/module/vision/GoalDetector/data/config/GoalDetector.yaml\"\n  }, \"GoalDetector.yaml\"), \" contain the values for tuning the ball and goal detectors respectively.\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Build and install the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"test/visualmesh\"), \" role to a robot.\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"SSH onto the robot.\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Enable NUsight messages on the robot by running\"), mdx(\"pre\", {\n    parentName: \"li\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-bash\"\n  }, \"nano config/NetworkForwarder.yaml\\n\")), mdx(\"p\", {\n    parentName: \"li\"\n  }, \"and set \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"message.vision.Balls\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"message.vision.Goals\"), \" to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"true\"), \".\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Run NUsight using \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"yarn prod\"), \" on a computer. Set up NUsight using the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/guides/main/getting-started\"\n  }, \"Getting Started page\"), \" if necessary.\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Run \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"./test/visualmesh\"), \" on the robot.\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Alter the configuration file for the detectors while simultaneously running the binary on the robot. In a new terminal, SSH onto the robot again and run:\"), mdx(\"pre\", {\n    parentName: \"li\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-bash\"\n  }, \"nano config/BallDetector.yaml\\n\")), mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Change the values and upon saving, the changes will be used immediately by the robot \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"without\"), \" needing to rebuild or rerun the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"./test/visualmesh\"), \" binary.\")), mdx(\"li\", {\n    parentName: \"ol\"\n  }, mdx(\"p\", {\n    parentName: \"li\"\n  }, \"Repeat #6 for the goal detector by running\"), mdx(\"pre\", {\n    parentName: \"li\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-bash\"\n  }, \"nano config/GoalDetector.yaml\\n\")))), mdx(\"p\", null, \"In general, it might be useful to adjust the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"confidence_threshold\"), \" on both detectors to improve the results. Other variables may give better results with different values, except for \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"log_level\"), \" and the covariances (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"goal_projection_covariance\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ball_angular_cov\"), \").\"), mdx(\"h2\", {\n    \"id\": \"benchmarks\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h2\",\n    \"href\": \"#benchmarks\",\n    \"aria-label\": \"benchmarks permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Benchmarks\"), mdx(\"p\", null, \"Benchmark results for various aspects of the vision system. These benchmarks tell us how well the system performs and if a new method improves the system. In general, benchmarks should be recalculated when there may be a change in the results. The benchmarks should be verified every six months if no changes have been made, to ensure unrelated changes did not cause issues.\"), mdx(\"h3\", {\n    \"id\": \"visual-mesh\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#visual-mesh\",\n    \"aria-label\": \"visual mesh permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Visual Mesh\"), mdx(\"p\", null, \"Test results from the Visual Mesh, broken down for each class with precision and recall values. The complete output from the Visual Mesh test can be found on the Google Drive, in the \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://drive.google.com/drive/folders/1OKdhV-dKLGJXYNLWaIw9lQ_8xBJf0cfT\"\n  }, \"Benchmarks folder\"), \" with a date. As well as the information provided on this page, the output contains graphs for each class for \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://towardsdatascience.com/the-f1-score-bec2bbc38aa6\"\n  }, \"F1\"), \", \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://rvprasad.medium.com/informedness-and-markedness-20e3f54d63bc\"\n  }, \"Informedness, Markedness\"), \", \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://en.wikipedia.org/wiki/Phi_coefficient\"\n  }, \"MCC\"), \", \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://en.wikipedia.org/wiki/Mutual_information\"\n  }, \"MI\"), \", \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://medium.com/@douglaspsteen/precision-recall-curves-d32e5b290248\"\n  }, \"PR\"), \", \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://en.wikipedia.org/wiki/Precision_and_recall\"\n  }, \"Precision, Recall\"), \", \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://developers.google.com/machine-learning/crash-course/classification/roc-and-auc\"\n  }, \"ROC\"), \".\"), mdx(\"p\", null, \"Visual Mesh benchmarks should be updated when a network is trained and added to the NUbots codebase, or if the Visual Mesh code updates in a way that would effect these values.\"), mdx(\"h4\", {\n    \"id\": \"real-world\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#real-world\",\n    \"aria-label\": \"real world permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Real World\"), mdx(\"p\", null, \"Coming soon...\"), mdx(\"h4\", {\n    \"id\": \"webots\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#webots\",\n    \"aria-label\": \"webots permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Webots\"), mdx(\"p\", null, \"Full metrics can be found in the Benchmarks folder on the NUbots Google Drive. Test dataset can be found on the NAS device. Should be updated if a new Webots Visual Mesh network replaces the old network, or if the RoboCup environment in Webots changes (a new network should be trained in this case).\"), mdx(\"details\", null, mdx(\"summary\", null, \"Ball\"), mdx(\"p\", null, \"Precision: 0.9552730904880183\"), mdx(\"p\", null, \"Recall: 0.9474011799668628\"), mdx(\"p\", null, \"Predicted Ball samples are really:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Ball: 95.527%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Goal: 0.198%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Line: 1.132%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Field: 2.163%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Robot: 0.902%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Environment: 0.078%\")), mdx(\"p\", null, \"Real Ball samples are predicted as:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Ball: 94.740%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Goal: 0.506%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Line: 1.528%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Field: 1.077%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Robot: 2.031%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Environment: 0.117%\"))), mdx(\"details\", null, mdx(\"summary\", null, \"Goal\"), mdx(\"p\", null, \"Precision: 0.9744150403727407\"), mdx(\"p\", null, \"Recall: 0.9818396740798292\"), mdx(\"p\", null, \"Predicted Goal samples are really:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Ball: 0.006%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Goal: 97.442%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Line: 0.176%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Field: 0.462%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Robot: 0.100%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Environment: 1.814%\")), mdx(\"p\", null, \"Real Goal samples are predicted as:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Ball: 0.002%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Goal: 98.184%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Line: 0.146%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Field: 0.210%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Robot: 0.056%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Environment: 1.402%\"))), mdx(\"details\", null, mdx(\"summary\", null, \"Line\"), mdx(\"p\", null, \"Precision: 0.9639229445906177\"), mdx(\"p\", null, \"Recall: 0.9643768381560178\"), mdx(\"p\", null, \"Predicted Line samples are really:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Ball: 0.036%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Goal: 0.280%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Line: 96.392%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Field: 2.885%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Robot: 0.365%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Environment: 0.042%\")), mdx(\"p\", null, \"Real Line samples are predicted as:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Ball: 0.026%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Goal: 0.341%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Line: 96.438%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Field: 2.910%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Robot: 0.283%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Environment: 0.002%\"))), mdx(\"details\", null, mdx(\"summary\", null, \"Field\"), mdx(\"p\", null, \"Precision: 0.9970544868367878\"), mdx(\"p\", null, \"Recall: 0.9969097621584649\"), mdx(\"p\", null, \"Predicted Field samples are really:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Ball: 0.001%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Goal: 0.017%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Line: 0.120%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Field: 99.705%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Robot: 0.074%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Environment: 0.082%\")), mdx(\"p\", null, \"Real Field samples are predicted as:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Ball: 0.002%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Goal: 0.037%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Line: 0.119%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Field: 99.691%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Robot: 0.087%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Environment: 0.064%\"))), mdx(\"details\", null, mdx(\"summary\", null, \"Robot\"), mdx(\"p\", null, \"Precision: 0.9772128370131125\"), mdx(\"p\", null, \"Recall: 0.9823020939044803\"), mdx(\"p\", null, \"Predicted Robot samples are really:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Ball: 0.006%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Goal: 0.015%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Line: 0.038%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Field: 0.283%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Robot: 97.721%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Environment: 1.936%\")), mdx(\"p\", null, \"Real Robot samples are predicted as:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Ball: 0.003%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Goal: 0.026%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Line: 0.050%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Field: 0.244%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Robot: 98.230%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Environment: 1.447%\"))), mdx(\"details\", null, mdx(\"summary\", null, \"Environment\"), mdx(\"p\", null, \"Precision: 0.9977592789558581\"), mdx(\"p\", null, \"Recall: 0.9970136589036935\"), mdx(\"p\", null, \"Predicted Environment samples are really:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Ball: 0.000%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Goal: 0.040%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Line: 0.000%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Field: 0.023%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Robot: 0.160%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Environment: 99.776%\")), mdx(\"p\", null, \"Real Environment samples are predicted as:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Ball: 0.000%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Goal: 0.053%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Line: 0.001%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Field: 0.030%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Robot: 0.215%\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Environment: 99.701%\"))), mdx(\"h3\", {\n    \"id\": \"object-positions\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h3\",\n    \"href\": \"#object-positions\",\n    \"aria-label\": \"object positions permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Object Positions\"), mdx(\"p\", null, \"Post-processing heuristics use Visual Mesh results to find the position of likely objects in the image. These benchmarks are the error between the real position and the calculated position in the three-dimensional world. This should be updated if the post-processing heuristics are updated, or if the Visual Mesh output changes.\"), mdx(\"h4\", {\n    \"id\": \"real-world-1\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#real-world-1\",\n    \"aria-label\": \"real world 1 permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Real World\"), mdx(\"p\", null, \"Coming soon...\"), mdx(\"h4\", {\n    \"id\": \"webots-1\",\n    \"style\": {\n      \"position\": \"relative\"\n    }\n  }, mdx(\"a\", {\n    parentName: \"h4\",\n    \"href\": \"#webots-1\",\n    \"aria-label\": \"webots 1 permalink\",\n    \"className\": \"anchor before\"\n  }, mdx(\"svg\", {\n    parentName: \"a\",\n    \"aria-hidden\": \"true\",\n    \"focusable\": \"false\",\n    \"height\": \"16\",\n    \"version\": \"1.1\",\n    \"viewBox\": \"0 0 16 16\",\n    \"width\": \"16\"\n  }, mdx(\"path\", {\n    parentName: \"svg\",\n    \"fillRule\": \"evenodd\",\n    \"d\": \"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"\n  }))), \"Webots\"), mdx(\"p\", null, \"Coming soon...\"));\n}\n;\nMDXContent.isMDXComponent = true;","tableOfContents":{"items":[{"url":"#odometry","title":"Odometry","items":[{"url":"#webots-live-error-tracking","title":"Webots Live Error Tracking"}]},{"url":"#vision","title":"Vision","items":[{"url":"#dataset-generation","title":"Dataset Generation"},{"url":"#the-visual-mesh","title":"The Visual Mesh"},{"url":"#camera-calibration","title":"Camera Calibration"},{"url":"#testing","title":"Testing"},{"url":"#tuning-detectors","title":"Tuning Detectors"}]},{"url":"#benchmarks","title":"Benchmarks","items":[{"url":"#visual-mesh","title":"Visual Mesh"},{"url":"#object-positions","title":"Object Positions"}]}]},"frontmatter":{"section":"Guides","chapter":"Main Codebase","title":"Maintaining Subsystems","description":"How to maintain subsystems within the main codebase.","keywords":null,"slug":"/guides/main/maintaining-subsystems","hidden":null},"childNUbookContributions":{"authors":[{"name":"Ysobel Sims","username":"ysims"}],"lastCommit":{"date":"2024-10-06T00:43:48.000Z","hash":"092ed4d086a639f36881702b6d6790285d813e52"}}}},"pageContext":{"mdxPath":"src/book/03-guides/01-main-codebase/04-maintaining-subsystems.mdx","id":"6cc935db-8e8e-5b4f-a213-e2c67234a2d3","next":{"chapter":"Main Codebase","title":"Data Recording and Playback","description":"How to record data from a running system and play it back.","slug":"/guides/main/data-recording-playback","hidden":null},"previous":{"chapter":"Main Codebase","title":"Running and Tuning Scripts","description":"How to tune and run scripts.","slug":"/guides/main/tuning-and-running-scripts","hidden":null},"menu":[{"title":"Team","slug":"/team/introduction","chapters":[{"title":"Introduction","slug":"/team/introduction","pages":[{"title":"Introduction to NUbots","slug":"/team/introduction","hidden":null},{"title":"Areas of Research","slug":"/team/areas-of-research","hidden":null},{"title":"Current Team","slug":"/team/current-members","hidden":null}],"hidden":false},{"title":"Joining the Team","slug":"/team/how-we-work","pages":[{"title":"How We Work","slug":"/team/how-we-work","hidden":null},{"title":"How to Join NUbots","slug":"/team/how-to-join","hidden":null},{"title":"Lab Induction","slug":"/team/induction","hidden":null}],"hidden":false},{"title":"Community","slug":"/team/sponsors","pages":[{"title":"Sponsors","slug":"/team/sponsors","hidden":null},{"title":"Connect","slug":"/team/connect","hidden":null}],"hidden":false},{"title":"History","slug":"/team/history","pages":[{"title":"Team History","slug":"/team/history","hidden":null},{"title":"Past Members","slug":"/team/past-members","hidden":null},{"title":"Publications","slug":"/team/publications","hidden":null}],"hidden":false},{"title":"RoboCup","slug":"/team/robocup","pages":[{"title":"RoboCup","slug":"/team/robocup","hidden":null},{"title":"Resources","slug":"/team/robocup/resources","hidden":null},{"title":"Debriefs","slug":"/team/robocup/debriefs","hidden":null}],"hidden":false}],"hidden":false},{"title":"System","slug":"/system/foundations/overview","chapters":[{"title":"Foundations","slug":"/system/foundations/overview","pages":[{"title":"Overview","slug":"/system/foundations/overview","hidden":null},{"title":"Build System","slug":"/system/foundations/build-system","hidden":null},{"title":"Continuous Integration","slug":"/system/foundations/ci-system","hidden":null},{"title":"NUClear","slug":"/system/foundations/nuclear","hidden":null},{"title":"Mathematics","slug":"/system/foundations/mathematics","hidden":null},{"title":"Configuration and Script System","slug":"/system/foundations/config-script","hidden":null},{"title":"Director","slug":"/system/foundations/director","hidden":null}],"hidden":false},{"title":"Subsystems","slug":"/system/subsystems/input","pages":[{"title":"Input","slug":"/system/subsystems/input","hidden":null},{"title":"Odometry","slug":"/system/subsystems/odometry","hidden":null},{"title":"Localisation","slug":"/system/subsystems/localisation","hidden":null},{"title":"Motion","slug":"/system/subsystems/motion","hidden":null},{"title":"Vision","slug":"/system/subsystems/vision","hidden":null},{"title":"Behaviour","slug":"/system/subsystems/behaviour","hidden":null},{"title":"Logging","slug":"/system/subsystems/logging","hidden":null}],"hidden":false},{"title":"Tools","slug":"/system/tools/nusight","pages":[{"title":"NUsight","slug":"/system/tools/nusight","hidden":null},{"title":"NUbook","slug":"/system/tools/nubook","hidden":null},{"title":"NUpbr","slug":"/system/tools/nupbr","hidden":null},{"title":"NUgan","slug":"/system/tools/nugan","hidden":null},{"title":"System Configuration","slug":"/system/tools/system_configuration","hidden":null},{"title":"NatNet SDK","slug":"/system/tools/natnet_sdk","hidden":null}],"hidden":false},{"title":"Hardware","slug":"/system/hardware/overview","pages":[{"title":"Overview and Specifications","slug":"/system/hardware/overview","hidden":null}],"hidden":false},{"title":"Modules","slug":"/system/modules/actuation/","pages":[{"title":"Actuation","slug":"/system/modules/actuation/","hidden":null},{"title":"Extension","slug":"/system/modules/extension/","hidden":null},{"title":"Input","slug":"/system/modules/input/","hidden":null},{"title":"Localisation","slug":"/system/modules/localisation/","hidden":null},{"title":"Nbs","slug":"/system/modules/nbs/","hidden":null},{"title":"Network","slug":"/system/modules/network/","hidden":null},{"title":"Output","slug":"/system/modules/output/","hidden":null},{"title":"Planning","slug":"/system/modules/planning/","hidden":null},{"title":"Platform","slug":"/system/modules/platform/","hidden":null},{"title":"Purpose","slug":"/system/modules/purpose/","hidden":null},{"title":"Skill","slug":"/system/modules/skill/","hidden":null},{"title":"Strategy","slug":"/system/modules/strategy/","hidden":null},{"title":"Support","slug":"/system/modules/support/","hidden":null},{"title":"Tools","slug":"/system/modules/tools/","hidden":null},{"title":"Vision","slug":"/system/modules/vision/","hidden":null}],"hidden":false}],"hidden":false},{"title":"Guides","slug":"/guides/main/getting-started","chapters":[{"title":"Main Codebase","slug":"/guides/main/getting-started","pages":[{"title":"Getting Started","slug":"/guides/main/getting-started","hidden":null},{"title":"NUClear","slug":"/guides/main/nuclear-tutorial","hidden":null},{"title":"Running and Tuning Scripts","slug":"/guides/main/tuning-and-running-scripts","hidden":null},{"title":"Maintaining Subsystems","slug":"/guides/main/maintaining-subsystems","hidden":null},{"title":"Data Recording and Playback","slug":"/guides/main/data-recording-playback","hidden":null},{"title":"Camera Calibration","slug":"/guides/main/camera-calibration","hidden":null},{"title":"Onboarding Workshop","slug":"/guides/main/onboarding","hidden":null}],"hidden":false},{"title":"Tools","slug":"/guides/tools/nusight-contribution","pages":[{"title":"Contributing to NUsight","slug":"/guides/tools/nusight-contribution","hidden":null},{"title":"Setting Up Webots","slug":"/guides/tools/webots-setup","hidden":null},{"title":"Visual Mesh Getting Started","slug":"/guides/tools/visualmesh","hidden":null},{"title":"Using NUpbr","slug":"/guides/tools/nupbr-guide","hidden":null},{"title":"GameController Setup","slug":"/guides/tools/gamecontroller","hidden":null}],"hidden":false},{"title":"Hardware","slug":"/guides/hardware/working-with-robots","pages":[{"title":"Working with Robots","slug":"/guides/hardware/working-with-robots","hidden":null},{"title":"Flashing a Robot","slug":"/guides/hardware/flashing","hidden":null},{"title":"Servo Setup and Calibration","slug":"/guides/hardware/servo-calibration","hidden":null},{"title":"Batteries","slug":"/guides/hardware/batteries","hidden":null},{"title":"DARwIn Op2 Robot Restoration and Calibration Guide","slug":"/guides/hardware/darwin-op2-guide","hidden":null}],"hidden":false},{"title":"General","slug":"/guides/general/learning-resources","pages":[{"title":"Learning Resources","slug":"/guides/general/learning-resources","hidden":null},{"title":"Contribution Workflow","slug":"/guides/general/contribute","hidden":null},{"title":"RoboCup Setup","slug":"/guides/general/robocup-setup","hidden":null},{"title":"Troubleshooting","slug":"/guides/general/troubleshooting","hidden":null},{"title":"Code Conventions","slug":"/guides/general/code-conventions","hidden":null},{"title":"Glossary","slug":"/guides/general/glossary","hidden":null}],"hidden":false}],"hidden":false},{"title":"Kitchen Sink","slug":"/kitchen-sink/headers","chapters":[{"title":"Markdown","slug":"/kitchen-sink/headers","pages":[{"title":"Headers","slug":"/kitchen-sink/headers","hidden":true},{"title":"Formatting and Paragraphs","slug":"/kitchen-sink/formatting-and-paragraphs","hidden":true},{"title":"Blockquotes","slug":"/kitchen-sink/blockquotes","hidden":true},{"title":"Alerts","slug":"/kitchen-sink/alerts","hidden":true},{"title":"Images","slug":"/kitchen-sink/images","hidden":true},{"title":"Lists","slug":"/kitchen-sink/lists","hidden":true},{"title":"Code","slug":"/kitchen-sink/code","hidden":true},{"title":"Math","slug":"/kitchen-sink/math","hidden":true},{"title":"Table of Contents","slug":"/kitchen-sink/table-of-contents","hidden":true},{"title":"Tables","slug":"/kitchen-sink/tables","hidden":true},{"title":"Collapsible Content","slug":"/kitchen-sink/collapsible","hidden":true},{"title":"GraphViz Diagrams","slug":"/kitchen-sink/graphviz-diagrams","hidden":true},{"title":"Referencing","slug":"/kitchen-sink/referencing","hidden":true}],"hidden":true}],"hidden":true}],"references":null,"hidden":null}},
    "staticQueryHashes": ["3715292327","445096115","466146812"]}