PointOneNav / fusion-engine-client

FusionEngine client interaction support.
MIT License
18 stars 11 forks source link

What reasons are there for the function callback to not be triggered on FusionEngineFramer's OnData? #184

Open sisaha9 opened 1 year ago

sisaha9 commented 1 year ago

Here is the relevant codebase: https://github.com/sisaha9/fusion_engine_ros_driver

I bind the function to the framer here: https://github.com/sisaha9/fusion_engine_ros_driver/blob/0c128b3ebfa7824a57e62542b7b19506e2a8f257/src/fusion_engine_ros_driver_node.cpp#L42

I send the data here: https://github.com/sisaha9/fusion_engine_ros_driver/blob/0c128b3ebfa7824a57e62542b7b19506e2a8f257/src/fusion_engine_ros_driver_utils.cpp#L102

I can confirm that function is being called. The buffer size for framer was initialized to 1024 while the incoming messages from my quectel devices were of sizes 98, 256, 179 and 75. The callback functions is filled here: https://github.com/sisaha9/fusion_engine_ros_driver/blob/stable/src/fusion_engine_ros_driver_node.cpp#L64. So far that function has not been called and the code has never errored out

adamshapiro0 commented 1 year ago

Hey @sisaha9. Your setup seems ok. Are you sure your SendDataToFramer() function is getting called and no data is getting lost? The most common reason for the callback not working is data loss. Are you seeing any CRC failure warnings? Those are enabled by default, though if you're receiving data from a device that outputs both FusionEngine messages and non-FusionEngine in the same stream, you'll want to disable them.

The framer class uses glog and has a number of built-in debug prints that you can enable and may help diagnose what's going on. You can enable them by enabling glog output to stderr (--logtostderr), and then setting the desired verbosity with the --vmodule argument. For example, to turn on the highest verbosity level in that file, you would set --vmodule=fusion_engine_framer=4.

To enable logging, you need to include glog in your project (https://github.com/google/glog) and then define the P1_HAVE_GLOG preprocessor macro, usually with -DP1_HAVE_GLOG=1 or similar. I just realized that we don't have an example of using glog in the readme or the cmake/bazel build environments. I'll take a note to add that in the future. (Worst case, for now if you can't get glog working easily, you could also just replace all the VLOG(n) lines with std::cout for testing.)


Separately, are you aware of @BlanchoMartin's ROS driver work? He has a driver working nicely with some new features like serial port handling, and is getting it ready to be made public soon. I believe it was initially based on your code. It might be a good idea for you guys to sync up and compare notes.

adamshapiro0 commented 1 year ago

Ah one additional thought: if you do not have glog compiled and enabled (--logtostderr), you will not see the CRC warnings. So if you are getting CRC issues and/or dropping data, it may not be obvious.

sisaha9 commented 1 year ago

I am using the Quectel device so that makes sense. Rn it's failing the Sync0 check. I haven't seen the other branch but would def like to sync up

adamshapiro0 commented 1 year ago

Sync 0 is simply looking for the first byte in the stream. That byte is ASCII . (0x2E), so it's likely to show up a lot in most incoming data streams.

When you say it's failing, which condition is it hitting? Is it finding sync 0 but never finding sync 1 (1 = 0x31)? Or is it finding both of those but not decoding a valid message?

If it never finds sync 0, that seems a little odd since it's a pretty common byte in both ASCII and binary. If it finds sync 0 occasionally but never finds sync 1, that's maybe a bit unexpected: the text .1 will show up in ASCII data like NMEA for numbers like 382.134, etc. And it should show up randomly in binary data on occasion.

If it's sometimes finding both sync bytes, but then never getting past the payload size and CRC checks, either the stream doesn't have any FusionEngine messages in it (FusionEngine output disabled, using the wrong UART on the Quectel device, etc.), or bytes are getting dropped somewhere. Note that UART1 on the LG69T does not contain FusionEngine data by default, only NMEA. UART2 should have FusionEngine+NMEA+RTCM.

sisaha9 commented 1 year ago

@adamshapiro0 This is the exact line it fails at: https://github.com/PointOneNav/fusion-engine-client/blob/master/src/point_one/fusion_engine/parsers/fusion_engine_framer.cc#L167

It never enters SYNC_1 and early exits after. For me the first byte is appearing as $

adamshapiro0 commented 1 year ago

Ah - if it's never getting past that, it means your data stream does not contain any SYNC0 bytes (.) at all. That very surprising since that's a common ASCII character. Even if you were recording from the wrong UART and only getting NMEA data, you should see . pretty frequently.

The VLOG(4) line just above that should be printing out the byte value every single time it gets there. If you're not getting past SYNC0, I would expect that line to print on every byte you pass to the framer. Is that true? Are you only seeing $, or are you seeing other bytes too, and just not .?

Can you enable VLOG(4) and then upload a text file with the output from running a few seconds of data through it? If possible, if you can also record a file of the binary data that you're sending to the framer, that would be helpful. You should be able to process that binary file with the Python p1_print tool to see if it has any FusionEngine messages.