A few simple debugging tips for RTKLIB

Unfortunately, error reporting is not one of RTKLIB’s strengths.  Sometimes it will halt with an error message that is less than helpful, other times it will just continue through the entire solution with Q=0 or Q=2 without ever getting a fix because of a minor error in the input file configuration or parameters. I suspect anyone who has used RTKLIB with any regularity has run into cases like this innumerable times. It still happens to me all the time, almost always because I have made a silly mistake somewhere. For a new RTKLIB user, it can be quite difficult to figure out why they are not getting a valid solution in cases like this.

In this post, I will demonstrate some examples of common errors and some techniques to help identify them. First let’s take a quick look at a couple of real-time solution examples with RTKNAVI, then I will jump to post-processing cases for the rest of the examples.

In my experience, the most common error when using RTKNAVI is to improperly specify the base location. To demonstrate this, I go to the “Positions” tab on the “Options” menu in RTKNAVI and switch the Base Station position type from “Average of Single Position” to “RTCM Position”. In this example, my base stream is u-blox binary and contains no RTCM messages so RTKLIB will not get any valid base location information and can not calculate a solution. However, rather than halting and letting the user know there is a problem, RTKNAVI just runs through the whole solution without ever reporting either an error or a valid position. To help understand what happened in a case like this, the first step is to click on the tiny unlabeled square above the “Start/Stop” button. This will bring up the RTK Monitor window. Choose “Error/Warning” from the Monitor options as shown in the image below to bring up additional error and warning information.

In this case, every sample reports an “initial base station position error”. This should be enough information to track down the problem fairly quickly. Often this will be the case. If the additional information in this window doesn’t help, then the next step is to enable the debug trace and look at the trace file. This is covered in more detail in the post-processing examples further below.

In my experience, the second most common reason to get no solution with RTKNAVI is that navigation messages haven’t been enabled for either base or rover receiver. If this is the case, then all the SNR bars will be gray. When navigation data is available, the bars will be colored as in the image above. Lack of SNR bar color is the easiest way to detect this problem but another symptom is that the “Error/Warning” window will report “No common satellites” for every sample even though satellites are appearing in the SNR window.

A more general troubleshooting technique that will work for either real-time or post-processing and for GUI or command line RTKLIB applications is the debug trace file. I will demonstrate a couple of examples of using this with RTKPOST but the same basic technique can also be used with RTKNAVI, RNX2RTKOP, RTKCONV, CONVBIN, or STRSVR.

To enable the debug trace, set “Output Debug Trace” in the “Options” menu to something other than “OFF”. For simple errors, level 2 is enough and will produce a less overwhelming amount of information. For more detailed information about the GNSS solution, especially the ambiguity resolution, level 3 is better. For more details about the communication streams, level 4 can be useful. Level 5 includes many of the solution matrices and is too detailed for most general debug. Level 1 only contains the error messages available in the error window and is not useful. The image below from the RTKPOST Options menu shows the trace level set to 3. I usually set it to level 3 since I am often looking at the details of the ambiguity resolution, but for simple debug I would recommend starting with level 2 and that is what I will use in the examples below.

Next, I will intentionally make some silly mistakes and show how they appear in the error window and the trace file.

Let’s start with an example where RTKPOST actually does a good job of reporting the error to demonstrate how it should work, and occasionally does. To keep the example simple I will use files in the root directory, with names: rover.obs, base.obs, and rover.nav.

In this first case, I have made a typo in the name of the .nav file. Now, when I click on “Execute” to start the solution, it almost immediately halts and reports “Error: no nav data” in the error window near the bottom of the window. If only RTKLIB would always be as straightforward as this!

Next, I intentionally make a typo in the rover observation file and click on “Execute”. Again, the solution halts almost immediately but in this case the error message in the error window is much less useful. Not only does it not tell me which file has a problem, but it also suggests there is something specific wrong with the input data, not that the file is completely missing. Fortunately, clicking on another tiny unlabeled square (circled in red below) brings up the trace file, assuming trace debug was enabled as described above. This tells us exactly what went wrong, that the input rover observation file could not be opened.

For the next example, I will correct the typo in the file name but then set the location in the base rinex file header to all zeros. This is another common problem and usually happens because the rinex file was generated by RTKCONV or other application from a binary receiver output file that did not contain navigation messages. Without navigation information, RTKCONV can not estimate the receiver location and sets the approximate position field in the rinex header to all zeros. Again, the solution halts almost immediately, and the error message is identical to the previous case. However, looking at the trace file, there is now no mention of a file open error. To understand the difference between these two trace files, it’s important to know that the entries in the trace file beginning with 2 are warnings, and those beginning with 1 are errors. RTKLIB treats the missing file as a warning since there may be other observation files that are present, and doesn’t get an actual error until it looks for the base position information. With just the error, it is impossible to tell these two case apart, but by looking at the warnings as well, it is fairly easy to differentiate them.

Another fairly common error is to use the wrong base observation file. If the base observations do not overlap the rover observations in time, then the solution will run all the way through the data, without error, but the solution status will always be Q=0. Here’s the trace output for this example. I aborted the run before it completed, after it was obvious that something is wrong which is why the error windows shows “aborted”. The “age of differential” is the time between rover observation and closest base observation so again in this case, looking at the trace file makes the problem much more obvious

If the wrong navigation file is used, the solution will again run to the end with no error, and the status will remain Q=0, just as above, but this time the trace file will report “no common satellites”

Another mistake I make fairly often, is when I am specifying the precise base location rather than using the approximate location in the rinex header, and I forget to change it when moving to a different data set with a different base location. In this case, the solution will run without error, but the fix status will remain in float (Q=2) for the entire solution. There are several reasons why you might never get a fix, including just poor quality data, but in this case when I look at the trace file I see extremely large outliers right from the first sample. If all the satellites are reporting outliers and they are as large as this, that almost always means that the base location has been specified incorrectly.

These are only a few examples but probably cover over 80% of cases I look at where people are unable to get a solution. Most of the rest are caused by low quality data.

If you have other examples of common failures that I haven’t covered here, please describe them in a comment, along with the signature seen in the trace file.

47 thoughts on “A few simple debugging tips for RTKLIB”

  1. i am having problem in rtkplot. I have inserted the google api key in gm_html file but still on live processing no map is shown in rtkplot option can someone guide.

    Like

  2. I’m having trouble processing subsets of data.

    I did a day trip with dynamic parts and static parts when I want to do accurate measurements on specific items. I’m using a F9P with a data logger (https://github.com/PaulZC/F9P_RAWX_Logger) that is recording ubx files, one each 15 minutes. Back home, I merge all files in one. I can process it using RTKPOST with quite good results in kinetic mode (80% fix, 20 % Q=2, with some tree cover). Now, I want to do calculation on static points so I indicate start and stop times in RTKCONV (or in RTKPOST) but RTKPOST is not able to solve, both in kinetic mode or in static one. I always have Q=0. Looking at debug:
    2 no receiver antenna pcv:
    2 pcv without radome is used type=TRM57971.00 TZGD
    2 10:45:19.99: point pos error (iteration divergent i=10)
    2 10:45:19.99: slip detected forward (sat=45 rcv=1 F=1 LLI=1)
    2 10:45:19.99: slip detected half-cyc (sat=56 rcv=1 F=1 LLI=0->2)
    2 10:45:19.99: slip detected half-cyc (sat=56 rcv=1 F=2 LLI=0->2)
    2 10:45:19.99: rover initial position error
    2 10:45:20.99: point pos error (iteration divergent i=10)
    2 10:45:20.99: rover initial position error
    2 10:45:21.99: point pos error (iteration divergent i=10)
    2 10:45:21.99: outlier rejected (sat= 21- 8 L1 v=522606.078)
    2 10:45:21.99: outlier rejected (sat= 21- 10 L1 v=-426705.761)
    2 10:45:21.99: outlier rejected (sat= 21- 11 L1 v=-690127.609)

    Even if I use a single quarter hour file, except the first one, I can’t get a fix. It’s like if there are some specific informations at the beginning of the log that are missing otherwise.

    Any clue?

    Like

    1. Hi Eric. I have not seen this exact problem before but I suspect the base position is being specified incorrectly somehow. The biggest clue in the debug log is the rejected outliers which are reporting errors of 429 to 690 km. The most likely reason for such large errors is that the base position is being specified incorrectly.

      Like

      1. Hi,

        Thanks for looking at my issue.

        The base position (and parameters) is OK when I process the full record file. So, there is no reason that it became wrong when I submit a subset.

        Also, I was walking so distance between start point and the subset is about 1 km. Indeed, looking in RINEX file, the header line is the same for full and subset files:
        4460154.0925 463144.3756 4522818.4216 APPROX POSITION XYZ
        In the subset, I manually replaced coordinates with better values but I still have the problem.

        Should be some trouble with earth rotation? It’s about 0.365 km/s at this point. Recording started at 10:11 :01. Subset starts at 10:45:20. Difference is of 2059 s. So earth rotation is of 670 km.

        Like

        1. Hi Eric. RTKLIB is using ECEF coordinates which are earth centered, earth fixed, so earth rotation will not affect your solution. RTKLIB can have trouble with the solution diverging if there are large gaps of missing data in the rover observations, maybe this is what you are seeing? It should be OK to use subsets of your data as long as they don’t include large gaps.

          Like

          1. So, after a careful investigation, I discovered that my data were wired. When looking at satellite elevation in the rinex file, there was a bunch of jumps in the elevation curves of all satellites. The same was observed after post-processing in the .pos file. So, I suspected that the position or some estimation of it was wrong. Indeed, the post-processed track was correct and NMEA track extracted from the .ubx file was also correct. The two other recordings early in the morning were OK. I suspected something wrong in the navigation file. Indeed, using navigation file from a reference station didn’t change anything. Then, I compared post-processing with the different constellations. I discovered that the trouble was coming from Glonass satellites. As glitches were present only for the first two thirds of the recording, I looked at Glonass satellites available at the same time. Removing R24 strongly improved results but some glitches remained. In addition, I removed R14 and last glitches vanished. Then I was able to do calculations on the choose subset. Victory!
            The morning recording were not affected because the two corresponding satellites were not visible. Also, recording of the same satellites were fine at the nearby reference station. So I don’t where is the problem (sat signal, F9P treatment?) but it exists. I can send you the faulty file if you want to investigate.

            Like

    2. Hi Eric

      I know nothing about the F9P or too much about RTKLIB, but I know I can see the same situation with my split-then-merged files (or any-but-the-first) when I ignore NMEA sentences (or GNSS-board-specific binary packets) (often ones coming at a LOW frequency) from later files which appeared in an earlier file. I record such data in a “most recent” map and write them into the start of the new file, myself.

      Hope that helps. Not sure how close to the metal you are
      Neil

      Like

      1. Yes, that’s exactly that: any-but-the-first. Indeed, my UBX files are containing NMEA sequences that I can extract before or after merge. But, after conversion from UBX to RINEX, no trace of NMEA sequence remains, as expected.

        Like

  3. Hi

    Your pages are proving a GREAT help in making sense of RTKLIB – thanks!

    Can you please tell me; is it possible to get RTKPOST (RNX2RTKP) to output GGA strings (via the NMEA 0183 Option) at 10Hz? I think the answer is “Yes – set the Interval to 0.1s”. But my efforts still see me getting 1Hz output. Since my Rover RINEX Obs file is only at 1Hz, I am wondering if that is where the problem lies?

    Thanks in advance

    Neil

    Like

    1. Hi Neil. The post-processing RTKLIB apps (RTKPOST and RNX2RTKP) don’t run synchronously to the data samples, they just process the data as fast as they can, so 1 Hz or 10 Hz output doesn’t make a lot of sense in this context. I think what you are referring to is just a decimation option for the output samples relative to the input observations. In this case you will not be able to set the output sample rate faster than the input sample rate.

      Like

  4. Tim,

    I own a company called GPMe and we are currently working on developing a program that relies on the core functions of RTKLIB.

    My developer stumbled on this forum and I am incredibly impressed with your working knowledge of RTKLIB. Is there a proper way to reach out to you directly, outside of this forum, to possibly ask a few in depth questions?

    Like

    1. Did you look at the menu item at the top labelled Consulting? Looks like Tim’s got a new gig and isn’t taking on new clients, but there is an email address.

      Like

  5. Hi Tim,
    Thank you very much for this website ..very useful! I was wondering if you had experienced any issue when using rtklib to visualize the multipath indicators or SNR versus satellite elevations. Sometimes it happened to me that, even if I uploaded the navigation file, rtklib does not show the satellite elevation. Any suggestion?
    Many thanks!

    Like

    1. Hi Mel. I have not seen this problem. Multipath estimates will only be plotted if you have both L1 and L2 data but the elevations should always be plotted if you have valid navigation data. Does your satellite visibility plot show the satellites in yellow/green or just gray? If the satellites are all gray, this usually indicates that the navigation data is either missing or not valid.

      Like

  6. I’m also having trouble getting a fix in moving configuration, using RTKPOST. So, I use a F9P. The antenna is sticking on the roof of the car. I’m trying to drive slow, i.e. no more than 30 km/h. I was less than 5 km from a base station which provide GPS and Glonass data. Looking in RTKPLOT, all GPS sats provide L1/L2 and some also L5. Nearly all Baidou provide L1/L2 and only two with just L1. Some parts of the road had tree cover but, even in open area, I can’t get the fix. For instance, the first 3 minutes, I was driving very slow on a track without cycle slip.
    In debug file, I can see:
    2 no receiver antenna pcv:
    2 no receiver antenna pcv:
    2 16:50:12.00: position variance too large: 8.6259
    2 16:50:13.00: position variance too large: 4.8198
    […]
    2 16:50:49.00: position variance too large: 0.1100
    2 16:50:50.00: position variance too large: 0.1044
    2 16:50:51.00: ambiguity validation failed (nb=8 ratio=2.92 thresh=3.00 s=77.37/226.01)
    2 16:50:52.00: large residual (sat=53-42 L1 v= 0.372 sig=0.014)
    2 16:50:52.00: large residual (sat=53-43 L1 v=-0.247 sig=0.013)
    2 16:50:52.00: large residual (sat=53-52 L1 v=-0.110 sig=0.014)
    2 16:50:52.00: large residual (sat=53-43 L2 v=-0.243 sig=0.013)
    2 16:50:52.00: large residual (sat=53-52 L2 v=-0.110 sig=0.014)

    Any clue on how to improve fix?

    Options:
    Kinematic
    L1+L2
    Combined
    Integer Ambiguity Res : GPS: Fix and Hold ; GLO : Auto Cal

    Something to do with antenna calibration? The base station comes with an .ATX file but I don’t know what to do with it.

    Like

    1. Hi Eric. My first guess would be that you have Glonass Ambiguity Resolution set to Autocal and have not set the Glonass HW biases properly. This option is badly named since it is really not calibrating automatically. You can either set Glonass Ambiguity Resolution to “Fix-and-Hold” which will work for unmatched receivers without worrying about the HW biases or you can read this post on how to set the biases manually.

      Like

      1. Thanks for your answer.

        I read the post again and I played again with the Glonass bias on static measurements. First, having a Trimble base station and a F9P rover, I tried using table values (Trimble = -0.7 cm/u-blox = -3.2 cm -> -0.025) but didn’t got good results. So, I tried manually. With values between 0.005 and 0.007, I obtained instantaneous Gloanss AR, at the same time as GPS AR. The Glonass Carrier-Phase Residuals were also very small, not distinguishable from GPS one. (u-blox value was for M8T and this suggests that for F9P, it should be near 0 cm).

        Despite such improvement in static condition (that I also checked at the beginning of my dynamic sequence), the fix of the dynamic sequence was not significantly improved.
        Glonass AR : Fix and Hold : 5.5%
        Glonass AR : Auto Cal / 0.006 : 6.1%
        Now that I know the Carrier-Phase Residuals graph :-), I can see that when I start moving with my car, Carrier-Phase is becoming noisy. May I have an issue with the engine like with your drone?
        Investigations are underway.

        Like

        1. Hi Eric. Yes you are very correct! … the u-blox F9P Glonass bias is zero, or near zero. When I wrote that post back in 2018, the F9P had not come out yet and so was not included in my testing. I had not realized till just now that I never went back and updated the table in that post to include the F9P. I have done that now as well as added a couple of other receivers I have since tested. Thanks for making me aware of this and sorry for any inconvenience that caused.

          Like

          1. Indeed, I think you already wrote it somewhere because I’ve already read elsewhere that F9P bias was near zero. 😉

            Like

  7. Hi Tim, I read your post and got a lot of helpful Suggestions, but when I was debugging rtknavi app, I ran into some problems.
    I compiled demo5_b33 using C++Builder and tested rtknavi’s single location using NEO-M8T, but sometimes I did not get the result. Error/Warning reported that “chi-square Error…”
    Then I downloaded a compiled rtknavi.exe(demo5_b31), and with the same hardware and software configuration, I got the correct results.How can I solve this problem?

    Like

    1. Hi Aaron. From your description, it is not clear if the difference is between versions b31 and b33 or between your compile and my compile. I don’t know have any good explanation for why either difference would cause this problem. Were you running RTKNAVI on recorded data or live data? If run on live data, then the difference could also be caused by variation in the real-time inputs. I would suggest logging some data and re-running it to verify which is the root cause. Make sure you enable time-tag files for both logging and replay.

      Like

  8. Tim
    A bit confused about antenna height. In Topcon Tools, you just select from a drop down box for the correct antenna name/brand and then input vertical or slant antenna height. In RTKlib:
    1. Where do you get the antenna parameters NGS08.atx? or IGS08.atx? Sokkia antennae are available in the NGS08.atx but not in the IGS08.atx.
    2. Will RTKlib read the antenna parameters from the atx file automatically? Is there a way to verify that it read the correct antenna parameter from the results file?
    3. What do I input into the U box? slant or vertical height?
    Thanks.

    Like

    1. Hi Jun. Entering antenna type and offsets in RTKLIB can be a little confusing and is not well documented. You first need to specify the file that contains the calibration data in the Options/Files tab. You can use the igs14.atx file that is included with the demo5 executables. Antenna type and offsets are often specified in the header of the rinex observation file. If you want to use these values, set the “Antenna Type” field in the Options/Positions tab to “*”. If you want to manually specify antenna type AND offsets you can do that with the “Antenna Type” and “Delta-E/N/U” fields. The correct values for the Delta-E/N/U fields are simply the East, North, and Up offsets in meters for the antenna. Be aware that you can only use the antenna type and offsets from the rinex header or from the configuration values, RTKLIB never combines values from both.

      Like

      1. Thank you Tim,
        I am trying out the different options in RTKLib by comparing the results with what I get from Topcon & Spectra post processing software. Even the 2 results from Topcon & Spectra are different although in the cm level.
        Strange that I get the closest results when using sp3 files in RTKLib to N files in Topcon/Spectra results.

        Like

        1. Hi Vlad. If you specify an antenna type in the RTKLIB solution then RTKLIB looks for the antenna calibration data in the antenna file. You need to specify the location and name of this file in the Files tab in the options menu or in the config file. You can use the igs14.atx file included with the demo5 executables for common antenna types.

          Like

          1. Thank you Tim.
            Yes, I use the igs14.atx file included with the demo5 – but the result is the same. This is with RTKNavi – not RTKPost. I need to use RTKNavi. I am surveyor and I get 1 cm accuracy. But can not input antenna offset. I use U-Blox ZED-F9P and u-blox ANN-MB-00 Antenna for GNSS Dual Band
            If you can help me I will be very, very thankful
            Best Regards

            Like

          2. Hi Vlad. The antenna file is specified the same way in RTKPOST and RTKNAVI. There are two rows in the files tab of the options menu for the antenna file. The first row is for the satellites and the second for the receivers. For RTK/PPK solutions you don’t need to specify the satellite antennas so just need to fill in the second row. Make sure to include the complete absolute path of the file, references for relative paths can be confusing in RTKLIB.

            Like

  9. Hi Tim
    Just downloaded the latest RTKLib and currently reviewing the various functions. I have been using GNSS Solutions for my post-processing and was trying to compare the results from the 2 software. I would like to ask a few questions:
    1. Using the same RINEX files, I am getting a fix solution (static) from GNSS Solutions but RTKLib I am getting a large file with individual second results. Most of which have the Q:4 solution. Shouldn’t I be getting just 1 lat/long/height solution?

    Where do you input the antenna height? I saw the the Options/Positions window with the Delta E/N/U boxes. The antenna height should go into the U box?

    Thank you.

    Like

    1. Hi Jun. A Q=4 solution is a DGPS solution. You must have the solution mode set to “dgps” instead of “kinematic”, meaning you are using pseudorange measurements only, no carrier phase. I would only recommend this for very poor quality data where the carrier phase measurements have so many cycle slips that they are degrading the solution. Yes, the antenna height should go into the Delta U box.

      Like

  10. Hi Tim,

    Congratulation for your web site, advices, codes …. I’ve used it, tested it on pc and RpiZeroW
    I’m located in North of France and want to use rtklib + 2 * neo m8t in real time calculation
    for agricultural driving purposes.

    Actual configuration is :
    Base on top of house (with ground plane):
    Hardware : neo m8t (CSG Shop) + ublox magnetic antenna ($20) + 433 MHz uhf transceiver
    Software : RawX + Sfrbx messages at a rate of 1 Hz

    Rover on top of tractor cab :
    Hardware : neo m8t + ublox magnetic antenna ($20) + uhf receiver + RpiZeroW
    Software : RpiZeroW with RTKRCV 2.4.3 (messages rate of 5 Hz) + the configuration file you provided for RTKRCV

    For debugging I use RtkNavi 2.4.3 demo b29d on PC and have tested all the points you’ve mentioned above
    I’ve roughly the same results on Rpi and on the PC (with the same .conf file) Good point …

    My system is “working”, it’s possible but difficult to have a fix, and more, to maintain it for a long time
    most of the time it’s float and the location is slightly always shifting.
    When the sky is very clear, it’s more easy to have fix.
    UHF link is stable and the base messages are comming OK in the Rpi
    In RtkNavi I’ve 7 to 10 satellites (green) between 40 and 50 db in Rover and Base frame
    The message error in RtkNavi is almost always “ambiguity validation failed” with 9 to 12 satellites, and ratio 1 to 1.5

    I’ve explored a lot things, configurations and tested all your advice but the result stays roughly at same level.
    I think of the following things, and at last I’ve post a question on your blog :
    Can it comes from my antennas, will it be much better with Tallysman or other dedicated rtk antenna ?
    Is there some specific setting for Europe in Ublox module or in RtkRcv I’ve not set ?
    Maybe there is another point I’ve forgotten ?
    Could it be much better if I move to zed f9p with dual band antenna at both sides ?

    If someone have roughly the same configuration in Europe, I’m interested to know if the results are better ?
    Any help appreciated
    If you need pictures of the system, don’t hesitate to ask me
    Best regards from France
    francois

    Like

    1. Hi Francois. Two M8T receivers with open sky views should be giving you a high percent of fix if you have RTKLIB set up correctly. The only setting you should need to change for Europe is to disable the SBAS constellation since the EGNOS satellites will degrade the solution. Make sure you have the GPS, Glonass, and Galileo constellation enabled on both base and rover and Glonass ambiguity resolution set to on since you have matched receivers. Also be sure you are using ground planes with both antennas. Higher quality antennas will improve the solution. You will see an even bigger improvement with the F9P, but of course the cost it a fair bit higher as well.

      Like

        1. Hi Damjang. I’m guessing you meant the M8N, since there is no u-blox N8T. You can not enable Galileo on M8N receivers running the older 2.xx firmware. The newer 3.xx firmware does support Galileo but does not support raw observations.

          Like

          1. Oh, sorry, I meant M8T. Do you think that I can update my M8T from v2.30 to v3.01 fw? I hear that update can fail because v3.01 is not officially compatible with M8T.

            Like

          2. Hi Damjang. The u-blox M8T is upgradable but the version 3 firmware that is compatible with the M8T is not available from the u-blox website. You would have to get that directly from u-blox or possibly one of their distributors but I think they only provide it to their larger customers.

            Like

  11. Hi Tim, nice post, I will try the debug level setting to help with fine tuning of the processing parameters.
    Is there a way to set the output debug trace level in the conf file? I see ‘out-outstat’ to set off;state;residual and ‘file-tracefile’ presumably to override the default trace file path, but nothing that refers to the debug trace level.
    Cheers
    Max

    Like

    1. Hi Max. I don’t believe there is an option in the config file to set the debug trace level but it can be set as a command line option for both RNX2RTKP (-x) and RTKRCV (-t). For example to set it to 2 in RNX2RTKP, add “-x 2” to the command line.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.