How do I read the position data from a GPS (NMEA) device? - vb.net

I'm trying to read data from a GPS device (NMEA). I am getting the data successfully. However, as soon as I start using it, it gives me gibbirish. This is what I get from the GPS:
$GPGSA,A,3,20,25,31,22,14,29,03,16,32,06,27,,1.5,0.8,1.3*33
$GPRMC,120556.000,A,2546.0985,S,02816.0193,E,0.22,276.44,291013,,,A*7A
$GPGGA,120557.000,2546.0984,S,02816.0191,E,1,11,0.8,1396.3,M,21.5,M,,0000*71
$GPGSA,A,3,20,25,31,22,14,29,03,16,32,06,27,,1.5,0.8,1.3*33
$GPGSV,3,1,12,31,50,165,19,14,48,055,27,16,43,304,42,32,36,265,38*76
$GPGSV,3,2,12,29,24,119,31,06,19,355,34,20,14,238,41,25,10,138,19*78
$GPGSV,3,3,12,27,09,351,33,22,06,008,36,03,05,341,36,23,,221,*7F
$GPRMC,120557.000,A,2546.0984,S,02816.0191,E,0.17,274.76,291013,,,A*7D
$GPGGA,120558.000,2546.0982,S,02816.0189,E,1,11,0.8,1396.0,M,21.5,M,,0000*72
$GPGSA,A,3,20,25,31,22,14,29,03,16,32,06,27,,1.5,0.8,1.3*33
$GPRMC,120558.000,A,2546.0982,S,02816.0189,E,0.07,220.52,291013,,,A*7B
$GPGGA,120559.000,2546.0981,S,02816.0187,E,1,11,0.8,1395.7,M,21.5,M,,0000*7A
$GPGSA,A,3,20,25,31,22,14,29,03,16,32,06,27,,1.5,0.8,1.3*33
$GPRMC,120559.000,A,2546.0981,S,02816.018
The above was received by doing the following:
//inside a 100ms ticker
Dim data As String = GpsPort.ReadExisting()
CommentBox.AppendText(data)
As soon as I do Dim strArr() As String = data.Split("$") then output it using:
CommentBox.AppendText(strArr(0).ToString) // inside the same ticker
the output is:
034.000,2546.0985,S,02816.0298,E,1,11,0.8,1360.6,M,21.5,M,,0000*77
3,20,29,14,22,31,25,03,16,32,06,27,,1.5,0.8,1.3*33
MC,121034.000,A,2546.0985,S,02816.0298,E,0.01,236.13,291013,,,A*75
.000,2546.0983,S,02816.0297,E,1,11,0.8,1359.9,M,21.5,M,,0000*7A
A,A,3,20,29,14,22,31,25,03,16,32,06,27,,1.5,0.8,1.3*33
,121035.000,A,2546.0983,S,02816.0297,E,0.06,283.04,291013,,,A*72
036.000,2546.0982,S,02816.0296,E,1,11,0.8,1359.3,M,21.5,M,,0000*73
3,20,29,14,22,31,25,03,16,32,06,27,,1.5,0.8,1.3*33
MC,121036.000,A,2546.0982,S,02816.0296,E,0.03,190.30,291013,,,A*72
.000,2546.0981,S,02816.0296,E,1,11,0.8,1358.6,M,21.5,M,,0000*75
A,A,3,20,29,14,22,31,25,03,16,32,06,27,,1.5,0.8,1.3*33
3,1,12,31,49,161,28,14,46,052,20,16,45,301,39,32,36,268,35*79
3,2,12,29,23,122,18,06,21,355,27,20,15,240,40,27,11,351,37*78
Can anyone assist me in getting the GPS co-ordinates from the GPGGA strings? Because splitting them clearly doesn't work.

You have to read the data line by line.
Each line is one NMEA sentence.
Once you detect "$GPGGA" (or you also could use the RMC message)
you have this line:
$GPGGA,120557.000,2546.0984,S,02816.0191,E,1,11,0.8,1396.3,M,21.5,M,,0000*71
Now you splitt by delimiter ","
Then this is latitude : 2546.0984,S
And this is longitude 02816.0191,E
read at NMEA spec which format the coordinates are: I think: the first to digits in latitdue are degrees, the rest is minutes: 25° 46.0984 minutes. If "S" multiply the result with -1.
slightly different for longitude:
02816.0191,E
first 3 digits degrees, rest minutes. 27° 16.0191 minutes. multiply with -1 if "W".

Basically, the messages you are seeing are part of a rather complicated message format. Each part means something different and the meanings depend on the message type.
You may want to look at some of the code in this open source project. I wrote this library with a colleague and it parses out those messages from a specific GPS device, but it should work with pretty much any device putting out the same data.

Related

Gps nmea output getting valid $GPGSV but not valid $GPGGA $GPRMC

I'm trying to parse gps nmea output from a modem connected to serial port of a cubietruck board (ARM® Cortex™-A7 Dual-Core). The configuration is done succesfully I get 4g network form modem but when I try to see nmea outout of the gps module, I get the following :
$GPRMC,,V,,,,,,,,,,N*53
$GPGSV,2,1,08,07,49.9,43.6,28.2,28,49.9,158.9,29.2,02,3.5,239.1,,05,49.9,286.9,E
$GPGSV,2,2,08,06,,,,08,9.8,68.9,,09,31.6,104.1,,13,20.4,299.5,,1*5E
$GNGNS,112218.9,,,,,NNN,,,,,,*03
$GPVTG,,T,,M,,N,,K,N*2C
$GPGSA,A,1,,,,,,,,,,,,,,,*1E
$GNGSA,A,1,,,,,,,,,,,,,,,*00
$GPGGA,,,,,,0,,,,,,,,*66
$GPRMC,,V,,,,,,,,,,N*53
$GPGSV,2,1,08,07,49.9,43.6,27.9,28,49.9,158.9,29.7,02,3.5,239.1,,05,49.9,286.9,F
$GPGSV,2,2,08,06,,,,08,9.8,68.9,,09,31.6,104.1,,13,20.4,299.5,,1*5E
$GNGNS,112219.9,,,,,NNN,,,,,,*02
Looking in http://aprs.gids.nl/nmea/ I found that $GPGSV is GPS Satellites in view. So what I understand is that I get 2 satellites. Is this perhaps the case that I don't get valid $GPGGA $GPRMC or should I check something else?
You don't have a positional "fix" and therefore get empty values in some of the telegrams. As you probably know, there should be latitude, longitude and other data instead of empty values between the commas. Two satellites are not enough to get a fix, you need at least 3 or 4 to get the position.
The NMEA 0183 standard is weakly defined and doesn't mention what GPS units should do when they don't have a positional fix. Sending empty values is pretty common, but some units might act differently. You can easily tell whether the data is valid or not from the A and V letters. V means void and A means active. In the RMC telegram, you can see a V, meaning the entire thing is void.
The reason you get values in the GSV telegrams is because the GPS is able to see two satellites and therefore calculate the values needed in the telegram.
The third field, 08, is the theoretical number of satellites you would be able to see in good conditions.
So what you have to do is to take the GPS outdoors or connect it to a proper antenna. It will start sending proper values when it's able to see the satellites.
Actually by your two GPGSV sentences you can see 08 satellites - eight of them. You have 2 'sentences' of GSV 2,1,08 means 1 of 2 sentences describing 08 satellites, and 2,2,08 means 2 of 2 sentences describing 08 satellites

Get GPS accuracy

I am working with a SIM868 cellular modem with GPS capabilities. I have access to send and receive data from/to the GPS processor, a MediaTek MT2503DV.
When I look at the raw data coming out of the processor, I see numerous NMEA strings ($GPGGA, $GPRMC...), and also $GPACCURACY. I cant find any documentation on $GPACCURACY, but I presume it is a number in meters of the accuracy of the GPS.
The $GPACCURACY string looks like this $GPACCURACY,25.9*36
What is $GPACCURACY, and what do the numbers following it mean?
Is there a way to only receive this and $RMC data out of the GPS?
From the 868 manual:
Message ID GPACCURACY:ACCURACY OF THE LOCATION
This message is accuracy of the location; The smaller the number is, the be better the condition is;
Table 2-11: GPACCURACY Data Format
Example: $GPACCURACY,961.2*04
Link to manual:
http://simcom.ee/documents/SIM868/SIM868_NMEA%20Message%20Specification_V1.03.pdf

Is this GPGSV sentence valid?

While parsing the NMEA output of a GPS receiver I get the following lines:
$GPGSV,4,1,16,02,17,228,35,03,04,048,37,05,59,285,29,06,02,030,34*73
$GPGSV,4,2,16,07,58,061,46,08,80,159,40,09,11,227,32,10,51,167,47*77
$GPGSV,4,3,16,13,15,089,38,15,00,279,,16,00,018,,26,34,279,42*7A
$GPGSV,4,4,16,28,20,154,39*4C
As I understand it, from various sources on the web (e.g. here), this is wrong. According to the 3rd number, there should be 16 satellites, which was true for all those GPS receivers I previously encountered, but the sentence from this one only contains the data for 13 satellites.
Is this an error? Or do I read the specification wrongly?
Nmea is a weakly specified file format. GPS chip manufactures provide documenttaion how they interpret the NMEA specification.
For example ublox and Sirf each have a chapter of about 40 pages describing how to interpret the NMEA format.
So if you write " Or do I read the specification wrongly?", then the question is which specification you are reading. That of the GPS chip manufacturer? The NMEA 0183 spec does not contain enough info to correctly parse the sentences.
Especially in your case: the NMEA protocol does not desribe how to handle empty values vs invalid ones.
In your case the receiver theretically expects to see 16 satellites, but found only 13.
I would expect that the missing 3 sats would have empty ",,,,,,,,". But obviously the manufacturer decided to just stop and append the checksum string. (Its simply not speciefied that it is mandatory to print out empty semicolons for the missing 3 sats.
Unfortunaetly you have to expect to write a NMEA parser for each CHPS chip manufacturer.
Therfore I always recommend to use the binary format of the Chip manufactureres protocol. (e,.g uBlox bianry or Sirf binary because these are exactly specified).
You can further look at the docu for GpsBable: they show how different manufacturres produce different GSV data sets.
Update:
As you now told that it is a ublox receiver:
The answer is, yes the NMEA sentences are valid. Look at the ublox protocol spec. i use spec for ublox 5:
On page where the GSV sentence is described look at the "Message Structure":
{,sv,elv,az,cno}*cs
the curly braces enclose the sequence that is repeated.
And below look at "1..4": this means 1,2,3 or 4 blocks. There is not written "4", its "1..4" therefore satelite info is optional, and has not to be empty.
If you further look at the example ublox gives, then you see, that the last GPGSV message contains less than 4 satellites, exactly as you are showing in your question.
Yes, it's inconsistent; the last message should have described more than one satellite (four, actually) so as to total the 16 advertised. The GPS receiver should have reported at least the satellite IDs (PRN), even if their viewing direction in the sky and SNR were unknown at the time, e.g.: {,01,,,}.
That being said, it's better to write programs tolerant against ill-formed messages; in this case, updating the number of satellites in view to 13, as counted.
(I've checked the checksums and they're okay.)

Objective C - Cross-correlation for audio delay estimation

I would like to know if anyone knows how to perform a cross-correlation between two audio signals on iOS.
I would like to align the FFT windows that I get at the receiver (I am receiving the signal from the mic) with the ones at the transmitter (which is playing the audio track), i.e. make sure that the first sample of each window (besides a "sync" period) at the transmitter will also be the first window at the receiver.
I injected in every chunk of the transmitted audio a known waveform (in the frequency domain). I want estimate the delay through cross-correlation between the known waveform and the received signal (over several consecutive chunks), but I don't know how to do it.
It looks like there is the method vDSP_convD to do it, but I have no idea how to use it and whether I first have to perform the real FFT of the samples (probably yes, because I have to pass double[]).
void vDSP_convD (
const double __vDSP_signal[],
vDSP_Stride __vDSP_signalStride,
const double __vDSP_filter[],
vDSP_Stride __vDSP_strideFilter,
double __vDSP_result[],
vDSP_Stride __vDSP_strideResult,
vDSP_Length __vDSP_lenResult,
vDSP_Length __vDSP_lenFilter
)
The vDSP_convD() function calculates the convolution of the two input vectors to produce a result vector. It’s unlikely that you want to convolve in the frequency domain, since you are looking for a time-domain result — though you might, if you have FFTs already for some other reason, choose to multiply them together rather than convolving the time-domain sequences (but in that case, to get your result, you will need to perform an inverse DFT to get back to the time domain again).
Assuming, of course, I understand you correctly.
Then once you have the result from vDSP_convD(), you would want to look for the highest value, which will tell you where the signals are most strongly correlated. You might also need to cope with the case where the input signal does not contain sufficient of your reference signal, and in that case you may wish to (for example) ignore values in the result vector below a certain level.
Cross-correlation is the solution, yes. But there are many obstacles you need to handle. If you get samples from the audio files, they contain padding which cross-correlation function does not like. It is also very inefficient to perform correlation with all those samples - it takes a huge amount of time. I have made a sample code which demonstrates time shift of two audio files. If you are interested in the sample, look at my Github Project.

AVSampleBufferDisplayLayer renders half of each frame when using high preset

I am using AVSampleBufferDisplayLayer to display video that is being streamed over the network. On the sending side an AVCaptureSession is used to capture CMSampleBuffers which are serialized into NAL units and streamed to the receiver, which then turns them back into CMSampelBuffers and feeds them to AVSampleBufferDisplayLayer (as is described for instance here). It works quite well - I can see the video and it streams more or less smoothly.
If I set the capture session's sessionPreset to AVCaptureSessionPresetHigh the video shown on the receiving side is cut in half - the top half displays the video from the sender while the bottom half is a solid dark green. If I use any other preset (e.g. AVCaptureSessionPresetMedium or AVCaptureSessionPreset1280x720) the video displays in its entirety.
Has anyone encountered such an issue, or has any idea what might cause it?
I tried examining the data at the source as well as the data at the destination, to see if I can determine where the image is being chopped off, but I have not been successful. It occurred to me that perhaps the high quality frame is being split into more than one NALUs and I am not putting it together correctly - is that possible? How does such splitting look like on the elementary-stream level (if possible at all)?
Thank you
Amos
The problem turned out to be that at the preset AVCaptureSessionPresetHigh one frame would get split into more than one type 5 (or type 1) NALU. On the receiving side I was combining the SPS, PPS and type 1 (or type 5) NAL units into a CMSampleBuffer, but ignoring the second part of the frame if they were split, which caused the problem.
In order to recognize if two successive NAL units belong to the same frame it is necessary to parse the slice header of the picture NAL units. This requires delving into the specification, but goes more or less like this: the first field of the slice header is first_mb_in_slice which is encoded in Golomb encoding. Next come slice_type and the pic_aprameter_set_id, also in Golomb encoding, and finally the frame_number, as an unsigned integer of length (log2_max_frame_num_minus_4 + 4) bits (to get the value of log2_max_frame_num_minus_4 it is necessary to parse the PPS corresponding to this frame). If two consecutive NAL units have the same frame_num they are part of the same frame and should be put into the same CMSampleBuffer.