Handle NavSatFix NaN value to prevent crashes
Intro
When valid latitude, longitude, or altitude data isn’t received from the GPS (particularly immediately after powering on the GPS module), the NavSatFix message’s latitude and longitude fields may show up as NaN.
-
raw NMEA data
max@maxbuntu:~$ ros2 topic echo /nmea_sentence header: stamp: sec: 1745471433 nanosec: 870266565 frame_id: gps_link sentence: $GNGGA,051033.85,,,,,0,00,9999.0,,,,,,*41 -
NavSatFix data
max@maxbuntu:~$ ros2 topic echo /fix header: stamp: sec: 1745471433 nanosec: 870266565 frame_id: gps_link status: status: -1 service: 1 latitude: .nan longitude: .nan altitude: .nan position_covariance: - 9.9980001e+19 - 0.0 - 0.0 - 0.0 - 9.9980001e+19 - 0.0 - 0.0 - 0.0 - 1.599680016e+21
In this situation, the following error occurs in the NTRIP client:
- ntrip_client
max@maxbuntu:~$ ros2 run ntrip_client ntrip_ros.py [ntrip_ros.py-3] [INFO] [1745463164.704517554] [ntrip_client]: Stopping RTCM publisher [ntrip_ros.py-3] [INFO] [1745463164.706382404] [ntrip_client]: Disconnecting NTRIP client [ntrip_ros.py-3] [INFO] [1745463164.708415831] [ntrip_client]: Shutting down node [ntrip_ros.py-3] Traceback (most recent call last): [ntrip_ros.py-3] File "/opt/ros/jazzy/lib/ntrip_client/ntrip_ros.py", line 102, in <module> [ntrip_ros.py-3] raise e [ntrip_ros.py-3] File "/opt/ros/jazzy/lib/ntrip_client/ntrip_ros.py", line 98, in <module> [ntrip_ros.py-3] rclpy.spin(node) [ntrip_ros.py-3] File "/opt/ros/jazzy/lib/python3.12/site-packages/rclpy/__init__.py", line 244, in spin [ntrip_ros.py-3] executor.spin_once() [ntrip_ros.py-3] File "/opt/ros/jazzy/lib/python3.12/site-packages/rclpy/executors.py", line 827, in spin_once [ntrip_ros.py-3] self._spin_once_impl(timeout_sec) [ntrip_ros.py-3] File "/opt/ros/jazzy/lib/python3.12/site-packages/rclpy/executors.py", line 822, in _spin_once_impl [ntrip_ros.py-3] raise handler.exception() [ntrip_ros.py-3] File "/opt/ros/jazzy/lib/python3.12/site-packages/rclpy/task.py", line 239, in __call__ [ntrip_ros.py-3] self._handler.send(None) [ntrip_ros.py-3] File "/opt/ros/jazzy/lib/python3.12/site-packages/rclpy/executors.py", line 508, in handler [ntrip_ros.py-3] await call_coroutine() [ntrip_ros.py-3] File "/opt/ros/jazzy/lib/python3.12/site-packages/rclpy/executors.py", line 396, in _execute [ntrip_ros.py-3] await await_or_execute(sub.callback, *msg_tuple) [ntrip_ros.py-3] File "/opt/ros/jazzy/lib/python3.12/site-packages/rclpy/executors.py", line 111, in await_or_execute [ntrip_ros.py-3] return callback(*args) [ntrip_ros.py-3] ^^^^^^^^^^^^^^^ [ntrip_ros.py-3] File "/opt/ros/jazzy/lib/ntrip_client/ntrip_ros_base.py", line 141, in subscribe_fix [ntrip_ros.py-3] nmea_lat = NMEAParser.lat_dd_to_dmm(fix.latitude) [ntrip_ros.py-3] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ [ntrip_ros.py-3] File "/opt/ros/jazzy/lib/python3.12/site-packages/ntrip_client/nmea_parser.py", line 33, in lat_dd_to_dmm [ntrip_ros.py-3] degrees = int(decimal_degrees_whole) [ntrip_ros.py-3] ^^^^^^^^^^^^^^^^^^^^^^^^^^ [ntrip_ros.py-3] ValueError: cannot convert float NaN to integer [ERROR] [ntrip_ros.py-3]: process has died [pid 3609, exit code 1, cmd '/opt/ros/jazzy/lib/ntrip_client/ntrip_ros.py --ros-args -r __node:=ntrip_client -r __ns:=/ --params-file /tmp/launch_params_0yrvmlvl'].
Changes
Before using fix.latitude and fix.longitude, check for NaN and clear the fields if detected.
Thanks for submitting this PR. Crashing is definitely not the desired behavior here.
However, I am curious if we even want to send the NMEA sentence to the server if it has NaN for either Latitude or Longitude. Most of the time, those are the only two pieces of information that NTRIP servers actually look at from the NMEA sentence.
Do you have experience using a server that is okay with receiving blank position information, and what is the purpose of sending the blank position information if so?
Actually, I have been using the package you provided without a full understanding of NTRIP. (By the way, thank you for creating such a convenient package! haha) I thought that sending empty data might not cause significant issues, so I modified it accordingly.
- Example15_NTRIPClient.ino (Removed existing comments for explanation)
void pushGPGGA(NMEA_GGA_data_t *nmeaData) { //Provide the caster with our current position as needed if ((ntripClient.connected() == true) && (transmitLocation == true)) { Serial.print(F("Pushing GGA to server: ")); Serial.print((const char *)nmeaData->nmea); ntripClient.print((const char *)nmeaData->nmea); // It just pushes the NMEA sentence to the NTRIP server } }
Since I couldn’t find an official specification for NTRIP servers, I referred to an NTRIP example from SparkFun’s ZED-F9P. In that example, it appeared that the system forwarded the NMEA sentence without checking whether the latitude or longitude was empty.
However, to avoid unnecessary traffic, it might be a good idea not to send the data if it is empty.