check_rtcm3.c
Go to the documentation of this file.
00001 
00002 #include <string.h>
00003 #include <stdio.h>
00004 #include <math.h>
00005 #include <check.h>
00006 #include "check_utils.h"
00007 
00008 #include <rtcm3.h>
00009 
00010 START_TEST(test_rtcm3_check_frame)
00011 {
00012   /* Test data taken from RTCM 10403.1 Document Example 4.2 */
00013   u8 test_data[] = {
00014     /* Frame Header. */
00015     0xD3, 0x00, 0x13,
00016     /* Data Message. */
00017     0x3E, 0xD7, 0xD3, 0x02, 0x02, 0x98, 0x0E, 0xDE, 0xEF, 0x34, 0xB4, 0xBD,
00018     0x62, 0xAC, 0x09, 0x41, 0x98, 0x6F, 0x33,
00019     /* CRC. */
00020     0x36, 0x0B, 0x98
00021   };
00022 
00023   /* Check against valid data. */
00024   s16 ret = rtcm3_check_frame(test_data);
00025   fail_unless(ret == 19,
00026       "Should return length 19 for test_data, got %d", ret);
00027 
00028   /* Corrupt preamble byte. */
00029   test_data[0] = 0x22;
00030   ret = rtcm3_check_frame(test_data);
00031   fail_unless(ret == -1,
00032       "Should return -1 for test_data with invalid preamble, got %d", ret);
00033 
00034   /* Correct preamble byte and corrupt data message. */
00035   test_data[0] = 0xD3;
00036   test_data[4] = 0x22;
00037   ret = rtcm3_check_frame(test_data);
00038   fail_unless(ret == -2,
00039       "Should return -2 for test_data with invalid CRC, got %d", ret);
00040 }
00041 END_TEST
00042 
00043 START_TEST(test_rtcm3_write_frame)
00044 {
00045   u8 test_data[] = {
00046     /* Frame Header. */
00047     0x22, 0x22, 0x22,
00048     /* Data Message. */
00049     0x3E, 0xD7, 0xD3, 0x02, 0x02, 0x98, 0x0E, 0xDE, 0xEF, 0x34, 0xB4, 0xBD,
00050     0x62, 0xAC, 0x09, 0x41, 0x98, 0x6F, 0x33,
00051     /* CRC. */
00052     0x22, 0x22, 0x22
00053   };
00054 
00055   /* Test data taken from RTCM 10403.1 Document Example 4.2 */
00056   u8 test_data_expected[] = {
00057     /* Frame Header. */
00058     0xD3, 0x00, 0x13,
00059     /* Data Message. */
00060     0x3E, 0xD7, 0xD3, 0x02, 0x02, 0x98, 0x0E, 0xDE, 0xEF, 0x34, 0xB4, 0xBD,
00061     0x62, 0xAC, 0x09, 0x41, 0x98, 0x6F, 0x33,
00062     /* CRC. */
00063     0x36, 0x0B, 0x98
00064   };
00065 
00066   u8 test_empty[] = {
00067     /* Frame Header. */
00068     0x22, 0x22, 0x22,
00069     /* CRC. */
00070     0x22, 0x22, 0x22
00071   };
00072 
00073   u8 test_empty_expected[] = {
00074     /* Frame Header. */
00075     0xD3, 0x00, 0x00,
00076     /* CRC. */
00077     0x47, 0xEA, 0x4B
00078   };
00079 
00080   s8 ret = rtcm3_write_frame(2222, NULL);
00081 
00082   fail_unless(ret == -1,
00083       "Should return -1 if length is larger than 1023, got %d", ret);
00084 
00085   fail_unless(rtcm3_write_frame(0, test_empty) == 0,
00086       "Returned error on test_in_empty");
00087 
00088   fail_unless(memcmp(test_empty, test_empty_expected, 6) == 0,
00089       "test_empty != test_empty_expected");
00090 
00091   fail_unless(rtcm3_write_frame(sizeof(test_data)-6, test_data) == 0,
00092       "Returned error on test_in_empty");
00093 
00094   fail_unless(memcmp(test_data, test_data_expected, sizeof(test_data)) == 0,
00095       "test_data != test_data_expected");
00096 }
00097 END_TEST
00098 
00099 START_TEST(test_rtcm3_read_write_header)
00100 {
00101   u8 buff[22];
00102 
00103   gps_time_t t = {
00104     .wn = 22,
00105     .tow = 22.222
00106   };
00107 
00108   rtcm3_write_header(buff, 1234, 2269, t, 1, 22, 1, 6);
00109 
00110   u16 type, id;
00111   u8 sync, n_sat, div_free, smooth;
00112   double tow;
00113 
00114   rtcm3_read_header(buff, &type, &id, &tow, &sync, &n_sat, &div_free, &smooth);
00115 
00116   fail_unless(type == 1234, "type decode error, decoded %d, expected 1234", type);
00117   fail_unless(id == 2269, "id decode error, decoded %d, expected 2269", id);
00118   fail_unless(fabs(tow - t.tow) < 1e-3, "TOW decode error, decoded %f, expected %f", tow, t.tow);
00119   fail_unless(sync == 1, "id decode error, decoded %d, expected 1", id);
00120   fail_unless(n_sat == 22, "n_sat decode error, decoded %d, expected 22", n_sat);
00121   fail_unless(div_free == 1, "div_free decode error, decoded %d, expected 1", div_free);
00122   fail_unless(smooth == 6, "smooth decode error, decoded %d, expected 6", smooth);
00123 }
00124 END_TEST
00125 
00126 
00127 START_TEST(test_rtcm3_encode_decode)
00128 {
00129   navigation_measurement_t nm_orig[22];
00130   navigation_measurement_t nm[22];
00131 
00132   seed_rng();
00133 
00134   for (u8 i=0; i<22; i++) {
00135     nm[i].prn = i;
00136     nm[i].raw_pseudorange = frand(19e6, 21e6);
00137     nm[i].carrier_phase = frand(-5e5, 5e5);
00138     nm[i].lock_time = frand(0, 1000);
00139     nm[i].snr = frand(0, 20);
00140   }
00141 
00142   memcpy(nm_orig, nm, sizeof(nm));
00143 
00144   gps_time_t t = {
00145     .wn = 1234,
00146     .tow = frand(0, 604800)
00147   };
00148 
00149   u8 buff[355];
00150 
00151   rtcm3_encode_1002(buff, 1234, t, 22, nm, 0);
00152 
00153   navigation_measurement_t nm_out[22];
00154   double tow_out;
00155   u8 sync, n_sat = 222;
00156   u16 id;
00157 
00158   s8 ret = rtcm3_decode_1002(buff, &id, &tow_out, &n_sat, 0, &sync);
00159 
00160   fail_unless(ret >= 0, "rtcm3_decode_1002 returned an error (%d)", ret);
00161   fail_unless(id == 1234, "decoded station id as %d, expected 1234", id);
00162   fail_unless(n_sat == 22, "decoded n_sat as %d, expected 22", n_sat);
00163   fail_unless(fabs(tow_out - t.tow) < 1e-3, "decoded TOW as %f, expected %f, error %f",
00164       tow_out, t.tow, tow_out - t.tow);
00165 
00166   ret = rtcm3_decode_1002(buff, &id, &tow_out, &n_sat, nm_out, &sync);
00167 
00168   for (u8 i=0; i<22; i++) {
00169     fail_unless(nm[i].prn == nm_out[i].prn, "[%d] PRNs not equal - "
00170         "decoded %d, expected %d", i, nm_out[i].prn, nm[i].prn);
00171 
00172     double pr_err = nm[i].raw_pseudorange - nm_out[i].raw_pseudorange;
00173     fail_unless(fabs(pr_err) < 0.02, "[%d] pseudorange error > 0.04m - "
00174         "decoded %f, expected %f, error %f", i, nm_out[i].raw_pseudorange, nm[i].raw_pseudorange, pr_err);
00175 
00176     double carr_err = nm[i].carrier_phase - nm_out[i].carrier_phase;
00177     fail_unless(fabs(carr_err) < 0.003, "carrier phase error (fractional part) > 0.003 cycles - "
00178         "[%d] decoded %f, expected %f, error %f", i, nm_out[i].carrier_phase, nm[i].carrier_phase, carr_err);
00179 
00180     double snr_err = nm[i].snr - nm_out[i].snr;
00181     /* Calculate error bound on SNR given logarithmic error bound on CNR. */
00182     double err_bound = nm[i].snr * (pow(10.0, 1.0 / 40.0) - 1);
00183     fail_unless(fabs(snr_err) < err_bound, "SNR error > 0.003 - "
00184         "[%d] decoded %f, expected %f, error %f, bound %f", i, nm_out[i].snr, nm[i].snr, snr_err, err_bound);
00185 
00186     fail_unless((nm_out[i].lock_time == 0) && (nm[i].lock_time == 0),
00187         "lock time should be zero when adjusting int. amb. - [%d] decoded %f",
00188         i, nm_out[i].lock_time, nm[i].lock_time);
00189 
00190     double cp_adj = nm[i].carrier_phase - nm_orig[i].carrier_phase;
00191     fail_unless(fmod(cp_adj, 1.0) == 0,
00192         "carrier phase adjusted by non integer amount %f -> %f (%f)",
00193         nm_orig[i].carrier_phase, nm[i].carrier_phase, cp_adj);
00194   }
00195 
00196   /* Re-encode after adjustment, now there should be no further adjustment and
00197    * the lock time should be correct. */
00198 
00199   for (u8 i=0; i<22; i++)
00200     nm[i].lock_time = frand(0, 1000);
00201 
00202   rtcm3_encode_1002(buff, 1234, t, 22, nm, 0);
00203   rtcm3_decode_1002(buff, &id, &tow_out, &n_sat, nm_out, &sync);
00204 
00205   for (u8 i=0; i<22; i++) {
00206     double cp_adj = nm_out[i].carrier_phase - nm[i].carrier_phase;
00207     fail_unless(cp_adj < 0.003, "carrier phase re-adjusted %f -> %f (%f)",
00208         nm[i].carrier_phase, nm_out[i].carrier_phase, cp_adj);
00209 
00210     fail_unless(nm_out[i].lock_time <= nm[i].lock_time,
00211         "lock time error, should always be less than input lock time - [%d] decoded %f, expected %f",
00212         i, nm_out[i].lock_time, nm[i].lock_time);
00213   }
00214 }
00215 END_TEST
00216 
00217 
00218 Suite* rtcm3_suite(void)
00219 {
00220   Suite *s = suite_create("RTCMv3");
00221 
00222   TCase *tc_core = tcase_create("Core");
00223   tcase_add_test(tc_core, test_rtcm3_check_frame);
00224   tcase_add_test(tc_core, test_rtcm3_write_frame);
00225   tcase_add_test(tc_core, test_rtcm3_read_write_header);
00226   tcase_add_test(tc_core, test_rtcm3_encode_decode);
00227   suite_add_tcase(s, tc_core);
00228 
00229   return s;
00230 }
00231 


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:28