{"id":33928,"date":"2026-05-18T05:00:00","date_gmt":"2026-05-18T03:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=33928"},"modified":"2026-05-26T09:44:51","modified_gmt":"2026-05-26T07:44:51","slug":"building-an-rtk-rover-web-controlled-precision-navigation","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/en\/building-an-rtk-rover-web-controlled-precision-navigation\/","title":{"rendered":"Building an RTK Rover: Web-controlled precision navigation"},"content":{"rendered":"\n<p>If you have ever been curious about how precision navigation systems actually function behind the scenes, or if you have considered incorporating high-accuracy positioning technology into one of your own projects but were not sure where to start, I believe this article will provide valuable input and practical guidance that you will find both interesting and useful.<\/p>\n\n\n\n<p>My goal was to develop an integrated system comprising two main components: a high-precision GNSS (Global Navigation Satellite System) receiver \u2013 Rover, and a web-based control application \u2013 GNSS RTK Planner. For the Rover, I selected an RTK (Real Time Kinematic) solution to achieve centimeter-level positioning accuracy in real time. The GNSS RTK Planner was designed with an interactive mapping interface that enables users to create navigation paths (Trails) and transmit them to connected Rovers, which are tasked with navigating the specified route.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><strong>GNSS and RTK<\/strong><\/strong><\/h2>\n\n\n\n<p>If it comes to navigation, we usually say &#8216;GPS&#8217;, which is actually partially correct. But the general name of the navigation systems which we widely use in our mobiles, cars, etc., is GNSS (Global Navigation Satellite System). It is a generic term for satellite-based navigation systems that provide positioning and timing services globally. Currently, four global systems are available:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>GPS (USA),<\/li>\n\n\n\n<li>GLONASS (Russia),<\/li>\n\n\n\n<li>Galileo (Europe),<\/li>\n\n\n\n<li>and BeiDou (China).<\/li>\n<\/ul>\n\n\n\n<p>And yes, besides global systems, there are local systems like QZSS&nbsp;(Japan) or NavIC&nbsp;(India) which operate over a desired region only.<\/p>\n\n\n\n<p>I&#8217;m not going to describe how the GNSS system works (there are thousands of books and articles about this topic). But one important thing, especially when it comes to the selection of a GNSS RTK receiver, is the type of signals it supports. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Frequency bands<\/strong><\/h3>\n\n\n\n<p>These days, GNSS satellites can transmit on multiple frequency bands. But currently, the most popular for civilian usage are these three (I used GPS naming convention):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>L1 band \u2013 which is a primary civilian signal (every simple GNSS receiver supports it).<\/li>\n\n\n\n<li>L2 band \u2013 originally military (GPS), now used for advanced civilian applications.<\/li>\n\n\n\n<li>L5 band \u2013 newer civilian safety-of-life signal (higher power compared to L2, wider bandwidth, the band is less interfered with by other systems).<\/li>\n<\/ul>\n\n\n\n<p>A little bit more comprehensive description of all available frequency bands used in navigation systems is present in the diagram below. Each GNSS provides its own naming convention, slightly different frequencies, or even different modulation types. Fortunately, GNSS antennas and receivers usually support all these different solutions.<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;uploadedSrc&quot;:&quot;https:\\\/\\\/sii.pl\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/image1.jpeg&quot;,&quot;figureClassNames&quot;:&quot;wp-block-image aligncenter size-large&quot;,&quot;figureStyles&quot;:null,&quot;imgClassNames&quot;:&quot;wp-image-33914&quot;,&quot;imgStyles&quot;:null,&quot;targetWidth&quot;:1920,&quot;targetHeight&quot;:750,&quot;scaleAttr&quot;:false,&quot;ariaLabel&quot;:&quot;Enlarge image: GNSS frequency bands&quot;,&quot;alt&quot;:&quot;GNSS frequency bands&quot;}\" data-wp-interactive=\"core\/image\" class=\"wp-block-image aligncenter size-large wp-lightbox-container\"><img decoding=\"async\" width=\"1024\" height=\"400\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image1-1024x400.jpeg\" alt=\"GNSS frequency bands\" class=\"wp-image-33914\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image1-1024x400.jpeg 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image1-300x117.jpeg 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image1-768x300.jpeg 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image1-1536x600.jpeg 1536w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image1.jpeg 1920w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge image: GNSS frequency bands\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on-async--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"context.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"context.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Fig. 1 GNSS frequency bands (<a href=\"https:\/\/gnss.store\/blogs\/gnss-antennas\/l1-l2-l5-l3-and-simply-l-frequency-bands?srsltid=AfmBOoqhs-UOlhca71YGDe70ZSLuyZk3jIEk5hZJPom54cydqnL_mq2a\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" ><\/a><a href=\"https:\/\/gnss.store\/blogs\/gnss-antennas\/l1-l2-l5-l3-and-simply-l-frequency-bands?srsltid=AfmBOoqhs-UOlhca71YGDe70ZSLuyZk3jIEk5hZJPom54cydqnL_mq2a\" rel=\"nofollow\" >source<\/a>)<\/figcaption><\/figure>\n\n\n\n<p>Each frequency carries different codes and navigation messages. Using multiple frequencies helps correct for atmospheric delays, especially ionospheric interference. RTK systems can operate on a single band (L1), but dual-band (L1 + L2 or L1 + L5) or triple-band systems achieve significantly better stability and precision. This is why I decided to use a GNSS RTK receiver that supports L1 and L2.<\/p>\n\n\n\n<p>Not all satellites use all these frequencies; some satellites may support only two of these three signals (usually older satellites launched many years ago). The table below shows a simplified set of available satellites and types of signals they emit (status for 2025):<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td class=\"has-text-align-center\" data-align=\"center\"><strong>System&nbsp;<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\"><strong>Total<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\"><strong>L1 or equivalent<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\"><strong>L2&nbsp;or equivalent<\/strong><\/td><td class=\"has-text-align-center\" data-align=\"center\"><strong>L5 or equivalent<\/strong><\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">GPS<\/td><td class=\"has-text-align-center\" data-align=\"center\">31<\/td><td class=\"has-text-align-center\" data-align=\"center\">31<\/td><td class=\"has-text-align-center\" data-align=\"center\">31<\/td><td class=\"has-text-align-center\" data-align=\"center\">24<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">Galileo<\/td><td class=\"has-text-align-center\" data-align=\"center\">28<\/td><td class=\"has-text-align-center\" data-align=\"center\">28<\/td><td class=\"has-text-align-center\" data-align=\"center\">28<\/td><td class=\"has-text-align-center\" data-align=\"center\">28<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">BeiDou<\/td><td class=\"has-text-align-center\" data-align=\"center\">44<\/td><td class=\"has-text-align-center\" data-align=\"center\">29<\/td><td class=\"has-text-align-center\" data-align=\"center\">15&nbsp;<\/td><td class=\"has-text-align-center\" data-align=\"center\">29&nbsp;<\/td><\/tr><tr><td class=\"has-text-align-center\" data-align=\"center\">GLONASS<\/td><td class=\"has-text-align-center\" data-align=\"center\">24<\/td><td class=\"has-text-align-center\" data-align=\"center\">24<\/td><td class=\"has-text-align-center\" data-align=\"center\">24<\/td><td class=\"has-text-align-center\" data-align=\"center\">&#8211;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>System improvement<\/strong><\/h3>\n\n\n\n<p>The civilian classic GNSS system provides relatively low precision \u2013 up to ~7 meters under very good conditions (<a href=\"https:\/\/www.faa.gov\/about\/office_org\/headquarters_offices\/ato\/service_units\/techops\/navservices\/gnss\/gps\/howitworks\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >Satellite Navigation \u2013 GPS &#8211; How It Works | Federal Aviation Administration<\/a>). Therefore, improvements to this system were started to be developed; here are some of them:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SABS&nbsp; (Satellite-Based Augmentation Systems) like systems broadcast correction data via geostationary satellites, improving accuracy to 1-3 meters without additional ground equipment.<\/li>\n\n\n\n<li>DGPS (Differential GPS) uses a nearby reference station to calculate and broadcast code-based corrections, achieving sub-meter to 1-2 meter accuracy depending on distance from the base station.<\/li>\n\n\n\n<li>PPP (Precise Point Positioning) uses precise satellite orbit and clock corrections (delivered via internet or satellite) to achieve decimeter to centimeter-level accuracy worldwide, though it requires longer convergence time (10-30 minutes) compared to RTK near-instant fixes.<\/li>\n\n\n\n<li>RTK (Real-Time Kinematic) employs carrier phase measurements and real-time corrections from a base station to achieve centimeter-level accuracy (1-3 cm), but requires a continuous data link and works best within 10-30 km of the base. Not every standard GNSS receiver supports such functionality. In this project, I used PX1122R, which works on the L1 and L2 bands and supports all available GNSS.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>RTK<\/strong> base station<\/h3>\n\n\n\n<p>But the receiver itself is not everything, a source of correction data is also needed \u2013 a RTK base station. It could be another stationary GNSS RTK receiver (like the PX1122R) positioned at a precisely known location that generates and transmits real-time correction data to the Rover. But in my case, it would generate unwanted costs, more work, and problems. Fortunately, some services provide the RTK correction data for free over the internet, using the NTRIP (Networked Transport of RTCM via Internet Protocol). One of them, in my location, is <a href=\"https:\/\/www.asgeupos.pl\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >System ASG-EUPOS<\/a>, and I decided to use it. To start with, all you need to do is register.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><strong>Implementation and challenges<\/strong><\/strong><\/h2>\n\n\n\n<p>This project is a kind of PoC, so I decided to use hardware and tools that simplify and speed up the development (e.g., micropython for the ESP32). At the very beginning, I tried to define some requirements that determined the whole project:<\/p>\n\n\n\n<p>For Rover:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Precision must be centimeter-level.<\/li>\n\n\n\n<li>The Rover must know its position and heading all the time, even when not moving.<\/li>\n\n\n\n<li>The Rover is a small device (centimeters).<\/li>\n\n\n\n<li>The Rover operates on small areas (several meters).<\/li>\n<\/ul>\n\n\n\n<p>For GNSS RTK Planner:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Establish a communication link with the Rover device.<\/li>\n\n\n\n<li>Visually define trail through graphical interaction with the map interface.<\/li>\n\n\n\n<li>Display the Trail on the map.<\/li>\n\n\n\n<li>Send Trail to connected Rover.<\/li>\n\n\n\n<li>Display the real-time location of the connected Rover on the map.<\/li>\n<\/ul>\n\n\n\n<figure data-wp-context=\"{&quot;uploadedSrc&quot;:&quot;https:\\\/\\\/sii.pl\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/image2-2.png&quot;,&quot;figureClassNames&quot;:&quot;wp-block-image aligncenter size-full&quot;,&quot;figureStyles&quot;:null,&quot;imgClassNames&quot;:&quot;wp-image-33916&quot;,&quot;imgStyles&quot;:null,&quot;targetWidth&quot;:678,&quot;targetHeight&quot;:562,&quot;scaleAttr&quot;:false,&quot;ariaLabel&quot;:&quot;Enlarge image: Przegl\\u0105d ca\\u0142ego rozwi\\u0105zania (wg orygina\\u0142u: \\u2018Overview of whole solution\\u2019)&quot;,&quot;alt&quot;:&quot;Przegl\\u0105d ca\\u0142ego rozwi\\u0105zania (wg orygina\\u0142u: \\u2018Overview of whole solution\\u2019)&quot;}\" data-wp-interactive=\"core\/image\" class=\"wp-block-image aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"678\" height=\"562\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image2-2.png\" alt=\"Przegl\u0105d ca\u0142ego rozwi\u0105zania (wg orygina\u0142u: \u2018Overview of whole solution\u2019)\" class=\"wp-image-33916\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image2-2.png 678w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image2-2-300x249.png 300w\" sizes=\"(max-width: 678px) 100vw, 678px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge image: Przegl\u0105d ca\u0142ego rozwi\u0105zania (wg orygina\u0142u: \u2018Overview of whole solution\u2019)\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on-async--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"context.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"context.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Fig. 2 Overview of the whole solution<\/figcaption><\/figure>\n\n\n\n<p>The entire system, beyond the obvious components such as the Rover and GNSS RTK Planner, requires not only high-quality GNSS signal reception but also real-time correction data from an RTK base station to function properly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>System operation<\/strong><\/h3>\n\n\n\n<p>The use and operation of the system can be described by the following sequence:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Launch the GNSS RTK Planner application and define the Rover by entering its name and the MAC address of the ESP32 module installed in our Rover. At this point, we can monitor the connection status, current GNSS Fix quality, and the Rover&#8217;s position.<\/li>\n\n\n\n<li>Power on the Rover, which performs the following sequence: verifies internet connectivity, access to the NTRIP service, and connects to the GNSS RTK Planner application. Once all stages are confirmed, the Rover establishes communication with the GNSS RTK Planner and begins transmitting GNSS data. If there is no internet access or an issue with any of the required services, a blue LED starts flashing.<\/li>\n\n\n\n<li>(Optionally) Calibrate the compass \u2013 press the dedicated button for 2 seconds; a yellow LED should light up. Now smoothly rotate the Rover in different directions. Calibration time is set to 2 minutes, which is more than enough.<\/li>\n\n\n\n<li>Within the GNSS RTK Planner, utilize the map interface to create a Trail \u2013 the path we want the Rover to follow. The defined Trail is then assigned to the Rover defined in the application.<\/li>\n\n\n\n<li>At this stage, it is possible to transmit the assigned Trail to the Rover and observe its movement on the map within the application.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>GNSS RTK Planner<\/strong><\/h2>\n\n\n\n<p>The GNSS RTK Planner is a web-based application that combines Flask and the OpenLayers project to provide an interactive mapping experience. The interface is designed for simplicity, making it easy to create, update, and delete Rovers and Trails. <\/p>\n\n\n\n<p>Each Trail represents a collection of GNSS waypoints that you can define by drawing lines or placing individual points directly on the map. Once defined, a Trail can be assigned to one or more Rovers in the app and then sent to the physical device. The defined Trail can also be displayed on the map after selecting it.<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;uploadedSrc&quot;:&quot;https:\\\/\\\/sii.pl\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/image3-1.png&quot;,&quot;figureClassNames&quot;:&quot;wp-block-image aligncenter size-full&quot;,&quot;figureStyles&quot;:null,&quot;imgClassNames&quot;:&quot;wp-image-33918&quot;,&quot;imgStyles&quot;:null,&quot;targetWidth&quot;:777,&quot;targetHeight&quot;:740,&quot;scaleAttr&quot;:false,&quot;ariaLabel&quot;:&quot;Enlarge image: GNSS RTK Planner view&quot;,&quot;alt&quot;:&quot;GNSS RTK Planner view&quot;}\" data-wp-interactive=\"core\/image\" class=\"wp-block-image aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"777\" height=\"740\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image3-1.png\" alt=\"GNSS RTK Planner view\" class=\"wp-image-33918\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image3-1.png 777w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image3-1-300x286.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image3-1-768x731.png 768w\" sizes=\"(max-width: 777px) 100vw, 777px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge image: GNSS RTK Planner view\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on-async--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"context.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"context.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Fig. 3 GNSS RTK Planner view<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Rover<\/strong><\/h2>\n\n\n\n<p>For Rover, I decided to use the ESP32 (dual-core processor, integrated Wi-Fi, and configurable GPIO ports board) as the base platform, and program it with micropython. The GNSS RTK receiver is PX1122R (L1 + L2) paired with an L1\/L2\/L5 multi-frequency high precision antenna. The Rover also includes an electronic compass (IMU9v6), which is essential for accurately determining heading direction. And for demonstration purposes, the Rover has been equipped with wheels powered by two DC motors and driven by MX1508.<\/p>\n\n\n\n<p>The need to use a compass comes from the specific nature of the project &#8211; immediate heading on startup, very low speed of Rover. Potentially, heading could be determined only based on the GNSS signal (dynamic, calculates direction from position change over time), but in this case, the minimum Rover speed should be &gt;1 m\/s, and this is not the case. Alternatively, instead of a compass, an advanced Moving Base Mode configuration could be used (two RTK receivers on the device) \u2013 but this is a story for another project with different requirements.<\/p>\n\n\n\n<p>I used the PX1122R&#8217; Rover Mode Configuration 2&#8242; (see <a href=\"https:\/\/navspark.mybigcommerce.com\/content\/PX1122R_DS.pdf\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >PX1122R_DS.pdf<\/a>) &nbsp;with RTK update rate set to 1s (every 1 second, the module sends GNSS data over the UART interface to the ESP32). I equipped the board with its own backup battery to minimize the startup time and to keep the configuration. According to the datasheet, the PX1122R gets RTK Fix &nbsp;within ~30s after power on, under specific conditions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Distance from RTK Base station less than 30 km (in my case, it was ~2 km).<\/li>\n\n\n\n<li>8 or more satellites above 15 degree elevation angle with good satellite geometry or low DOP (Dilution of Precision) value. Simply saying, sometimes 8 or even more satellites with a strong signal are not enough to get the RTK Fix, if they are not well distributed in the sky.<\/li>\n\n\n\n<li>Open sky environment without interference.<\/li>\n\n\n\n<li>Signal over 37dB\/Hz.<\/li>\n<\/ul>\n\n\n\n<figure data-wp-context=\"{&quot;uploadedSrc&quot;:&quot;https:\\\/\\\/sii.pl\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/image4.jpeg&quot;,&quot;figureClassNames&quot;:&quot;wp-block-image aligncenter size-full&quot;,&quot;figureStyles&quot;:null,&quot;imgClassNames&quot;:&quot;wp-image-33920&quot;,&quot;imgStyles&quot;:null,&quot;targetWidth&quot;:692,&quot;targetHeight&quot;:521,&quot;scaleAttr&quot;:false,&quot;ariaLabel&quot;:&quot;Enlarge image: Rover top&quot;,&quot;alt&quot;:&quot;Rover top&quot;}\" data-wp-interactive=\"core\/image\" class=\"wp-block-image aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"692\" height=\"521\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image4.jpeg\" alt=\"Rover top\" class=\"wp-image-33920\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image4.jpeg 692w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image4-300x226.jpeg 300w\" sizes=\"(max-width: 692px) 100vw, 692px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge image: Rover top\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on-async--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"context.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"context.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Fig. 4 Rover top<\/figcaption><\/figure>\n\n\n\n<figure data-wp-context=\"{&quot;uploadedSrc&quot;:&quot;https:\\\/\\\/sii.pl\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/image5.jpeg&quot;,&quot;figureClassNames&quot;:&quot;wp-block-image aligncenter size-full&quot;,&quot;figureStyles&quot;:null,&quot;imgClassNames&quot;:&quot;wp-image-33922&quot;,&quot;imgStyles&quot;:null,&quot;targetWidth&quot;:692,&quot;targetHeight&quot;:521,&quot;scaleAttr&quot;:false,&quot;ariaLabel&quot;:&quot;Enlarge image: Rover inside&quot;,&quot;alt&quot;:&quot;Rover inside&quot;}\" data-wp-interactive=\"core\/image\" class=\"wp-block-image aligncenter size-full wp-lightbox-container\"><img decoding=\"async\" width=\"692\" height=\"521\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on-async--click=\"actions.showLightbox\" data-wp-on-async--load=\"callbacks.setButtonStyles\" data-wp-on-async-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image5.jpeg\" alt=\"Rover inside\" class=\"wp-image-33922\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image5.jpeg 692w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/image5-300x226.jpeg 300w\" sizes=\"(max-width: 692px) 100vw, 692px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge image: Rover inside\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on-async--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"context.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"context.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Fig. 5 Rover inside<\/figcaption><\/figure>\n\n\n\n<p>Added a battery, switches, some cables, and after assembly, the whole thing was placed in a &#8216;specialized&#8217; 2-liter container. To get it moving, two drive wheels were attached (each controlled by a separate DC motor).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Chellenges<\/strong><\/h2>\n\n\n\n<p>When I was selecting the hardware, I did not take into account maximum floating-point number precision. And for ESP32, it is up to 7 decimal places in the best case, which is not sufficient for RTK system precision (for example, 52.123456789 needs ~10 significant digits). In practice, the results were even worse because of the accumulated error when doing the math. Anyway, I accepted the challenge \u2013 I kept the hardware setup, and for part of the code, which is doing the coordinates calculation, I used integer numbers. But next time I will select a 64-bit platform.<\/p>\n\n\n\n<p>Another challenge and current weakness of this project is traction control. This resulted from a combination of various problems, ranging from mechanical aspects, such as the incorrect selection of DC motors and wheels, to the poor quality of the planetary gears, to the underdeveloped drive control software and compass. The traction control was not the main goal of this project, yet it caused the most problems during development. Project source code is available on <a href=\"https:\/\/github.com\/karolew\/GNSS_RTK_Planner\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >GitHub.<\/a><\/p>\n\n\n<div class=\"nsw-o-blogersii-banner\">\n            <picture>\n            <source srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/04\/Blog-Embedded-Lab-Desktop_.jpg\" media=\"(min-width: 992px)\" >\n            <source srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/04\/Blog-Embedded-Lab-Mob_.jpg\" media=\"(min-width: 300px)\" >            <img decoding=\"async\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/04\/Blog-Embedded-Lab-Desktop_.jpg\" alt=\"\"  class=\"\"  >\n        <\/picture>\n        <div class=\"cnt\">\n                    <div class=\"nsw-m-title-block -h3 -invert  -has-title-margin-bottom-0 -has-title-font-weight-bold\">\n                                <h2 class=\"nsw-m-title-block__title\">Embedded Systems<\/h2>\n                <\/div>\n                            <p class=\"has-nsw-p-4-font-size has-invert-color\">\n                We offer R&amp;D, design, development, and testing services for embedded systems, ensuring the security and reliability of your technologies.\n            <\/p>\n                            <a  href=\"https:\/\/sii.pl\/en\/what-we-offer\/embedded-systems\/\" class=\"nsw-a-button -ghost -banner-button\"   >\n        <span>Embedded systems offering<\/span>\n    <\/a>\n            <\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><strong>Demonstration and conclusion<\/strong><\/strong><\/h2>\n\n\n\n<p>The demonstration was conducted in a quite challenging urban environment where the GNSS signal reception was significantly compromised due to buildings, structures, and other obstacles that prevented a perfect, unobstructed view of the sky.<\/p>\n\n\n\n<p>For this test, I used 3 navigational Trails: a linear path, a square-shaped route, and a triangular course, each in an area not larger than 3m x 3m. To establish realistic performance parameters, I configured the system with an acceptance threshold of \u00b120 centimeters for each target GNSS waypoint, meaning the Rover needed to approach within this tolerance range to register arrival at each designated coordinate point successfully.<\/p>\n\n\n\n<p>The attached video presentation shows that the Rover follows the assigned routes correctly. It does not follow perfectly the lines connecting the GNSS coordinates, but with an error of centimeters. Based on visual observation during the trials, I estimated that the maximum positioning error in the worst-case scenarios appeared to be approximately 40 centimeters from the designated path.<\/p>\n\n\n\n<p>The observed deviation from the ideal path can be attributed primarily to limitations of the traction control system, which lacks the precision and responsiveness needed for single-centimeter path following. Apart from that, the solution meets its initial objectives and provides a good starting point for further development.<\/p>\n\n\n\n<figure class=\"wp-block-embed aligncenter is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe title=\"GNSS RTK Planner Demo\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/wG-7WOqRIGU?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><figcaption class=\"wp-element-caption\">GNSS RTK Planner Demo<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Some references<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/navspark.mybigcommerce.com\/content\/PX1122R_DS.pdf\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >PX1122R_DS.pdf<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.faa.gov\/about\/office_org\/headquarters_offices\/ato\/service_units\/techops\/navservices\/gnss\/gps\/howitworks\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >Satellite Navigation &#8211; GPS &#8211; How It Works | Federal Aviation Administration<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.gps.gov\/codelesssemi-codeless-gps-access-commitments\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >DOD Positioning, Navigation, and Timing (PNT) Executive Committee<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.gps.gov\/new-civil-signals\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >Official GPS Government Website (GPS.gov)<\/a>&nbsp;<\/li>\n\n\n\n<li><a href=\"https:\/\/www.esa.int\/Applications\/Satellite_navigation\/Galileo\/Two_new_satellites_added_to_Galileo_constellation_for_increased_robustness\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >European Space Agency (ESA)<\/a><\/li>\n\n\n\n<li><a href=\"http:\/\/www.beidou.gov.cn\/xt\/gfxz\/201912\/P020191227325641753862.pdf\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >China Satellite Navigation Office (CSNO)<\/a>&nbsp;<\/li>\n\n\n\n<li><a href=\"https:\/\/www.unoosa.org\/documents\/pdf\/icg\/2022\/ICG16\/02.pdf\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >UN Office for Outer Space Affairs (UNOOSA)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/gnss-sdr.org\/docs\/tutorials\/gnss-signals\/\" target=\"_blank\" rel=\"noreferrer noopener\" rel=\"nofollow\" >GNSS-SDR<\/a>&nbsp;<\/li>\n\n\n\n<li><a href=\"https:\/\/www.asgeupos.pl\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >System ASG-EUPOS<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/support.swiftnav.com\/support\/solutions\/articles\/44001850808-understanding-gps-gnss-rtk-technology\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >Swift Navigation Support<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/siipoland-my.sharepoint.com\/personal\/dbaldyga_sii_pl\/Documents\/Blog\/autorzy%20i%20teksty\/Rafa\u0142%20Fr\u0105tczak\/\u2022%09https:\/gnss.store\/blogs\/gnss-receivers\/rtk-ppp-and-autonomous?srsltid=AfmBOorEZIsQKHFF8vggicAFOq3W2BmfSWdfuPPH0cbUy1qfKfqEe84n\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >RTK, PPP and autonomous<\/a><\/li>\n<\/ul>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;33928&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;2&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;2&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5&quot;,&quot;size&quot;:&quot;30&quot;,&quot;title&quot;:&quot;Building an RTK Rover: Web-controlled precision navigation&quot;,&quot;width&quot;:&quot;159&quot;,&quot;_legend&quot;:&quot;{score}\\\/5&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 159px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 2px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 30px; height: 30px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 24px;\">\n            5\/5    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>If you have ever been curious about how precision navigation systems actually function behind the scenes, or if you have &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/en\/building-an-rtk-rover-web-controlled-precision-navigation\/\">Continued<\/a><\/p>\n","protected":false},"author":793,"featured_media":33925,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1320],"tags":[15035,2198,1526,1342],"class_list":["post-33928","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hard-development","tag-web-applications","tag-case-study-en","tag-guidebook","tag-embedded-en"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2026\/05\/idea.jpg","category_names":["Hard development"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/33928"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/users\/793"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/comments?post=33928"}],"version-history":[{"count":3,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/33928\/revisions"}],"predecessor-version":[{"id":34048,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/33928\/revisions\/34048"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media\/33925"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media?parent=33928"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/categories?post=33928"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/tags?post=33928"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}