RTK and Navio

@timkaiser we are now able to send raw data from APM to RTKLIB and receive NMEA from RTKLIB on second GPS port. We developed it on Navio+, so hopefully it will work both for Navio+ and Navio Raw. After code cleanup and small bug fixes we will be able to give it to you for field testing. This will probably take several days more.

1 Like


I’ll be waiting anxiously haha.

Finishing the hardware attachments etc.

Any tips on setting up my rover with a PPM encoder? I have a SkyFly 6 channel transmitter/receiver and a PPM encoder - it looks like it is working well, although when APMrover2.elf is finished booting the rover takes off (or would, if it weren’t up on blocks)…Must be some failsafe configs not quite set right. Do you have a config file for MIssion Planner for your rover?


Maybe a bit off-topic. @timkaiser, can you tell me what do you use for your long range wifi setup ?


1 Like

An ENGenius ENS202 at the base, and a cheap chinese “hipower” USB adapter. Works for about 1km

1 Like

@igor.vereninov any luck on the RTK?



We’ve come up with little hacks for now to make RTK work.

These are the steps that I make to see the obs-count in rtkrcv tick.

  1. you need to clone our APM repo

git clone git@github.com:emlid/ardupilot.git

git clone git@github.com:emlid/RTKLIB.git or use our tutorial to download it

  1. Compile navio-raw-rtk branch

cd ardupilot/APMrover2
git checkout navio-raw-rtk

If you compile on RPI you just type make configure && make navio and you’re good to go!

To cross-compile refer to our tutorial

  1. Launch rtkrcv

cd ~/rtklib/bin-rpi

After rtkrcv's CLI has been launched, type several commands to it:

load rover-single-apm.conf
status 1

  1. Run APM

sudo ./ArduCopter.elf -A udp:<mavproxy ip>:14500 -E tcp:

-E tells APM to use second GPS.

For now we’ve implemented switch to second GPS right after it’s got 2D_FIX.

  1. obs() count in rtkrcv should be updated at 5Hz.

It’s been tested on NavIO+. I’ll test it on NavIO RAW as soon as I get an opportunity.
I believe it should work.

We’ve heard that APM is capable to track your position with cm accuracy. But mavlink uses float to send coordinated. Thus, only meter accuracy in GCS is achievable for now.

There’s some fuss about it right now. Take a look at this issue.

I’ll be glad to help you out anytime. And I’d really appreciate your feedback.

1 Like

Well, hmm.

OK. I looked at the rover-single-apm.conf file.

All that is happening is that APM is sending the GPS info out on the local tcp port (should be 12345), to RTKLIB. Which will allow RTKLIB to calculate an RTK fix when it is also getting the base corrections.

But how does the RTK fix get sent back to APM?

A few points:

  1. if you start APMrover2.elf without rtkrcv running, it generates a “connection refused” error. Even without the -E switch in the command line.

  2. The Navio RAW is not sending recognizable GPS data to rtkrcv over the loopback address port 12345.

  3. Are you sure you won’t give me a trade-in amount on the RAW for a new Navio+, so you don’t have to develop RTKLIB for both?

:smiley: :smiley: :smiley:


1 Like


APM will receive NMEA data from RTKLIB on port -E and see it as secondary GPS unit. Switch to secondary unit will happen when it has fix.

We will check what you have pointed out and I will PM you about Navio+ :smile:

1 Like


  1. This branch was developed to be used with RTKLIB. The error just says that it cannot find rtkrcv. It doesn’t affect other APM functionality.

  2. I’d be really grateful if you connected APM to u-center (it can be launched with wine, if you’re using a linux machine) to see what’s really being trasferred to rtkrcv. In order to do it you need

socat -d -d tcp-l:12345 tcp-l:12346
sudo sudo ./APMRover2.elf -A udp:<mavproxy ip>:14500 (without -E switch)

After that socat will be waiting for connection on

Run u-center.exe and connect to tcp:rpi-ip:12346 (The connection established in the top left corner menus. It’s not really hard to find, but feel free to ask!)

socat will respond to the connection from u-center with some debug info. Thus, you know the connection has been established.

In u-center you need to open Message Configuration and you will see the messages that would get transmitted from APM to rtkrcv (we sniff the data).

If you see the RXM-RAW and RXM-SFRB messaged, everything works as I’d wanted. These are sufficient for rtkrcv to tick obs() count.

If you don’t see anything, the problem might be in AP_HAL_Linux/LinuxSPIDriver.cpp. The wrong speed has been selected for NEO-6T. It might not be able to work @ 4Mhz like NEO-M8N. The only thing you need to change is Ublox’ speed. Try 400KHz.

1 Like


I just updated the repo. You can git pull the changes. If the speed was the issue, all problems will go away.


Made APMrover2 in the right branch.
Running rtkrcv…

And the GPS lock is good. :smiley:

Everything seems to be working… except for the “float” versus “int” problem (resolution). I will hook up my second raw receiver tomorrow as a base and hook it into RTK and see what kind of resolution I get.

Thanks guys! You are GREAT!

@timkaiser is this https://github.com/diydrones/ardupilot/issues/1907 the float / int problem you mention? According to LorenzMeier (who replied to this issue on github )this is an usage issue.


I hooked up my other raw receiver (base station for RTK, a Skytraq raw receiver)… configured it all, ran APM with the hacks… and it works pretty well. It is a cloudy day and I am inside, so I am not getting RTK “fix” solutions, but even with “single” solutions it is within 1 foot of being right (in relation to the base station - I don’t exactly know the coordinates of my base station to the mm, but that’s ok).

I wonder if we will get Mission Planner to display “RTK FIX” or “RTK FLOAT” instead of “3D Fix” on the GPS.

Now, once I get my Sabertooth 2x25 problem figured out, I will be out in the vineyard with this dude; first a flyover with the quad and IR camera… then image processing to see where the bugs are (all ready to go)… then send out the rover with the spray gun.


1 Like

Perfect. I am planing to use the navio+ on RTK on a research quad. I am looking to stream video and telemetry over 4G LTE… Looking forward to the write-up. Thank you for your innovation. I am looking forward to putting this to work.

1 Like

So here’s an update:

“Vinnie” the Landrover:
Frame: Motorized wheelchair. New batteries - 24v system
Motor controller: Sabertooth 2x25, mixed mode RC, microprocessor mode
Telemetry/communications: highpower Wifi (have also tried 933MHz radios, and will probably end up with 4G because of crosstalk/interference)
RTK: NavIO RAW on rover, will probably switch to NavIO+ very soon. Skytraq raw receiver at base; base in house, running strsvr (from RTKLIB) on indoors machine which also runs Mission Planner. The “both-apm.conf” file is attached to this to show you how it is all set up.
RC radio: cheap FlySky 6 channel, with channel 7 on the receiver actually receiving channel 6 from the RC transmitter, and parameters in Mission Planner adjusted accordingly. I aim to get rid of the RC radio entirely soon and just use the 4G telemetry set up for control. But for now it is easier to test.

Attached are the “both-apm.conf” file for configuring rtkrcv, and my rc.local file (which autostarts everything).

Remember to make sure you start rtkrcv FIRST, and wait a bit (sleep 20)… otherwise APMrover2.elf won’t run with the -E switch (btw Igor, shouldn’t it be the case that if APMrover2.elf doesn’t find the second GPS named at the -E switch, that it allows the APMrover2.elf file to still execute, but with a message to that effect? Would be much better that way…)

You can watch rtkrcv at telnet:(RPi IP):12347

Local files are created in a local “temp” directory with info from rtkrcv also.

Problems to be solved:

  1. failsafe — with Sabertooth in this mode, there is no local failsafe for the motors, which means that when APMrover2 loses radio signal (or failsafe’s for whatever other reason), the Sabertooth just keeps doing whatever is was doing before (bad idea, IMO). So I have to add another failsafe to shut down the power or something. ANy ideas?

  2. long-range telemetry (probably pretty easy with some config changes, as soon as I can bring myself to pay for a 4G account for this project) (any ideas? It needs to be reliable to about 1-2km)

  3. cm RTK resolution — I won’t really know what the resolution is until I get the rover outside and play with it awhile (snow on the ground now). I have heard there is a “usage issue” regarding the way (float vs int) things are sent to Mission Planner… Anybody got any more info on this? Anybody trying RTK on a quad or plane?

Here is the both-apm.conf file:

console-passwd =admin
console-timetype =gpst # (0:gpst,1:utc,2:jst,3:tow)
console-soltype =dms # (0:dms,1:deg,2:xyz,3:enu,4:pyl)
console-solflag =1 # (0:off,1:std+2:age/ratio/ns)
inpstr1-type =tcpsvr # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,7:ntripcli,8:ftp,9:http,10:spi)
inpstr2-type =tcpcli # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,7:ntripcli,8:ftp,9:http,10:spi)
inpstr3-type =ftp # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,7:ntripcli,8:ftp,9:http,10:spi)
inpstr1-path =
inpstr2-path =
inpstr3-path =cddis.gsfc.nasa.gov/gps/products/%W/igu%W%D%hb.sp3.Z
inpstr1-format =ubx # (0:rtcm2,1:rtcm3,2:oem4,3:oem3,4:ubx,5:ss2,6:hemis,7:skytraq,14:sp3)
inpstr2-format =skytraq # (0:rtcm2,1:rtcm3,2:oem4,3:oem3,4:ubx,5:ss2,6:hemis,7:skytraq,14:sp3)
inpstr3-format =sp3 # (0:rtcm2,1:rtcm3,2:oem4,3:oem3,4:ubx,5:ss2,6:hemis,7:skytraq,14:sp3)
inpstr2-nmeareq =off # (0:off,1:latlon,2:single)
inpstr2-nmealat =0 # (deg)
inpstr2-nmealon =0 # (deg)
outstr1-type =tcpsvr # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripsvr)
outstr2-type =file # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripsvr)
outstr1-path =
outstr2-path =/home/pi/rtkdata/sol2_%Y%m%d%h%M.pos
outstr1-format =nmea # (0:llh,1:xyz,2:enu,3:nmea)
outstr2-format =nmea # (0:llh,1:xyz,2:enu,3:nmea)
logstr1-type =off # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripsvr)
logstr2-type =off # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripsvr)
logstr3-type =off # (0:off,1:serial,2:file,3:tcpsvr,4:tcpcli,6:ntripsvr)
logstr1-path =/home/pi/rtkdata/rov_%Y%m%d%h%M.log
logstr2-path =/home/pi/rtkdata/ref_%Y%m%d%h%M.log
logstr3-path =/home/pi/rtkdata/cor_%Y%m%d%h%M.log
misc-svrcycle =10 # (ms)
misc-timeout =30000 # (ms)
misc-reconnect =30000 # (ms)
misc-nmeacycle =5000 # (ms)
misc-buffsize =32768 # (bytes)
misc-navmsgsel =rover # (0:all,1:rover,1:base,2:corr)
misc-startcmd =
misc-stopcmd =
file-cmdfile1 =/home/pi/RTKLIB-master/data/ubx_spi_raw_5hz.cmd
file-cmdfile2 =/home/pi/RTKLIB-master/data/skytraq_raw_5hz.cmd
file-cmdfile3 =
pos1-posmode =kinematic # (0:single,1:dgps,2:kinematic,3:static,4:movingbase,5:fixed,6:ppp-kine,7:ppp-static)
pos1-frequency =l1 # (1:l1,2:l1+l2,3:l1+l2+l5)
pos1-soltype =combined # (0:forward,1:backward,2:combined)
pos1-elmask =15 # (deg)
pos1-snrmask =20 # (dBHz)
pos1-dynamics =on # (0:off,1:on)
pos1-tidecorr =off # (0:off,1:on)
pos1-ionoopt =brdc # (0:off,1:brdc,2:sbas,3:dual-freq,4:est-stec)
pos1-tropopt =saas # (0:off,1:saas,2:sbas,3:est-ztd,4:est-ztdgrad)
pos1-sateph =brdc # (0:brdc,1:precise,2:brdc+sbas,3:brdc+ssrapc,4:brdc+ssrcom)
pos1-exclsats = # (prn …)
pos1-navsys =3 # (1:gps+2:sbas+4:glo+8:gal+16:qzs+32:comp)
pos2-armode =off # (0:off,1:continuous,2:instantaneous,3:fix-and-hold)
pos2-gloarmode =off # (0:off,1:on,2:autocal)
pos2-arthres =5
pos2-arlockcnt =0
pos2-arelmask =0 # (deg)
pos2-aroutcnt =5
pos2-arminfix =10
pos2-slipthres =0.05 # (m)
pos2-maxage =30 # (s)
pos2-rejionno =30 # (m)
pos2-niter =1
pos2-baselen =0 # (m)
pos2-basesig =0 # (m)
out-solformat =llh # (0:llh,1:xyz,2:enu,3:nmea)
out-outhead =on # (0:off,1:on)
out-outopt =off # (0:off,1:on)
out-timesys =gpst # (0:gpst,1:utc,2:jst)
out-timeform =tow # (0:tow,1:hms)
out-timendec =3
out-degform =deg # (0:deg,1:dms)
out-fieldsep =
out-height =ellipsoidal # (0:ellipsoidal,1:geodetic)
out-geoid =internal # (0:internal,1:egm96,2:egm08_2.5,3:egm08_1,4:gsi2000)
out-solstatic =all # (0:all,1:single)
out-nmeaintv1 =0 # (s)
out-nmeaintv2 =0 # (s)
out-outstat =off # (0:off,1:state,2:residual)
stats-errratio =100
stats-errphase =0.003 # (m)
stats-errphaseel =0.003 # (m)
stats-errphasebl =0 # (m/10km)
stats-errdoppler =1 # (Hz)
stats-stdbias =30 # (m)
stats-stdiono =0.03 # (m)
stats-stdtrop =0.3 # (m)
stats-prnaccelh =1 # (m/s^2)
stats-prnaccelv =0.1 # (m/s^2)
stats-prnbias =0.0001 # (m)
stats-prniono =0.001 # (m)
stats-prntrop =0.0001 # (m)
stats-clkstab =5e-12 # (s/s)
ant1-postype =llh # (0:llh,1:xyz,2:single,3:posfile,4:rinexhead,5:rtcm)
ant1-pos1 =34.87031095 # (deg|m)
ant1-pos2 =-98.21211167 # (deg|m)
ant1-pos3 =400 # (m|m)
ant1-anttype =
ant1-antdele =0 # (m)
ant1-antdeln =0 # (m)
ant1-antdelu =0 # (m)
ant2-postype =llh # (0:llh,1:xyz,2:single,3:posfile,4:rinexhead,5:rtcm)
ant2-pos1 =0 # (deg|m)
ant2-pos2 =0 # (deg|m)
ant2-pos3 =0 # (m|m)
ant2-anttype =
ant2-antdele =0 # (m)
ant2-antdeln =0 # (m)
ant2-antdelu =0 # (m)
misc-timeinterp =off # (0:off,1:on)
misc-sbasatsel =0 # (0:all)
file-satantfile =/home/pi/RTKLIB-master/data/igs05.atx
file-rcvantfile =/home/pi/RTKLIB-master/data/igs05.atx
file-staposfile =/home/pi/RTKLIB-master/data/station.pos
file-geoidfile =
file-dcbfile =/home/pi/RTKLIB-master/data/P1C1_ALL.DCB
file-tempdir =/home/pi/rtkdata
file-geexefile =
file-solstatfile =
file-tracefile =

and add these to your rc.local file:

sudo /home/pi/RTKLIB-master/bin-rpi/rtkrcv -s -p 12347 -o /home/pi/RTKLIB-master/bin-rpi/both-apm.conf &

sleep 20

sudo /home/pi/ardupilot/APMrover2/APMrover2.elf -A udp: -E tcp: > /home/pi/startup_log &

1 Like


I can already tell that the RPi standard B+ is not going to have enough juice to do everything that needs to be done.

I have an RPi2, but probably will switch to Odroid platform for Vinnie (the land part) and use the RPI or RPi2 for the quad.

1 Like


The APM prohibits this behavior. If you provide an address for the switch, it’d better be working.
It’s not difficult to ignore that constraint, though. But I don’t think it’s that necessary. isn’t it?

The same trouble here. The weather is kinda messy, so that’s not feasible to test outside.

I’ll look into the issue in the next couple of days as soon as I got some spare time.

The obs() count does tick, doesn’t it?

1 Like

Yes… if you look at the rtkrcv through telnet (I have mine set on port 12347), you can see the obs counter tick on both the rover GPS and the base GPS. So it is getting observations. What I am wondering is in what format the output fix is sent and whether that is the problem. Doesn’t seem like it should be, though. I don’t think my .sp3 corrections are coming through though…

1 Like

Hey guys,

I’m trying to use RTK lib with my NAVIO+ for postprocess positioning. NAVIO+ is equipped with Ublox M8N and to use that receiver along with RTK lib you have to acquire TRK-MEAS and TRK-SFRBX msgs (correct me if I’m wrong) and a few others that are not an issue. I tried looking at Ublox M8N documentation and there is not a single word about TRK msgs (class 0x03). Only information I found abut them is on link. Is there any other site, that you know of, with information about this type of messages? Also do you have some advice on how to process received msgs form Ublox in order to covert it to RINEX format that is expected in RTK postprocess?

1 Like


You are right, you need TRK-MEAS ad TRK-SFRBX messages for RTK, they are not officially supported by u-blox. These messages were found by enthusiasts, they were meant to be used for debug purposes.

You can convert them to RINEX using RTKLib converter.