====== Swift Navigation / Carnegie Robotics Duro ====== [{{:swiftnav:duro:swiftnav_duro.png?400 |Photo credit Carnegie Robotics}}] Developed jointly by Swift Navigation and Carnegie Robotics and released in 2018, then was bought by Carnegie Robotics in fall 2024,
Duro™ is a ruggedized, high-performance and low-cost GNSS receiver with Real Time Kinematics (RTK) technology for a centimeter-level positioning accuracy. GNSS multi-band and multi-constellation support enable Duro to offer fast RTK convergence times and high position availability. [[https://carnegierobotics.freshdesk.com/support/solutions/articles/154000199758-duro-specification-and-user-manual|Duro Specification and User Manual]]Duro uses the Piski Multi multi-band, multi-constellation GNSS receiver in a ruggedized enclosure. This page will contain information about both the Duro and Piksi Multi - as far as I can tell, there is little inherently unique about the Duro compared to the Piksi Multi mounted on the evaluation board that Swift Navigation also sold it on. A variant of the Duro, called "Duro Inertial" also exists. As far as I have been able to determine, the hardware is identical, but it has additional software that enables the IMU to be used for inertial navigation in the event of GNSS loss. ===== Specs ===== Because the Duro uses the Piksi Multi internally, these specs are those of the Piksi Multi. The Duro has capable DC-DC power supplies on-board and runs off 10-35v DC, consuming 5-6w. Additionally, it can supply 0.25A of 5v and 1A of 12v on its serial and aux connectors, for powering external devices. All of this is laid out in the [[https://www.swiftnav.com/resource-files/Piksi%20Multi/v2.2/Specification/Piksi%20Multi%20HW%20Specification%20v2.2%20%5B000-534-02-02%5D.pdf|HW Spec PDF]], but at a high level: [{{ :swiftnav:piksi_multi.png?direct&400|Photo credit Swift Navigation}}] * Based on the Zync 7020 running custom cores and linux * Dual band RTK, up to 10Hz * GPS L1/L2 * GLONASS G1/G2 * BeiDou B1/B2 * Galileo E1/E5b * Raw measurements at 20Hz * On-board IMU (Bosch BMI160) and magnetometer (Bosch BMM150) accessible through binary data stream * I/O * UART, Ethernet, CAN, USB * Communication Protocols * SBP, NMEA, RTCM * Software-switchable antenna bias power, 4.85v at up to 100mA Satellite tracking and acquisition, as well as the calculation of PVT solutions, are handled entirely by the Zynq 7020. A program in the Zynq, which Swift Navigation calls "SwiftNAP", receives the digitized RF and passes it directly to other software on the device.
Piksi Multi employs a unique design, which does not utilize an ASIC. Instead, the tracking and correlation duties are serviced by the programmable logic of the Zynq 7020. This allows Piksi Multi to be extremely flexible with regards to how tracking and correlation resources are allocated; it also makes comparisons of tracking channel count largely irrelevant. Piksi Multi is capable of simultaneous tracking of L1 and L2 signals from up to 22 satellites. Piksi Multi HW Specification v2.2, p.2[{{ :swiftnav:piksi_multi_block_diagram.png?direct&900 |Piksi Multi HW Specification v2.2, p.3}}] ===== Connectivity ===== Like just about every other commercial GNSS receiver, especially rugged ones, the Duro uses unique connectors for power, serial, ethernet, etc. Unfortunately un-casing the unit does not readily provide access to these signals internally, so using the connectors as intended is the best course of action for working with the Duro. The connectors used are standard M12, which are slightly more available than LEMO or Fischer, and the user manual documents them well, if you choose to make your own cables. Behind an access panel there is a microSD slot and MicroUSB port. Using these is not sanctioned by Swift Navigation or Carnegie Robotics and will ruin the device's IP rating.
root@piksi:/persistent # ls -l /etc/init.d/S99unicontrol*
-rwxr-xr-x 1 root root 524 Mar 20 2022 /etc/init.d/S99unicontrol_0_customization
-rwxr-xr-x 1 root root 143 Mar 20 2022 /etc/init.d/S99unicontrol_1_remote_support_setup
-rwxr-xr-x 1 root root 116 Mar 20 2022 /etc/init.d/S99unicontrol_2_stats
-rwxr-xr-x 1 root root 140 Mar 21 2022 /etc/init.d/S99unicontrol_3_config_upgrader
-rwxr-xr-x 1 root root 122 Mar 21 2022 /etc/init.d/S99unicontrol_4_can_setup
-rwxr-xr-x 1 root root 200 Mar 21 2022 /etc/init.d/S99unicontrol_5_machine
-rwxr-xr-x 1 root root 143 May 24 2022 /etc/init.d/S99unicontrol_6_support_tunnel
''S99unicontrol_4_can_setup'' is right there - and really all it does is call ''/var/can-setup/can-setup.sh'' - can we stop it?
#!/bin/sh
#
# Start the can1 network
#
#Default configuration
DO_NOT_START=
CAN_BITRATE=250000
CAN_RESTART_MS=100
#Check customization file
if [ -f /persistent/customization.config ]; then
source /persistent/customization.config
fi
#Skip auto-starting
if [ "$DO_NOT_START" -eq "1" ]; then
echo "DO_NOT_START: can";
exit 0
fi
#Start the network
echo "Starting canbus error reporter"
/var/can-setup/log_can_startup_errors.sh &
if [ -z "$CAN_RESTART_MS" ]; then
echo "Starting can1 network: "
/sbin/ip link set can1 type can bitrate $CAN_BITRATE
else
echo "Starting can1 network (restart param $CAN_RESTART_MS): "
/sbin/ip link set can1 type can bitrate $CAN_BITRATE restart-ms $CAN_RESTART_MS
fi
/sbin/ip link set can1 up
It looks like we can, and fairly easily! It sources ''customization.config'' and checks the status of ''DO_NOT_START''. That config file resides in the very small, but aptly named and persistent, ''/persistent/'' directory. I didn't want to simply set this to ''1'' and potentially break a bunch of things, so I scanned through the entire file system to see what else checked a ''DO_NOT_START'' variable, and was please to find that it's only Unicontrol stuff that I am comfortable disabling:
$ grep -rnw / -e '"$DO_NOT_START" -eq "1"'
./var/can-setup/can-setup.sh:17:if [ "$DO_NOT_START" -eq "1" ]; then
./var/machine/run_machine.sh:16:if [ "$DO_NOT_START" -eq "1" ]; then
./var/remote_support/remote_support_setup.sh:19:if [ "$DO_NOT_START" -eq "1" ]; then
''customization.config'' also has a variable ''DO_NOT_START_REMOTE_SUPPORT'', which is only checked by the ''remote_support_setup.sh'' script, which will exit if either of those variables is true.
In addition to remote support and canbus configuration, the ''run_machine.sh'' script also checks these variables. ''machine'' appears to be the program that configures the Duro for the specific piece of equipment it is installed on - in this case of this unit, an excavator. This is great, because I don't want any of those components running - especially ''machine'' - it consumes the lion's share of available RAM and quite a few CPU cycles, and the remote support stuff makes constant API calls with a token that is no longer valid.
I quickly learned that it is not as simple as setting those variables to true, because before they are read the Unicontrol init scripts actually overwrite ''customization.config'' with a bare-bones copy stored in ''/var/customization/''. After that, the aptly named "config upgrader" init script is supposed to phone home and grab the latest version of the config file and machine definition file. All of this makes sense in the context of how this thing was deployed, but it's just a big headache for me. Honestly, this is a great template for embedded systems design in general, as far as I can tell the developers who built this did a really good job, and reverse engineering it has been a fun task.
Thankfully, and somewhat ironically, Unicontrol's custom init scripts actually save us here. The first one that is called after the rest of the system boots is ''S99unicontrol_0_customization'' and it does three things: it checks to see if ''customization.config'' exists in the persistent directory, then it checks to see if that config file has ''CUSTOM_SCRIPT'' defined, and if it does, it runs that script.
So what we can do is use this script to stop or remove the other init scripts before they wipe out my own locally created configuration file. Since the customization script runs first, this gives us an easy pathway - I simply created a script in the persistent directory called ''init_override.sh'' which removes the other S99unicontrol init scripts. I could have only removed the one that deletes my config file, but seeing as I am not using any of them, they can all go.
#!/bin/sh
rm -f /etc/init.d/S99unicontrol_1_remote_support_setup
rm -f /etc/init.d/S99unicontrol_2_stats
rm -f /etc/init.d/S99unicontrol_3_config_upgrader
rm -f /etc/init.d/S99unicontrol_4_can_setup
rm -f /etc/init.d/S99unicontrol_5_machine
rm -f /etc/init.d/S99unicontrol_6_support_tunnel
It is then referenced in ''customization.config'' as ''CUSTOM_SCRIPT=/persistent/init_override.sh'' and we reboot the system. When it unpacks the linux image into RAM and works its way through the init scripts it will hit ''S99unicontrol_0_customization'' which will find the override script (not yet deleted from the persistent storage!) and //poof// all of the other Unicontrol stuff is gone, there are a couple of vanilla init scripts that run afterwards, and then the unit is operating as normal, with a mostly vanilla configuration.
If we ever want that stuff to run again, all we have to do is comment out the ''CUSTOM_SCRIPT'' line in the config file, reboot again, and all those intit scripts will run again - but make sure the config file is backed up (or duplicated under another name in /persistent/) because of course it will be deleted.
===== Photos =====
My Duro is a late model, with Carnegie Robotics branding. It is not clear to me when it was manufactured, but the [[https://www.marvell.com/content/dam/marvell/en/public-collateral/phys-transceivers/marvell-phys-transceivers-alaska-88e1512-product-brief.pdf|Marvell PHY]] on the carrier board has a late 2021 date code. The Piksi Multi seems to be an 00108-09 revision, but I haven't confirmed its date of manufacture yet.
Note that the Verbatim microSD card was not included in the unit, I placed it in the slot to demonstrate how it fits.
Also, I have not yet removed the Piksi Multi itself from the Duro enclosure, which is why I don't have a photo of the top of it. It is mounted with 4.5mm standoffs, and I only have nut drivers in 4 and 5mm, go figure. While I could remove them via other means, I see no need to at the moment - and the unit is thermally bonded with the enclosure, something I'd rather not disrupt. When I get my hands on a Piksi Multi Evaluation Board, I probably will pull it.
{{gallery>:swiftnav:duro:photos}}