Panoramax JuraMap trail views


JuraMap


Panoramax notes

A simplified version of the deprecated proof-of-concept TrekView Explorer has been used for the panoramic viewing of JuraMap trails. This Rails-based server is being replaced by the backend and web API of a Panoramax instance for storing and viewing field photos. The trails are displayed on the "Trails" layer of the detailed raster JuraMap.

The background map tiles for the Panoramax trails layer is the vector JuraMap which is rendered using TileKiln, as explained in an Implementation Note.

The menu system for the raster JuraMap allows a Panoramax web viewer to be displayed using a modal (the Panoramax web viewer derived from the Geovisio web viewer is demonstrated here). The same approach can be used for the vector JuraMap.

1. Dynamic alignment

A major issue arose. It is unclear how the Geovisio/Panoramax viewer's map can be centred dynamically so as to align with the base map. As discussed below, one way to achieve alignment is to set an intial centre for the Geovisio web viewer and then to calculate the map centre when the base map is moved.

2. Distance between photos

The JuraMap trails are historic trails (i.e., probably existed at the end of the 19th century). As shown on the vector JuraMap , the trails involve hiking (OpenStreetMap sac_scale = hiking) or mountain hiking (sac_scale = mountain_hiking) with visibility ranging from "excellent" through "intermediate" to "bad".

The speed of walking is generally fairly slow and the distance between photos need only be about 100 to 200 metres in most cases (we do not plan to use the shorter distances needed for feature detection models).

Using a Google Pixel 4a smartphone, it is proving fairly difficult to establish Panoramax settings that avoid having duplicate photos which break the line representing the sequence of photos that is shown on the Panoramax map.

The problem may be the smartphone's relatively inacurate GPS. This is demonstrated in the Panoramax viewer where photos appear to correspond to points that are a few metres from trails. Moreover, the EXIF coordinate data for some photos are transferred to the next photo. Repositioning the photos is needed (using, for example, the JSOM OpenStreetMap editor with the photoadjust and photo_geotagging plugins).

3. Photo sequence mapping

To make sure that a sequence of photos that are separated by a fairly long distance (typically 100 to 200 metres), the variable ST_Length has changed from 50 to 300 in the Postgresql database function "compute_sequence_geometry" (thus making a multiline geometry for the sequence, spliting each picture separated by more than 300 meters). This changed can be made using pgAdmin or by executing a Python migration.after editing the file in "geovisio/migrations" with the name starting with "20240813". In the API repository, a change from 50 metres to 75 metres was made recently.

4. Playback speed

The other significant change was to force the time duration of the web-viewer's playback of each photo in a sequence to be the maximum. This was done by adding "&speed=3000" to the urlHash variable described below or by setting a viewer option ("transition:3000") according to the web viewer API documentation.

This change is for the variable "TransitionDuration Changes" which is the duration of stay on a picture during a sequence play. It is not immediately clear how the duration can be set more elegantly to the maximum value (speed = 3000). It may also be necesssary to set the Flask environment variable PIC_MAX_STAY_DURATION=3000.

Setting a constant playback speed of 3000 (or a smaller value for a shorter duration) was needed because the drop-down in the Geovisio web viewer to adjust the sequence playback speed sometimes was not displayed for an unknown reason.


A. Panoramax installation

A1. Geovisio API

Installing a Postgresql database followed the normal procedure for OpenStreetMap editing and rendering applications. Installing the Panoramax API is straightforward (see gitlab repository).

Regarding API settings, for initial testing it is useful to use Flask and simply execute in a terminal:

  • flask run

with an .env file of the form:


FLASK_APP=geovisio

DB_URL=postgres://user:user@localhost:5432/geovisio

FS_URL=/home/user/geovisio/data

INFRA_NB_PROXIES=1

FLASK_RUN_HOST=0.0.0.0

PICTURE_PROCESS_DERIVATES_STRATEGY=PREPROCESS

API_ACCEPT_DUPLICATE

PIC_MAX_STAY_DURATION=3000


It is noted that the Geovisio API is set up to run behind an Apache2 proxy (hence the environment setting "INFRA_NB_PROXIES=1", see documentation).

A2. Geovisio (Panoramax) web viewer

To integrate the Geovisio web viewer into the JuraMap raster app, following the documentation the most straightforward approach was to clone the repository, rename its directory from "web-viewer" to "geovisio-viewer" for clearer identification, and execute in terminal:

  • cd geovisio-viewer
  • npm install
  • npm build

The files "geovisio-viewer/build/index.js" and "geovisio-viewer/build/index.css" were then copied to the JuraMap raster map web directory called "history" (i.e., to "/var/www/html/history" for a Ubuntu 18.04 system). With the renaming of Geovisio to Panoramax in the Gitlab repository, the index files are best called geovisio-index.js or more correctly index-panoramax.js, and similarly for index.css

To integrate in the JuraMap raster app, a Leaflet Bootstrap modal (see repository) was set up that had as its body statement:

  • <div id="viewer" class="fullpage">

which is the same as the statement used for the Geovisio web viewer (see the file "geovisio-viewer/build/viewer.html").

The JuraMap raster app uses Leaflet.ActiveLayers so a Leaflet layerGroup is needed for the "Trails" layer of Panoramax photos that are displayed using the Bootstrap modal:

  • var viewerLayer1 = new L.layerGroup(viewer)
  • this.trails = {name:"Trails", layer:viewerLayer1}

The key statement in the JuraMap raster Javascript is:

  • viewer = new Geovisio.Viewer("viewer,"https://geovisio.juramap.org/api",{transition:3000,style:"https://www.juramap.org/tiles/pnorman.json",map:{center: mapCenterCoords, startWide:true, minZoom:19, maxZoom:19}});

where:

  • "https://geovisio.juramap.org/api" is the Geovision (Panoramax) API address;
  • "https://www.juramap.org/tiles/pnorman.json" is the address of the JuraMap vector map TileKiln renderer.

The web viewer's API Reference is crucial. Aside from the options for "map" (i.e., "options.map") "startWide", "minZoom" and "maxZoom" also listed are "raster", "center", "zoom", "bounds", and "geocoder". According to the API Reference "raster" must be a MapLibre raster source definition, so all the options may not work for a web viewer that uses a vector map as a background source.

However, alignment of the base map and the viewer map seems to work if:

  • the centre is initially set as center:[6.61,46.48] for an initial map centre at latitude 46.48 and longitude 6.61;

Once the base map is moved, the viewer map is aligned by calculating mapCentre according to the maplibre-gl LngLatLike object definition and an URL hash:

  • var latCentre = map.getCenter().lat.toFixed(6);
  • var lngCentre = map.getCenter().lng.toFixed(6);
  • var jsonDataAry = [{"coordinates":[lngCenter, latCenter]}];
  • mapCenter = jsonDataAry[0].coordinates;
  • var urlHash = mapZoom+"/"+latCenter+"/"+lngCenter+"&focus=map&map="+mapZoom+"/"+latCenter+"/"+lngCenter
  • window.location.hash = urlHash;

B. Photography

Streetview ("Panoramax") photography seems to be poorly established for use in remote locations in less-developed countries. Although apps such as SW Maps with GPS correction data from a NTIRP caster (streamed directly to SW Maps or by having the provider of the Android mock connection app (a developer option) set as the GNSS Master app) work well, one would hope to be able to acquire and automatically geo-tag high-resolution panoramic or photosphere images.

While we work out the best and simplest way to obtain geo-tagged high-resolution panoramas for example, the Positioning discussion below for now only considers an accurate positioning of a base station where a photo is taken. Ultimately, the aim is to take photos at a rover's position, where the rover's position is determined in conjunction with the base station. In other words, a precisely positioned static base station sends corrections to a moving rover to obtain high real-time precision for the rover's position using Real-Time Kinetic (RTK) positioning.

So far, the best option in the case of a GNSS receiver (Drotek RTK module DP0601) configured using the u-center default configuration with an Internet (TCP/IP) connection between a Pixel 4a Android smartphone's hotspot and a Raspberry Pi 3B+ attached to the GNSS receiver is to use the Lefebure NTRIP Client Android app with the PointPerfect SPARTN GNSS correction service, a mock Android connection and either the Mapillary for Android app or SW Maps to take geo-tagged photographs.

The RTKLIB str2str program (see below) can be used instead of Lefebure or GNSS Master to stream PointPerfect SPARTN correction data for processing by the receiver, noting that these GNSS apps are still needed in order to set the smartphone's mock location for use with a streetview application such as Mapillary and SW Maps or a camera app such as OpenCamera.

With the default receiver configuration, a Bluetooth connection (from the smartphone to the receiver) instead of a tcp/ip Internet connection via a smartphone hotspot does not work with either the two NTRIP clients (Lefebure or GNSS Master) or str2str. This needs to be checked.

For the Mapillary app, as a guest as opposed to being logged in to Mapillary, the Mapillary app allows a single, wide-angle photo to be taken that can be saved to the Pictures -> Mapillary folder. The saved .jpg 72 dpi 4032 x 3024 pixels standard 0.6 magnified Pixel 4a 4 x 3 "full image" retains the EXIF geo-tags. Panoramas made by rotating the smartphone comprise a series of stiched photos. Each photo can also be saved, but not the stiched panorma.

For the u-blox ZED-F9P receiver, the CFG-NMEA-HIGHPREC configuration setting reportedly gives 7 digits after the decimal point, which is non-standard. For the SW Maps app, which does not have a panorama mode, for the high-precision geo-tag message configuration the app displays Decimal Minutes with 6 decimal places before saving an image as a .jpg file (e.g., a latitude with 26.965051 minutes). The Windows 10 Explorer information for the file gives 26; 0.57903 Decimal Seconds, equivalent to 26.96505 Decimal Minutes. The actual location for this example is 46; 26.96505 Degrees; Decimal Minutes, equivalent to 46.4494175 Decimal Degrees so by all accounts, SW Maps retains the high-precision geo-tag of 7 decimal places for Decimal Degrees on saving and corresponding to a precision of about 10 cm. But care must be taken to use an EXIF editor or reader that parses EXIF meta-data correctly.

OpenCamera has a panorama mode and panoramas are geo-tagged to 27; 1.6199 Decimal Seconds parsed using Windows Explorer. This is one decimal place less than for SW Maps. For some unknown reason, we are having difficulty taking 360-degree panoramas (we manage at most about 180 degrees). Assuming nonetheless that a full 370 degree panorama can be taken, it is unfortunate that the OpenCamera's geo-tag precision is much less than for SW Maps (46.054045, or 6 decimal places, equivalent to a precision of about 100 cm).

The Mapillary app retains a significantly higher precision for .jpg images compared to SW Maps (and OpenCamera). It saves the high-precision position geo-tag as Degrees; Minutes; Seconds (e.g., 46; 26; 57.901908) with Seconds to 6 decimal places as opposed to Decimal Minutes to 6 decimal places for SW Maps. It is therefore unfortunate that Mapillary's guest-mode only allows a single wide-angle photo to be taken instead of a stitched panorama.

C. Base station positioning

Accurate geo-tagging of a photo uploaded to the Panoramax server requires satellite-based Global Positioning System (GPS) data to be corrected. The GPS data is acquired by a GPS receiver located on a base station or on a rover that communicates with a base station. We consider first base stations and the cases where a base station has access to the Internet over a wide area network or via smartphone's mobile data network during field work in remote areas.

C1. Real-time online correction data available

If the base station has available an Internet connection, an accurate Real Time Kinetic (RTK) positioning combined with Precise Point Positioning (PPP) Global Navigation Satellite System correction services (called RTK-PPP) can be implemented to give the position for each photo uploaded to the Panoramax server. PPP models GNSS errors using data generated by a network of global reference stations to deliver corrections to a GPS receiver via satellite or over the Internet to improve position accuracy. Single-station RTK-PPP involves connecting a NTRIP caster to a NTRIP client that transmits corrections to a GPS receiver (corrections are calculated by the receiver). In our case, for field work power must come from a portable power bank. With the receiver as a base station, the aim is for a geolocated photo taken at the receiver's position and uploaded to the Panoramax server to have its position coordinates stored in the photograph file as EXIF tags.

Our base station connects a Drotek RTK module (DP0601) by a USB cable to a RasperryPi single-board computer (RaspberryPi 3B+) powered using a nominally 5 Volt powerbank (SBS). A note in passing: acquiring suitable powerbanks for a RasberryPi is not straightforward (some exotic brands - CRAVE Plus 10000 mAh and RAVPower 20000 mAh - are recommended). The RaspberryPi connects to a Google smartphone (Pixel 4a) WiFi hotspot and the smartphone's RealVNC Viewer remote desktop app is used to manipulate the RaspberryPi and the GPS receiver.

There are two types of low-cost antenna for GPS receivers, namely survey and patch antenna. We use either an uncalibrated, ground-plane surveying Drotek DA901 antenna or a u-blox ANN-MB2-00 all-band patch antenna.

For the PPP positioning of a base station, high-performance geodetic survey antenna provide 2 to 3 times better accuracy than patch antenna largely owing to multipath effects. Second, low-cost calibrated survey antenna perform better than patch antenna, athought a patch antenna's horizontal accuracy may be better. In general, therefore, a survey antenna is probably preferable for a base station that is not configured as a base - rover arrangement.

For a base - rover arrangement to be discussed later, it is best to have the same antenna for both the base and the rover. Patch antenna are better than low-cost survey antenna for real-time kinetic (RTK) positioning the rover if the separation (baseline) between the base and the rover is short (less than a kilometre). In terms of repeatability of the baseline, the repeatability using patch antenna decreases when the baseline exceeds 25 km.

Before connecting the GPS receiver to the RaspberryPi it is probably wise to establish factory settings on the Drotek's DP0601 u-blox RTK ZED-F9P multi-band GNSS receiver using u-center on a Windows PC. It is also necessary to check firmware using the dialog in uCenter found at: UBX ⇒ MON (Monitor) ⇒ VER (Version) ⇒ "Poll". u-blox provides instructions for updating firmware.

Installing RealVNC on an Android smartphone and a RaspberryPi is discussed elsewhere. A key initial step is to configure the Raspberry's WiFi so that it connects to the WiFi network that is used to configure the RaspberryPi and the GPS receiver. A RaspberryPi terminal command:

  • sudo nano/etc/wpa_supplicant/wpa_supplicant.conf

is used to edit the file "wpa_supplicant.conf" by adding:


network={convert

ssid=" MyNetworkSSID"

psk=" Password"

}


Connecting a smartphone to the RaspberryPi's desktop requires the internet address of the smartphone's hotspot. In our case, the simplest is to display the address by connecting the RaspberryPi to a display screen before configuration and photographing starts. The address is displayed when the drop-down at the top-right of the RaspberryPi's desktop is used to connect the RaspberryPi to the hotspot. The address in our case is of the form "192.168.x.83". Fortunately, the number x remains the same until the Pixel 4a (Android version 14) is rebooted. The Network Anaylzer app that scans the local area network can also identify the Pixel 4a WiFi hotspot Internet address.

Once the GPS receiver is connected to the Internet and to the GPS receiver, the PyGPSclient graphical GNSS testing, diagnostic and device configuration application is installed on the RaspberryPi. PyGPSclient is written in Python and can be installed in a virtual environment using terminal commands of the form:

  • sudo apt install -y python3-pip
  • mdir pygps
  • cd pygps
  • python3 -m venv .
  • source bin/activate
  • pip3 install --upgrade pygpsclient
  • pygpsclient

PyGPSclient is used to obtain the base's position for geo-tagging photos taken at the base's position. The most straightforward procedure appears to be to set the receiver's configuration to the PyGPSclient default settings (in PyGPSclient: USB/UART ⇒ UBX Config ⇒ "RESTORE FACTORY DEFAULTS") with the PyGPSclient's NTRIP Client configuration "Data type" set to "SPARTN".

The u-blox Windows application u-center can also be used by connecting the receiver to a Windows PC USB port, selecting the u-center COM port and setting Messages View ⇒ UBX ⇒ CFG ⇒ CFG ⇒ "Revert to default configuration" ⇒ Send. Also needed is UBX ⇒ RXM ⇒ RAWX ⇒ right click ⇒ "Enable message".

If a u-center Network Connection is used instead of a USB connection u-center default configuration can be set using View ⇒ Configuration View ⇒ CFG (Configuration) ⇒ "Revert to default configuration" ⇒ Send (in other words, use Configuration View instead of Messages View). RAWX messages are enabled using View ⇒ Configuration View ⇒ MSG (Messages) ⇒ 02-15 RXM-RAWX ⇒ check USB.

Connecting a Pixel 4a to a RaspberryPi 3B+ to set up a Network Connection using Bluetooth is not particularly straightforward. For a RasberryPi 3B+ with the current 64bit Bookworm RaspberryPi OS, relevant terminal commands for Bluetooth are:

  • systemctl status/start bluetooth (to check/start Bluetooth)
  • hciconfig ("hciconfig -a" to check and obtain the Bluetooth address)
  • bluetoothctl (to run the various commands that pair the Pixel 4a to a Windows PC)
  • sudo l2ping XX:XX:XX:XX (to check that the Pixel 4a Bluetooth is connected where XX:... is the Pixel 4a Bluetooth address)

One then needs to set up the RaspberryPi so that the smartphone's Bluetooth connection can connect to the GPS receiver's serial port. Accordingly, in a terminal:

  • sudo nano /etc/systemd/system/dbus-org.bluez.service
  • add " -C" to the end of "ExecStart=/usr/lib/bluetooth/bluetoothd"
  • add "ExecStartPost=/usr/bin/sdptool add SP" as the next line

After a reboot and restarting Bluetooth, run in a terminal:

  • sudo sdptool browse local

to check that a "Serial Port" with "Channel 1" is listed. Then connect to the Bluetooth part with:

  • sudo rfcomm watch hci0 1

to check that the RaspberryPi is listening for a connection on Bluetooth serial. Displayed in the terminal should be: "Waiting for connection on Channel 1" and when a Bluetooth connection to the Raspberry Pi is made: "Connection from XX:XX:XX:XX:XX to /dev/rfcomm0". A smartphone app such as Serial Bluetooth Terminal (currently Version 1.48) can be used to type smartphone terminal commands that are displayed on a Raspberry Pi terminal using:

  • cat /dev/rfcomm0

Add this stage it is wise to check that u-center on the Windows PC can acquire GPS observation data when the GPS receiver is connected to one of the RaspberryPi's USB ports. When the Drotek receiver is connected the u-blox F9P creates automatically a port called "/dev/ttyACM0". Check this using:

  • ls /dev/tty*
  • sudo cat /dev/ttyACM0

The receiver's output should be displayed on using the terminal command:

  • python -m serial.tools.miniterm /dev/ttyACM0

To connect the receiver's ttyACM0 to a serial port (often ttyAMA0 or ttyS0) gpsd is often needed but in fact does gpsd does not work with the PointPerfect NTRIP service (and many other NTRIP services) since a GNGGA message string (sentence) is needed to identify the receiver's position. The following is noted nevertheless.

  • sudo apt-get install gpsd gpsd-clients

Some processes (identified using the terminal "ps aux ¦ grep ttyS0") may need to be removed and it helps to stop and disable gpsd at boot:

  • sudo systemctl stop gpsd.socket
  • sudo systemctl disable gpsd.socket

gpsd is manually run in a terminal:

  • sudo gpsd /dev/serial0 -F /var/run/gpsd.sock

The terminal commands "gpsmon", "cgps", "xgps", and "gpspipe -r" should display receiver data.

But as noted, gpsd does not work with the PointPerfect NTRIP service.

PyGPSClient and pygnssutils.gnssntripclient both support the PointPerfect SPARTN NTRIP service and can return the required GNGGA sentence(s), formatted with either fixed reference coordinates or the live position from an active receiver.

The gnss

In the meantime, u-centre on the Windows PC can be used as the client by setting up a u-center WiFi Network Connection. This requires redirecting the serial interface of the RaspberryPi to a network port by installing ser2net and editing or creating a "ser2net.conf" file:

  • apt install ser2net
  • sudo nano /etc/ser2net.conf

with the line

  • 6000:raw:600:/dev/ttyACM0:115200 NONE 1STOPBIT 8DATABITS XONXOFF LOCAL -RTSCTS

Starting ser2net followed by checking the interface with:

  • sudo ser2net -u
  • sudo netstat -ltnp | grep 6000

should display a message which refers to tcp6 output on port number 6000 and gives the process id (PID). The "-u" option disables UUID locking so that ser2net with a PID displayed as say "1234" can be stopped with:

  • sudo kill 1234

Other recipes have been proposed. None seem to work, including possibly the one proposed here. In the end one resorts to rebooting the RasberryPi in order to stop ser2net.

An alternative to ser2net is the RTKLIB str2str. The advantage of str2str is that the NTRIP correction data can be streamed to the receiver with the corrected output streamed to a tcp/ip port. The str2str terminal command is of the form:

  • ./str2str -in ntrip://pp_username:pp_password@pp_hostname:pp_port/pp_mountpoint -out serial://ttyACM0:115200#50000 -b 1

The "pp_" parameters are for a -blox PointPerfect GNSS correction service or equivalent NTRIP account and the corrected output is streamed to tcp/ip port = 50000 (i.e., to the smartphone's hotspot, say 192.168.33.83:50000) thus making the corrected data available to the NTRIP client (e.g., Lefebure or GNSS Master) used to set the smartphone's mock location.

In our case, since correction data is being fed to the Drotek 601, the receiver's RTK status LED blinks while the RTK type is "float" and switches off when a "fix" is obtained. Similarly, the SW Maps, the colour for the position pointer changes colour when a "fix" is acheived (blue: regular GNSS fix; orange: RTK Float); green: RTK Fix).

The corrected data stream can be strated automatically on booting up the RaspberryPi. Several recipes have been demonstrated:


rc.local autostart edit rc.local (sudo nano /etc/rc.local") by adding:

  • cd /etc/usr/local
  • sudo ./str2str -in ntrip://pp_username:pp_password@pp_hostname:pp_port/pp_mountpoint -out serial://ttyACM0:115200#50000 -b 1

(note that "sudo" is need) to move to the str2str directory, which can of course be on a USB key that is mounted using a terminal command of the form:

  • sudo mount /dev/sda1 /media/usb -o uid=raspi,gid=raspi

register a bash file, say "ntrip-serial.sh", that starts corrected data streaming as an autostart file.


crontab with “crontab -e" to add the task:

  • @reboot sudo /etc/usr/local/str2str <statement above> &

Installing str2str is fairly strightforward. The latest RTKLIB version (b34k) is downloaded:

  • wget -qO - https://github.com/rtklibexplorer/RTKLIB/archive/refs/tags/b34j.tar.gz | tar -xvz

and the str2str compilation flags are set by editing the makefile in the directory

/home/user/RTKLIB//app/consapp/str2str/gcc

Then run "make" and "sudo make install" and copy the str2str executable in the "gcc" directory to say "/home/usr/local/bin".

For tcp/ip connections as opposed to Bluetooth:

  • u-center: when using u-center, create a Receiver ⇒ Connection ⇒ Network Connection ⇒ New of the form "tcp:192.168.x.y:6000" where the address is the address of the RaspberryPI and connect the receiver by selecting "Network connection" in the u-center "Select Receiver Port" dropdown. If the connection is via the smartphone's hotspot with for example "192.168.111.83" as the address the Network Connection address is say "tcp:192.168.111.83:6000" (the Windows PC will of course need to have its WiFi connection set to the smartphone's hotspot) . If the connection is via the RaspBerryPi's LAN WiFi address, say "192.168.1 222", the Network Address is "tcp:192.168.1.222:6000"
  • str2str: when using str2str with a NTRIP client app such as GNSS Master for a mock location, set the TCP connection address as the Raspberry Pi's LAN WiFi address (say "192.168.1 222:5000") or its hotspot address (say "192.168.112.83:5000") if the Raspberry Pi is connected to the smartphone's hotspot .

It seems that positionning corrections are applied if the receiver is configured with either the u-centre "Revert to default configuration" (i.e., connecting the receiver to a Windows PC USB port and setting Messages View ⇒ UBX ⇒ CFG ⇒ CFG ⇒ "Revert to default configuration" ⇒ Send) or the PyGPSclient's "RESTORE FACTORY DEFAULTS". The u-center default configuration can also be set when u-center uses a network connection instead of a USB connection. In this case, View ⇒ Configuration View ⇒ CFG (Configuration) ⇒ "Revert to default configuration" ⇒ Send must be used (i.e., use Confguration View instead of Messages View).

To date, only the PointPerfect correction service has been used (requires setting up a Thingstream account). The Galileo HAS (High Accuracy Service) Internet Data Distribution NTRIP service is being examined since it is in principle available in areas and regions not presently covered by most NTRIP correction services including PointPerfect (a HAS request for access has been approved).

Once a RTK fix is established, for photos taken at the base position, the base coordinates can be noted or stamped as EXIF geo-tags if the camera allows (as is the case for Android streetmap and mapping apps mentioned above). The coordinates stored in a .jpg image can be adjusted if necessary using the JOSM OpenStreetMap editor with the photo_geotagging and photoadjust modules installed. On opening an image in JOSM, the "Geotagged Images" layer is set as active and "Edit" ⇒ "Edit photo GPS data" is selected in order to enter the base's latitude and longitude coordinates. A right click on "Geotagged Images" ⇒ "Write coordinates to image header" is then needed before the geo-tagged photo is uploaded to the Panoramax server.

Instead of noting or stamping the base-station's coordinates, a PyGPSclient log file can be saved in a directory called "data" for example. A webserver is then established using the terminal commands:

  • cd data
  • python3 -m http.server

such that the log file is available at the web address of the Raspberry Py web server ("http://192.168.1.222:8000" as an example). Of the many other alternatives for transferring files from a Raspberry Pi to a Windows PC WinSCP is recommended. The log file can also be streamed to a USB key. Once downloaded, the log file can be played using u-center on a Windows system to obtain the photo's latitude and longitude coordinates (displayed as Reference Position ⇒ Average in u-center's Deviation Map).

Another procedure (which can also be used for a series of geo-tagged photos) is to convert the .obs file to a .gpx file. The .gpx file is then edited in Notebook or a similar editor to create waypoints by replacing "trk" an the tags by "w" and deleting the <tk> and <trkseg> tags. Separately, JOSM preferences at Edit ⇒ Preferences ⇒ GPS Points ⇒ Waypoint labelling is set to "?{ '{time}' }" so that the time a geo-tagged photo was taken is displayed in JOSM beside each waypoint. The displayed waypoint times are then matched to the base-station's geo-tagged photo in order to set the base-station position in JOSM.

Yet another possibility stems from the fact that JOSM also allows interpolation of a photo's position using a GPS track.

At this point, since one is now talking about mapping, it is perhaps useful to point out that to determine the GPS coordinates of any measured point first requires the definition of a reference frame (a global network of accurately measured points with defined Cartesian coordinates). Moreover, in order to achieve meaningful centimetre or millimetre level accuracy, all components in the end-to-end application (including the GPS data source, maps and geo-referenced imagery) must use the same or related "plate-fixed" reference frame.

WGS84 is the reference system used by the Global Positioning System (GPS) and is the default reference datum used by ZED-F9P (see UBX-CFG-DATUM). WGS84 is regularly released to keep it coincident with the ITRF reference frame. The PointPerfect reference frame is ITRF2020 current epoch. WGS84 realisations since October 2018 are coincident with ITRF at the sub-centimetre level so while there are no official transformation parameters one can consider that ITRF2020 and WGS84 are likely to agree at the sub-centimetre level. Photos tagged using u-blox F9P observations can therefore be treated in JOSM in the same way as OpenStreetMap features.

The Galileo HAS system uses the Galileo Terrestrial Reference Frame (GTRF). For a given point, the difference between coordinates expressed in ITRF and GTRF is less than 3 cm.C1.2. Correction data not available

C2. Online post-processing correction data available

If real-time correction data is not available (either because a mobile data connection or a NTRIP caster is not available for the region) the GPS receiver's log file can be used for PPK post-processing to obtain the base-station's position accurately. In this case, once a fix is achieved the PyGPSclient.log file is saved and downloaded to the Windows PC.

The file is then renamed as .ubx and the rtklib rtlconf executable is used to convert the .ubx log file with u-blox protocol to a .obs RINEX file (the u-blox F9P receiver's raw observation data is configured to supply UBX-RXM-RAWX data packets which are decoded and rendered as RINEX). As above, recommended is the demo5 version (the latest is demo5 b34k) of rtklib which has Windows executables (dated 11/9/2021 and synchronised up to the b34 versions of rtklib version 2.4.3). The RINEX observation file can then be uploaded to Canada's CSRS-PPP service or other similar services (APPS, AUSPOS, DGDPS, OPUS) to receive by email a CSRS-PPP report giving the corrected position of the base station.

To avoid the need for a Windows PC in the field, a solution would be to install u-center on the RasberryPi by first installing Wine. However, in the field it would probably be impactical to use a RealVNC desktop on a smartphone to manipulate u-center.

Nonetheless, it is worth noting that if a Windows PC is available in the field, instead of transfering the .ubx file from the RaspberryPi as described above, the Windows PC with u-center and a Bluetooth or TCP/IP hotspot connection to a RasberryPi connected to the GPS receiver can be used to configure a GPS receiver and collect GPS observation data. RTK corrections are then applied by post-processing (using either a real-time service with playback of the observation data or via online submission of the observation data).

D. Base station summary

The discussion so far has described how the accurate geo-tagging of photos taken at a specific position (called a base station position) can be carried out using a simple kit comprising:

  • a smartphone (Pixel 4a) having available a mobile data Internet connection and access to an Internet-distributed GPS correction service (PointPerfect);
  • a low-cost GPS receiver (Drotex DP0601 connected to a Drotek DA09011 survey antenna or a patch antenna);
  • a small computer (RaspberryPi 3B+) with on-board wireless networking (WiFi);
  • a low-cost smartphone power bank (SBS) to power the RaspberryPi and the receiver.

Preliminaries:

  • the RaspberryPi has been configured after connecting it to a monitor, keyboard and mouse (automatic WiFi hotspot);
  • the RaspberryPi hotspot address (e.g., 192.168.111.83) is known using the RasberryPi's desktop WiFi dropdown or an Android app such as Network Analyzer;
  • the receiver has been configured using u-center or PyGPSclient default/factoryconfiguration;
  • an online correction service is available, either in real-time or via the submission of data for post-processing;
  • set a smartphone's GNSS app as the mock location provider for a camera app that can geo-tag images.

Pixel 4a:

  • open RVNC Viewer app and connect to RaspberryPi:

Pixel 4a RVNC Viewer commands:

-- PyGPSclient

  • open a RaspberryPi terminal
  • enter "cd /pygpsclient" (location of PyGPSclient)
  • enter "source bin/activate"
  • enter "pygpsclient"
  • select UBS/UART (to start GPS observation data collection and saving of a .ubx file in a "data" directory)
  • select NTRIP Client and select arrow icon to start
  • once a RTK fix is indicated, note the coordinates displayed in View ⇒ Scatter Plot window
  • open a webserver ("python3 -m http.server") and download the .ubx file for post-processing correction.

-- str2str

  • open a RaspberryPi terminal
  • execute the RasberryPi str2str command to stream corrected observation data to the smartphone.

E. Rover positioning

To be discussed


13 December 2024

PeterBoswell.com