diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000000..58807032f3
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,43 @@
+{
+    // Use IntelliSense to learn about possible attributes.
+    // Hover to view descriptions of existing attributes.
+    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "type": "java",
+            "name": "Current File",
+            "request": "launch",
+            "mainClass": "${file}"
+        },
+        {
+            "type": "java",
+            "name": "ProjectionCLI",
+            "request": "launch",
+            "mainClass": "org.openstreetmap.josm.data.projection.ProjectionCLI",
+            "projectName": "josm"
+        },
+        {
+            "type": "java",
+            "name": "ProjectionRefTest",
+            "request": "launch",
+            "mainClass": "org.openstreetmap.josm.data.projection.ProjectionRefTest",
+            "projectName": "josm"
+        },
+        {
+            "type": "java",
+            "name": "ProjectionRegressionTest",
+            "request": "launch",
+            "mainClass": "org.openstreetmap.josm.data.projection.ProjectionRegressionTest",
+            "projectName": "josm"
+        },
+        {
+            "type": "java",
+            "name": "MainApplication",
+            "request": "launch",
+            "mainClass": "org.openstreetmap.josm.gui.MainApplication",
+            "projectName": "josm",
+            "vmArgs": "-Djosm.dir.name=JOSM-dev --add-exports=java.base/sun.security.action=ALL-UNNAMED --add-exports=java.desktop/com.sun.imageio.plugins.jpeg=ALL-UNNAMED --add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED",
+        }
+    ]
+}
\ No newline at end of file
diff --git a/nodist/data/exif-position-error.jpg b/nodist/data/exif-position-error.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..db8edf752efa8b0274e7f89a20534da20e122219
GIT binary patch
literal 47012
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
Sd`idhJ9(nE<}muSkN?>xYR41+

literal 0
HcmV?d00001

diff --git a/src/org/openstreetmap/josm/data/ImageData.java b/src/org/openstreetmap/josm/data/ImageData.java
index 232ecc6588..7a0ae4a3f4 100644
--- a/src/org/openstreetmap/josm/data/ImageData.java
+++ b/src/org/openstreetmap/josm/data/ImageData.java
@@ -365,6 +365,83 @@ public class ImageData implements Data {
         afterImageUpdated(img);
     }
 
+    /**
+     * Update the GPS track direction of the image and trigger update.
+     * @param img the image to update
+     * @param trackDirection the new GPS track direction
+     * @since xxx
+     */
+    public void updateImageGpsTrack(ImageEntry img, double trackDirection) {
+        img.setExifGpsTrack(trackDirection);
+        afterImageUpdated(img);
+    }
+
+    /**
+     * Update the image horizontal positioning error and trigger update.
+     * @param img the image to update
+     * @param hposerr the new horizontal positionning error
+     * @since xxx
+     */
+    public void updateImageHPosErr(ImageEntry img, double hposerr) {
+        img.setExifHPosErr(hposerr);
+        afterImageUpdated(img);
+    }
+
+    /**
+     * Update the image GPS differential mode and trigger update.
+     * @param img the image to update
+     * @param gpsDiffMode the new GPS differential mode
+     * @since xxx
+     */
+    public void updateImageGpsDiffMode(ImageEntry img, Integer gpsDiffMode) {
+        img.setGpsDiffMode(gpsDiffMode);
+        afterImageUpdated(img);
+    }
+
+    /**
+     * Update the image GPS 2d/3d mode value and trigger update.
+     * @param img the image to update
+     * @param gps2d3dMode the new 2d/3d GPS mode
+     * @since xxx
+     */
+    public void updateImageGps2d3dMode(ImageEntry img, Integer gps2d3dMode) {
+        img.setGps2d3dMode(gps2d3dMode);
+        afterImageUpdated(img);
+    }
+
+    /**
+     * Update the image GPS DOP value and trigger update.
+     * @param img the image to update
+     * @param exifGpsDop the new GPS DOP value
+     * @since xxx
+     */
+    public void updateImageExifGpsDop(ImageEntry img, Double exifGpsDop) {
+        img.setExifGpsDop(exifGpsDop);
+        afterImageUpdated(img);
+    }
+
+    /**
+     * Update the image GPS datum and trigger update.
+     * @param img the image to update
+     * @param exifGpsDatum the new datum string value
+     * @since xxx
+     */
+    public void updateImageExifGpsDatum(ImageEntry img, String exifGpsDatum) {
+        img.setExifGpsDatum(exifGpsDatum);
+        afterImageUpdated(img);
+    }
+
+    /**
+     * Update the image GPS processing method and trigger update.
+     * @param img the image to update
+     * @param exifGpsProcMethod the new GPS processing method
+     * @since xxx
+     */
+    public void updateImageExifGpsProcMethod(ImageEntry img, String exifGpsProcMethod) {
+        img.setExifGpsProcMethod(exifGpsProcMethod);
+        afterImageUpdated(img);
+    }
+
     /**
      * Manually trigger the {@link ImageDataUpdateListener#imageDataUpdated(ImageData)}
      */
diff --git a/src/org/openstreetmap/josm/data/gpx/GpxConstants.java b/src/org/openstreetmap/josm/data/gpx/GpxConstants.java
index 543cdfebce..bfaff9f7e2 100644
--- a/src/org/openstreetmap/josm/data/gpx/GpxConstants.java
+++ b/src/org/openstreetmap/josm/data/gpx/GpxConstants.java
@@ -145,6 +145,11 @@ public interface GpxConstants {
      *  Fractional seconds are allowed for millisecond timing in tracklogs. */
     String PT_TIME = "time";
 
+    /** True Course/Bearing angle over ground.
+     * @since xxx
+     */
+    String PT_COURSE = "course";
+
     /** Magnetic variation (in degrees) at the point. 0.0 &lt;= value &lt; 360.0 */
     String PT_MAGVAR = "magvar";
 
@@ -188,8 +193,8 @@ public interface GpxConstants {
      * Ordered list of all possible waypoint keys.
      */
     List<String> WPT_KEYS = Collections.unmodifiableList(Arrays.asList(PT_ELE, PT_TIME, PT_MAGVAR, PT_GEOIDHEIGHT,
-            GPX_NAME, GPX_CMT, GPX_DESC, GPX_SRC, META_LINKS, PT_SYM, PT_TYPE,
-            PT_FIX, PT_SAT, PT_HDOP, PT_VDOP, PT_PDOP, PT_AGEOFDGPSDATA, PT_DGPSID, PT_STD_HDEV, PT_STD_VDEV));
+            GPX_NAME, GPX_CMT, GPX_DESC, GPX_SRC, META_LINKS, PT_SYM, PT_TYPE, PT_FIX, PT_SAT, PT_COURSE,
+            PT_HDOP, PT_VDOP, PT_PDOP, PT_AGEOFDGPSDATA, PT_DGPSID, PT_STD_HDEV, PT_STD_VDEV));
 
     /**
      * Ordered list of all possible route and track keys.
diff --git a/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java b/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java
index 023c495be3..be3f29beaf 100644
--- a/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java
+++ b/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelation.java
@@ -1,6 +1,7 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.data.gpx;
 
+import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -72,6 +73,7 @@ public final class GpxImageCorrelation {
         }
 
         final GpxImageDirectionPositionSettings dirpos = settings.getDirectionPositionSettings();
+        final GpxImageExtendedSettings extSettings = settings.getExtendedSettings();
         final long offset = settings.getOffset();
 
         boolean isFirst = true;
@@ -141,14 +143,14 @@ public final class GpxImageCorrelation {
                         }
                     }
                     WayPoint nextWp = i < size - 1 ? wps.get(i + 1) : null;
-                    ret += matchPoints(images, prevWp, prevWpTime, curWp, curWpTime, offset, interpolate, tagTime, nextWp, dirpos);
+                    ret += matchPoints(images, prevWp, prevWpTime, curWp, curWpTime, offset, interpolate, tagTime, nextWp, dirpos, extSettings);
                     prevWp = curWp;
                     prevWpTime = curWpTime;
                 }
             }
         }
         if (trkTag && prevWp != null) {
-            ret += matchPoints(images, prevWp, prevWpTime, prevWp, prevWpTime, offset, false, trkTagTime, null, dirpos);
+            ret += matchPoints(images, prevWp, prevWpTime, prevWp, prevWpTime, offset, false, trkTagTime, null, dirpos, extSettings);
         }
         Logging.debug("Correlated {0} total points", ret);
         return ret;
@@ -209,8 +211,110 @@ public final class GpxImageCorrelation {
         return null;
     }
 
-    private static int matchPoints(List<? extends GpxImageEntry> images, WayPoint prevWp, long prevWpTime, WayPoint curWp, long curWpTime,
-            long offset, boolean interpolate, int tagTime, WayPoint nextWp, GpxImageDirectionPositionSettings dirpos) {
+    static Double getHPosErr(WayPoint wp) {
+        if (wp != null) {
+            if (wp.attr.get(GpxConstants.PT_STD_HDEV) instanceof Float) {
+                Float hposerr = (Float) wp.attr.get(GpxConstants.PT_STD_HDEV);
+                if (hposerr != null) {
+                    return hposerr.doubleValue();
+                }
+            } else if (wp.attr.get(GpxConstants.PT_STD_HDEV) instanceof Double) {               
+                Double hposerr = (Double) wp.attr.get(GpxConstants.PT_STD_HDEV);
+                if (hposerr != null) {
+                    return hposerr;
+                }
+            }
+        }
+        return null;
+    }
+
+    static Double getGpsDop(WayPoint wp) {
+        if (wp != null) {
+            if (wp.attr.get(GpxConstants.PT_PDOP) != null) {
+                if (wp.attr.get(GpxConstants.PT_PDOP) instanceof Float) {
+                    Float pdopvalue = (Float) wp.attr.get(GpxConstants.PT_PDOP);
+                    return pdopvalue.doubleValue();
+                } else if (wp.attr.get(GpxConstants.PT_PDOP) instanceof Double) {
+                    Double pdopvalue = (Double) wp.attr.get(GpxConstants.PT_PDOP);
+                    return pdopvalue.doubleValue();
+                }
+            } else if (wp.attr.get(GpxConstants.PT_HDOP) != null) {
+                if (wp.attr.get(GpxConstants.PT_HDOP) instanceof Float) {
+                    Float hdopvalue = (Float) wp.attr.get(GpxConstants.PT_HDOP);
+                    return hdopvalue.doubleValue();
+                } else if (wp.attr.get(GpxConstants.PT_HDOP) instanceof Double) {
+                    Double hdopvalue = (Double) wp.attr.get(GpxConstants.PT_HDOP);
+                    return hdopvalue.doubleValue();
+                }
+            }
+        }
+        return null;
+    }
+
+    static Double getGpsTrack(WayPoint wp) {
+        if (wp != null) {
+            String trackvalue = wp.getString(GpxConstants.PT_COURSE);
+            Logging.debug("track angle value: {0}", trackvalue);
+            if (!Utils.isEmpty(trackvalue)) {
+                try {
+                    return Double.valueOf(trackvalue);
+                } catch (NumberFormatException e) {
+                    Logging.warn(e);
+                }
+            }
+        }
+        return null;
+    }
+
+    static String getGpsProcMethod(String prevGpsFixMode, final String curGpsFixMode,
+                                    final List<String> positioningModes) {
+        String gpsProcMethod = null;
+        Integer lowestProcIndex = null;
+        int lowestGnssModeIdx = 3; // 2d or higher index in positioningModes list are Gnss methods
+        try {
+            lowestProcIndex = Math.min(positioningModes.indexOf(prevGpsFixMode), positioningModes.indexOf(curGpsFixMode));
+            if (lowestProcIndex < 0) {
+                return null;
+            }
+            gpsProcMethod = "GNSS" + " " + positioningModes.get(lowestProcIndex).toUpperCase() + " " + "CORRELATION";
+            if (lowestProcIndex < lowestGnssModeIdx) {
+                gpsProcMethod = positioningModes.get(lowestProcIndex).toUpperCase() + " " + "CORRELATION";
+            } else {
+                gpsProcMethod = "GNSS" + " " + positioningModes.get(lowestProcIndex).toUpperCase() + " " + "CORRELATION";
+            }
+            gpsProcMethod = gpsProcMethod.replace("FLOAT RTK", "RTK_FLOAT");
+            gpsProcMethod = gpsProcMethod.replace(" RTK ", " RTK_FIX ");
+        } catch (ArrayIndexOutOfBoundsException ex) {
+            Logging.warn(ex);
+        }
+        return gpsProcMethod;
+    }
+
+    static Integer getGps2d3dMode(String prevGpsFixMode, final String curGpsFixMode,
+                                final List<String> positioningModes) {
+        Integer lowestMode = null;
+        lowestMode = Math.min(positioningModes.indexOf(prevGpsFixMode), positioningModes.indexOf(curGpsFixMode));
+        if (lowestMode > 3) {
+            return 3;
+        }
+        if (lowestMode > 2) {
+            return 2;
+        }
+        return null;
+    }
+
+    private static int matchPoints(List<? extends GpxImageEntry>
+                                        images,
+                                        WayPoint prevWp,
+                                        long prevWpTime,
+                                        WayPoint curWp,
+                                        long curWpTime,
+                                        long offset,
+                                        boolean interpolate,
+                                        int tagTime,
+                                        WayPoint nextWp,
+                                        GpxImageDirectionPositionSettings dirpos,
+                                        GpxImageExtendedSettings extSetting) {
 
         final boolean isLast = nextWp == null;
 
@@ -236,6 +340,15 @@ public final class GpxImageCorrelation {
         int ret = 0;
         Double speed = null;
         Double prevElevation = null;
+        Double prevHPosErr = null;
+        Double prevGpsDop = null;
+        Double prevGpsTrack = null;
+        String prevGpsFixMode = null;
+        //list of differential GPS mode
+        //TODO move these lists in Gpx.Constants?
+        final List<String> diffMode = Arrays.asList("dgps", "float rtk", "rtk");
+        final List<String> positioningModes = Arrays.asList("none", "manual", "estimated", "2d", "3d", "dgps", "float rtk", "rtk");
+
 
         if (prevWp != null && interpolate) {
             double distance = prevWp.greatCircleDistance(curWp);
@@ -244,9 +357,17 @@ public final class GpxImageCorrelation {
                 speed = 3600 * distance / (curWpTime - prevWpTime);
             }
             prevElevation = getElevation(prevWp);
+            prevHPosErr = getHPosErr(prevWp);
+            prevGpsDop = getGpsDop(prevWp);
+            prevGpsTrack = getGpsTrack(prevWp);
+            prevGpsFixMode = prevWp.getString(GpxConstants.PT_FIX);
         }
 
         final Double curElevation = getElevation(curWp);
+        final Double curHPosErr = getHPosErr(curWp);
+        final Double curGpsDop = getGpsDop(curWp);
+        final Double curGpsTrack = getGpsTrack(curWp);
+        final String curGpsFixMode = curWp.getString(GpxConstants.PT_FIX);
 
         if (!interpolate || isLast) {
             final long half = Math.abs(curWpTime - prevWpTime) / 2;
@@ -266,6 +387,7 @@ public final class GpxImageCorrelation {
                     } else {
                         curTmp.setPos(curWp.getCoor());
                     }
+                    //TODO fix this, nextWp doesn't exist here
                     if (nextWp != null && dirpos.isSetImageDirection()) {
                         double direction = curWp.bearing(nextWp);
                         curTmp.setExifImgDir(computeDirection(direction, dirpos.getImageDirectionAngleOffset()));
@@ -317,6 +439,62 @@ public final class GpxImageCorrelation {
                     if (curElevation != null && prevElevation != null) {
                         curTmp.setElevation(prevElevation + (curElevation - prevElevation) * timeDiff + dirpos.getElevationShift());
                     }
+
+                    // Add exif GpsHPositioningerror interpolated value
+                    if (curHPosErr != null && prevHPosErr != null) {
+                        Double interpolatedValue = prevHPosErr + (curHPosErr - prevHPosErr) * timeDiff;
+                        curTmp.setExifHPosErr(Math.round(interpolatedValue*10000)/10000.0);
+                    }
+
+                    // Add exif GpsDifferentialMode
+                    // Get previous and current waypoint differential. As no interpolation is possible,
+                    // set differential mode to 0 if any waypoint isn't in differential mode.
+                    if (prevGpsFixMode != null) {
+                        if (diffMode.contains(prevGpsFixMode) && diffMode.contains(curGpsFixMode)) {
+                            curTmp.setGpsDiffMode(1);
+                        } else {
+                            curTmp.setGpsDiffMode(0);
+                        }
+                    }
+
+                    // Add exif GpsMeasureMode
+                    if (prevGpsFixMode != null && curGpsFixMode != null) {
+                        Integer gps2d3dMode = getGps2d3dMode(prevGpsFixMode, curGpsFixMode, positioningModes);
+                        if (gps2d3dMode != null) {
+                            curTmp.setGps2d3dMode(gps2d3dMode);
+                        }
+                    }
+                    
+                    // Add exif GpsProcessingMethod. As no interpolation is possible,
+                    // set processing method to the "lowest" previous and current processing method value.
+                    if (prevGpsFixMode != null && curGpsFixMode != null) {
+                        String gpsProcMethod = getGpsProcMethod(prevGpsFixMode, curGpsFixMode, positioningModes);                       
+                        if (gpsProcMethod != null) {
+                            curTmp.setExifGpsProcMethod(gpsProcMethod);
+                        }
+                    }
+
+                    // Add Exif GpsDop with interpolated GPS DOP value
+                    if (curGpsDop != null && prevGpsDop != null) {
+                        Double interpolatedValue = prevGpsDop + (curGpsDop - prevGpsDop) * timeDiff;
+                        curTmp.setExifGpsDop(Math.round(interpolatedValue*100)/100.0);
+                    }
+
+                    // Add Exif GpsTrack tag
+                    if (dirpos.isSetGpxTrackDirection()) {
+                        if (curGpsTrack != null && prevGpsTrack != null) {
+                            curTmp.setExifGpsTrack(prevGpsTrack + (curGpsTrack - prevGpsTrack) * timeDiff);
+                        }
+                    }
+                    
+                    // Add GpsDatum tag
+                    if (extSetting.isSetImageGpsDatum()) {
+                        if (diffMode.contains(prevGpsFixMode) && diffMode.contains(curGpsFixMode)) {
+                            curTmp.setExifGpsDatum(extSetting.getImageGpsDatum());
+                        } else //without differential mode, datum is WGS-84
+                            curTmp.setExifGpsDatum("WGS-84");
+                    }
+
                     curTmp.setGpsTime(curImg.getExifInstant().minusMillis(offset));
                     curTmp.flagNewGpsData();
                     curImg.tmpUpdated();
diff --git a/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelationSettings.java b/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelationSettings.java
index 079d69f99c..aa08ec4f7e 100644
--- a/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelationSettings.java
+++ b/src/org/openstreetmap/josm/data/gpx/GpxImageCorrelationSettings.java
@@ -12,6 +12,7 @@ public class GpxImageCorrelationSettings {
     private final long offset;
     private final boolean forceTags;
     private final GpxImageDirectionPositionSettings directionPositionSettings;
+    private final GpxImageExtendedSettings extendedSettings;
 
     /**
      * Constructs a new {@code GpxImageCorrelationSettings}.
@@ -19,7 +20,10 @@ public class GpxImageCorrelationSettings {
      * @param forceTags force tagging of all photos, otherwise prefs are used
      */
     public GpxImageCorrelationSettings(long offset, boolean forceTags) {
-        this(offset, forceTags, new GpxImageDirectionPositionSettings(false, 0, 0, 0, 0));
+        this(offset, forceTags,
+        new GpxImageDirectionPositionSettings(false, 0, false, 0, 0, 0),
+        new GpxImageExtendedSettings(false, null)
+        );
     }
 
     /**
@@ -30,11 +34,27 @@ public class GpxImageCorrelationSettings {
      */
     public GpxImageCorrelationSettings(long offset, boolean forceTags,
             GpxImageDirectionPositionSettings directionPositionSettings) {
+        this(offset, forceTags, directionPositionSettings,
+        new GpxImageExtendedSettings(false, null));
+    }
+
+    /**
+     * Constructs a new {@code GpxImageCorrelationSettings}.
+     * @param offset offset in milliseconds
+     * @param forceTags force tagging of all photos, otherwise prefs are used
+     * @param directionPositionSettings direction/position settings
+     * @param extendedSettings GPS datum settings
+     * @since xxx @extendedSettings was added
+     */
+    public GpxImageCorrelationSettings(long offset, boolean forceTags,
+            GpxImageDirectionPositionSettings directionPositionSettings,
+            GpxImageExtendedSettings extendedSettings) {
         this.offset = offset;
         this.forceTags = forceTags;
         this.directionPositionSettings = Objects.requireNonNull(directionPositionSettings);
+        this.extendedSettings = Objects.requireNonNull(extendedSettings);
     }
-
+    
     /**
      * Returns the offset in milliseconds.
      * @return the offset in milliseconds
@@ -59,9 +79,19 @@ public class GpxImageCorrelationSettings {
         return directionPositionSettings;
     }
 
+    /**
+     * Returns the extended exif metadata settings.
+     * @return the extended exif metadata settings
+     * @since xxx
+     */
+    public GpxImageExtendedSettings getExtendedSettings() {
+        return extendedSettings;
+    }
+
     @Override
     public String toString() {
         return "[offset=" + offset + ", forceTags=" + forceTags
-                + ", directionPositionSettings=" + directionPositionSettings + ']';
+                + ", directionPositionSettings=" + directionPositionSettings
+                + ", extendedSettings=" + extendedSettings + ']';
     }
 }
diff --git a/src/org/openstreetmap/josm/data/gpx/GpxImageDirectionPositionSettings.java b/src/org/openstreetmap/josm/data/gpx/GpxImageDirectionPositionSettings.java
index 20dd5e0f73..53483c2e4f 100644
--- a/src/org/openstreetmap/josm/data/gpx/GpxImageDirectionPositionSettings.java
+++ b/src/org/openstreetmap/josm/data/gpx/GpxImageDirectionPositionSettings.java
@@ -9,6 +9,7 @@ public class GpxImageDirectionPositionSettings {
 
     private final boolean setImageDirection;
     private final double imageDirectionAngleOffset;
+    private final boolean setGpxTrackDirection;
     private final double shiftImageX;
     private final double shiftImageY;
     private final double elevationShift;
@@ -17,14 +18,18 @@ public class GpxImageDirectionPositionSettings {
      * Constructs a new {@code GpxImageDirectionPositionSettings}.
      * @param setImageDirection determines if image direction must be set towards the next GPX waypoint
      * @param imageDirectionAngleOffset direction angle offset in degrees
+     * @param setGpxTrackDirection determines if image course direction must be set
      * @param shiftImageX image shift on X axis relative to the direction in meters
      * @param shiftImageY image shift on Y axis relative to the direction in meters
      * @param elevationShift image elevation shift in meters
+     * @since xxx @setGpsTrackDirection was added
      */
     public GpxImageDirectionPositionSettings(
-            boolean setImageDirection, double imageDirectionAngleOffset, double shiftImageX, double shiftImageY, double elevationShift) {
+            boolean setImageDirection, double imageDirectionAngleOffset, boolean setGpxTrackDirection, 
+            double shiftImageX, double shiftImageY, double elevationShift) {
         this.setImageDirection = setImageDirection;
         this.imageDirectionAngleOffset = imageDirectionAngleOffset;
+        this.setGpxTrackDirection = setGpxTrackDirection;
         this.shiftImageX = shiftImageX;
         this.shiftImageY = shiftImageY;
         this.elevationShift = elevationShift;
@@ -46,6 +51,15 @@ public class GpxImageDirectionPositionSettings {
         return imageDirectionAngleOffset;
     }
 
+    /**
+     * Determines if GPS course direction must be set. Angle value is from the gpx trace.
+     * @return {@code true} if image GPS course must be set
+     * @since xxx
+     */
+    public boolean isSetGpxTrackDirection() {
+        return setGpxTrackDirection;
+    }
+
     /**
      * Returns image shift on X axis relative to the direction in meters
      * @return image shift on X axis relative to the direction in meters
@@ -73,7 +87,10 @@ public class GpxImageDirectionPositionSettings {
     @Override
     public String toString() {
         return "[setImageDirection=" + setImageDirection
-                + ", imageDirectionAngleOffset=" + imageDirectionAngleOffset + ", shiftImageX=" + shiftImageX
-                + ", shiftImageY=" + shiftImageY + ", elevationShift=" + elevationShift + ']';
+                + ", imageDirectionAngleOffset=" + imageDirectionAngleOffset
+                + ", setImageGpxTrackDirection=" + setGpxTrackDirection
+                + ", shiftImageX=" + shiftImageX
+                + ", shiftImageY=" + shiftImageY
+                + ", elevationShift=" + elevationShift + ']';
     }
 }
diff --git a/src/org/openstreetmap/josm/data/gpx/GpxImageEntry.java b/src/org/openstreetmap/josm/data/gpx/GpxImageEntry.java
index f4161cd78f..4886980cdd 100644
--- a/src/org/openstreetmap/josm/data/gpx/GpxImageEntry.java
+++ b/src/org/openstreetmap/josm/data/gpx/GpxImageEntry.java
@@ -32,6 +32,9 @@ public class GpxImageEntry implements Comparable<GpxImageEntry>, IQuadBucketType
     private Integer exifOrientation;
     private LatLon exifCoor;
     private Double exifImgDir;
+    private Double exifGpsTrack;
+    private Double exifHPosErr;
+    private Double exifGpsDop;
     private Instant exifTime;
     private Projections cameraProjection = Projections.UNKNOWN;
     /**
@@ -57,6 +60,14 @@ public class GpxImageEntry implements Comparable<GpxImageEntry>, IQuadBucketType
     private Double speed;
     /** Elevation (altitude) in meters */
     private Double elevation;
+    /** GPS Differential mode */
+    private Integer gpsDiffMode;
+    /** GPS Measure mode */
+    private Integer gps2d3dMode;
+    /** GPS Datum */
+    private String exifGpsDatum;
+    /** GPS processing method */
+    private String exifGpsProcMethod;
     /** The time after correlation with a gpx track */
     private Instant gpsTime;
 
@@ -88,6 +99,13 @@ public class GpxImageEntry implements Comparable<GpxImageEntry>, IQuadBucketType
         exifOrientation = other.exifOrientation;
         exifCoor = other.exifCoor;
         exifImgDir = other.exifImgDir;
+        exifGpsTrack = other.exifGpsTrack;
+        exifHPosErr = other.exifHPosErr;
+        gpsDiffMode = other.gpsDiffMode;
+        gps2d3dMode = other.gps2d3dMode;
+        exifGpsDop = other.exifGpsDop;
+        exifGpsDatum = other.exifGpsDatum;
+        exifGpsProcMethod = other.exifGpsProcMethod;
         exifTime = other.exifTime;
         isNewGpsData = other.isNewGpsData;
         exifGpsTime = other.exifGpsTime;
@@ -169,6 +187,69 @@ public class GpxImageEntry implements Comparable<GpxImageEntry>, IQuadBucketType
         return elevation;
     }
 
+    /**
+     * Return the GPS Differential mode value. The GPS Differential mode value from the temporary
+     * copy is returned if that copy exists. 
+     * @return the differential mode value
+     * @since xxx
+     */
+    @Override
+    public Integer getGpsDiffMode() {
+        if (tmp != null)
+            return tmp.gpsDiffMode;
+        return gpsDiffMode;
+    }
+
+    /**
+     * Return the GPS 2d or 3d mode value. The GPS mode value form the temporary
+     * copy is returned if that copy exists. 
+     * @return the GPS 2d/3d mode value
+     * @since xxx
+     */
+    @Override
+    public Integer getGps2d3dMode() {
+        if (tmp != null)
+            return tmp.gps2d3dMode;
+        return gps2d3dMode;
+    }
+
+    /**
+     * Return the GPS DOP value. The GPS DOP value from the temporary
+     * copy is returned if that copy exists. 
+     * @return the DOP value
+     * @since xxx
+     */
+    @Override
+    public Double getExifGpsDop() {
+        if (tmp != null)
+            return tmp.exifGpsDop;
+        return exifGpsDop;
+    }
+
+    /**
+     * Return the exif GPS coordinates datum value.
+     * @return The datum value
+     * @since xxx
+     */
+    @Override
+    public String getExifGpsDatum() {
+        if (tmp != null)
+            return tmp.exifGpsDatum;
+        return exifGpsDatum;
+    }
+
+    /**
+     * Return the exif GPS processing method string
+     * @return the processing method string
+     * @since xxx
+     */
+    @Override
+    public String getExifGpsProcMethod() {
+        if (tmp != null)
+            return tmp.exifGpsProcMethod;
+        return exifGpsProcMethod;
+    }
+
     /**
      * Returns the GPS time value. The GPS time value from the temporary copy
      * is returned if that copy exists.
@@ -272,6 +353,32 @@ public class GpxImageEntry implements Comparable<GpxImageEntry>, IQuadBucketType
             return tmp.exifImgDir;
         return exifImgDir;
     }
+    
+    /**
+     * Convenient way to determine if this entry has a EXIF GPS track angle value,
+     * without the cost of building a defensive copy.
+     * @return {@code true} if this entry has a EXIF track angle value
+     * @since xxx
+     */
+    @Override
+    public Double getExifGpsTrack() {
+        if (tmp != null)
+            return tmp.exifGpsTrack;
+        return exifGpsTrack;
+    }
+
+    /**
+     * Convenient way to determine if this entry has a EXIF GPS horizontal positionning error value,
+     * without the cost of building a defensive copy.
+     * @return {@code true} if this entry has a EXIF GPS horizontal positionning error value
+     * @since xxx
+     */
+    @Override
+    public Double getExifHPosErr() {
+        if (tmp != null)
+            return tmp.exifHPosErr;
+        return exifHPosErr;
+    }
 
     @Override
     public Instant getLastModified() {
@@ -345,6 +452,56 @@ public class GpxImageEntry implements Comparable<GpxImageEntry>, IQuadBucketType
         this.elevation = elevation;
     }
 
+    /**
+     * Sets GPS Differential mode.
+     * @param gpsDiffMode GPS Differential mode
+     * @since xxx
+     */
+    @Override
+    public void setGpsDiffMode(Integer gpsDiffMode) {
+        this.gpsDiffMode = gpsDiffMode;
+    }
+
+    /**
+     * Sets GPS 2d/3d mode.
+     * @param gps2d3dMode GPS 2d/3d mode value
+     * @since xxx
+     */
+    @Override
+    public void setGps2d3dMode(Integer gps2d3dMode) {
+        this.gps2d3dMode = gps2d3dMode;
+    }
+
+    /**
+     * Sets GPS DOP value.
+     * @param exifGpsDop GPS DOP value
+     * @since xxx
+     */
+    @Override
+    public void setExifGpsDop(Double exifGpsDop) {
+        this.exifGpsDop = exifGpsDop;
+    }
+
+    /**
+     * Sets the GPS Datum.
+     * @param exifGpsDatum GPS Datum
+     * @since xxx
+     */
+    @Override
+    public void setExifGpsDatum(String exifGpsDatum) {
+        this.exifGpsDatum = exifGpsDatum;
+    }
+
+    /**
+     * Sets the GPS Processing Method.
+     * @param exifGpsProcMethod GPS Processing Method
+     * @since xxx
+     */
+    @Override
+    public void setExifGpsProcMethod(String exifGpsProcMethod) {
+        this.exifGpsProcMethod = exifGpsProcMethod;
+    }
+
     /**
      * Sets associated file.
      * @param file associated file
@@ -412,6 +569,26 @@ public class GpxImageEntry implements Comparable<GpxImageEntry>, IQuadBucketType
         this.exifImgDir = exifDir;
     }
 
+    /**
+     * Sets the exif GPS track (move direction angle)
+     * @param exifGpsTrack the exif GPS track angle
+     * @since xxx
+     */
+    @Override
+    public void setExifGpsTrack(Double exifGpsTrack) {
+        this.exifGpsTrack = exifGpsTrack;
+    }
+
+    /**
+     * Sets the exif horizontal positioning error
+     * @param exifHposErr the Exif horizontal positionning error
+     * @since xxx
+     */
+    @Override
+    public void setExifHPosErr(Double exifHPosErr) {
+        this.exifHPosErr = exifHPosErr;
+    }
+
     /**
      * Sets the IPTC caption.
      * @param iptcCaption the IPTC caption
@@ -507,9 +684,10 @@ public class GpxImageEntry implements Comparable<GpxImageEntry>, IQuadBucketType
     @Override
     public int hashCode() {
         return Objects.hash(height, width, isNewGpsData,
-            elevation, exifCoor, exifGpsTime, exifImgDir, exifOrientation, exifTime,
-            iptcCaption, iptcHeadline, iptcKeywords, iptcObjectName,
-            file, gpsTime, pos, speed, tmp, cameraProjection);
+            elevation, exifCoor, exifGpsTime, exifImgDir, exifGpsTrack, exifHPosErr,
+            exifGpsDop, gpsDiffMode, gps2d3dMode, exifGpsDatum, exifGpsProcMethod,
+            exifOrientation, exifTime, iptcCaption, iptcHeadline, iptcKeywords,
+            iptcObjectName, file, gpsTime, pos, speed, tmp, cameraProjection);
     }
 
     @Override
@@ -526,6 +704,13 @@ public class GpxImageEntry implements Comparable<GpxImageEntry>, IQuadBucketType
             && Objects.equals(exifCoor, other.exifCoor)
             && Objects.equals(exifGpsTime, other.exifGpsTime)
             && Objects.equals(exifImgDir, other.exifImgDir)
+            && Objects.equals(exifGpsTrack, other.exifGpsTrack)
+            && Objects.equals(exifHPosErr, other.exifHPosErr)
+            && Objects.equals(gpsDiffMode, other.gpsDiffMode)
+            && Objects.equals(gps2d3dMode, other.gps2d3dMode)
+            && Objects.equals(exifGpsDop, other.exifGpsDop)
+            && Objects.equals(exifGpsDatum, other.exifGpsDatum)
+            && Objects.equals(exifGpsProcMethod, other.exifGpsProcMethod)
             && Objects.equals(exifOrientation, other.exifOrientation)
             && Objects.equals(exifTime, other.exifTime)
             && Objects.equals(iptcCaption, other.iptcCaption)
@@ -570,6 +755,7 @@ public class GpxImageEntry implements Comparable<GpxImageEntry>, IQuadBucketType
      * Copy the values from the temporary variable to the main instance. The
      * temporary variable is deleted.
      * @see #discardTmp()
+     * @since xxx exifGpsTrack, exifHPosErr, gpsDiffMode, gps2d3dMode, exifGpsDop, exifGpsDatum, exifGpsProcMethod added
      */
     public void applyTmp() {
         if (tmp != null) {
@@ -578,6 +764,13 @@ public class GpxImageEntry implements Comparable<GpxImageEntry>, IQuadBucketType
             elevation = tmp.elevation;
             gpsTime = tmp.gpsTime;
             exifImgDir = tmp.exifImgDir;
+            exifGpsTrack = tmp.exifGpsTrack;
+            exifHPosErr = tmp.exifHPosErr;
+            gpsDiffMode = tmp.gpsDiffMode;
+            gps2d3dMode = tmp.gps2d3dMode;
+            exifGpsDop = tmp.exifGpsDop;
+            exifGpsDatum = tmp.exifGpsDatum;
+            exifGpsProcMethod = tmp.exifGpsProcMethod;
             isNewGpsData = isNewGpsData || tmp.isNewGpsData;
             tmp = null;
         }
diff --git a/src/org/openstreetmap/josm/data/gpx/GpxImageExtendedSettings.java b/src/org/openstreetmap/josm/data/gpx/GpxImageExtendedSettings.java
new file mode 100644
index 0000000000..b7e88ec695
--- /dev/null
+++ b/src/org/openstreetmap/josm/data/gpx/GpxImageExtendedSettings.java
@@ -0,0 +1,39 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.gpx;
+
+/**
+ * Image extended exif metadata settings used by {@link GpxImageCorrelationSettings}.
+ * @since xxx
+ */
+public class GpxImageExtendedSettings {
+
+    private final boolean setImageGpsDatum;
+    private final String imageGpsDatum;
+    
+    /**
+     * Construcs a new {@code GpxImageExtendedSettings}.
+     * @param setImageGpsDatum determines if images GPS datum must be set
+     * @param imageGpsDatum determines the GPS coordinates datum value to be set
+     */
+    public GpxImageExtendedSettings(
+        boolean setImageGpsDatum, String imageGpsDatum) {
+            this.setImageGpsDatum = setImageGpsDatum;
+            this.imageGpsDatum = imageGpsDatum;
+        }
+    
+    /**
+     * Determines if image GPS datum must be set
+     * @return if the GPS datum must be set
+     */
+    public boolean isSetImageGpsDatum() {
+        return setImageGpsDatum;
+    }
+    
+    /**
+     * Return the GPS coordinates datum code.
+     * @return the datum code
+     */
+    public String getImageGpsDatum() {
+        return imageGpsDatum;
+    }
+}
diff --git a/src/org/openstreetmap/josm/data/imagery/street_level/IImageEntry.java b/src/org/openstreetmap/josm/data/imagery/street_level/IImageEntry.java
index 3dcd79705d..04a9504e95 100644
--- a/src/org/openstreetmap/josm/data/imagery/street_level/IImageEntry.java
+++ b/src/org/openstreetmap/josm/data/imagery/street_level/IImageEntry.java
@@ -218,13 +218,69 @@ public interface IImageEntry<I extends IImageEntry<I>> {
      */
     Double getElevation();
 
+    /**
+     * Return the GPS Differential mode value. The differential mode value from the temporary
+     * copy is returned if that copy exists. 
+     * @return the fix mode value
+     * @since xxx
+     */
+    Integer getGpsDiffMode();
+
+    /**
+     * Return the GPS 2d/3d mode value. The 2d/3d mode value from the temporary
+     * copy is returned if that copy exists.
+     * @return the 2d/3d mode value
+     * @since xxx
+     */
+    Integer getGps2d3dMode();
+
+    /**
+     * Return the GPS DOP value. The GPS DOP value from the temporary
+     * copy is return if that copy exists.
+     * @return the GPS DOP value
+     * @since xxx
+     */
+    Double getExifGpsDop();
+
+    /**
+     * Return the GPS datum value. The GPS datum value from the temporary
+     * copy is return if that copy exists. 
+     * @return the GPS datum value
+     * @since xxx
+     */
+    String getExifGpsDatum();
+
+    /**
+     * Return the GPS processing method. The processing method value from the temporary
+     * copy is return if that copy exists.
+     * @return the GPS processing method
+     * @since xxx
+     */
+    String getExifGpsProcMethod();
+
     /**
      * Returns the image direction. The image direction from the temporary
      * copy is returned if that copy exists.
      * @return The image camera angle
      */
     Double getExifImgDir();
+    
+    /**
+     * Returns the image GPS track direction. The GPS track direction from the temporary
+     * copy is returned if that copy exists.
+     * @return the image GPS track direction angle
+     * @since xxx
+     */
+    Double getExifGpsTrack();
 
+    /**
+     * Returns the image horizontal positionning error. The image positionning error
+     * from the temporary copy is returned if that copy exists.
+     * @return the image horizontal positionning error
+     * @since xxx
+     */
+    Double getExifHPosErr();
+    
     /**
      * Convenient way to determine if this entry has a EXIF time, without the cost of building a defensive copy.
      * @return {@code true} if this entry has a EXIF time
@@ -251,6 +307,14 @@ public interface IImageEntry<I extends IImageEntry<I>> {
      */
     Instant getGpsInstant();
 
+    /**
+     * Returns the Exif GPS Time value. The Exif GPS time value from the temporary copy
+     * is returned if that copy exists.
+     * @return the Exif GPS time value
+     * @since xxx
+     */
+    Instant getExifGpsInstant();
+
     /**
      * Returns the IPTC caption.
      * @return the IPTC caption
diff --git a/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java b/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
index 92d16c1ed1..faaaf50268 100644
--- a/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
+++ b/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
@@ -978,12 +978,17 @@ public class OsmDataLayer extends AbstractOsmDataLayer
         addStringIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_SYM, "wpt_symbol", null);
         addStringIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_TYPE, null, null);
 
+        // Angle info
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_COURSE, "gps:course");
+
         // Accuracy info
         addStringIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_FIX, "gps:fix", null);
         addIntegerIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_SAT, "gps:sat");
         addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_HDOP, "gps:hdop");
         addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_VDOP, "gps:vdop");
         addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_PDOP, "gps:pdop");
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_STD_HDEV, "gps:stdhdev");
+        addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_STD_VDEV, "gps:stdvdev");
         addDoubleIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_AGEOFDGPSDATA, "gps:ageofdgpsdata");
         addIntegerIfPresent(wpt, n, gpxPrefix, GpxConstants.PT_DGPSID, "gps:dgpsid");
 
diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java b/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
index a47b4bb734..a3478fbea2 100644
--- a/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
+++ b/src/org/openstreetmap/josm/gui/layer/geoimage/CorrelateGpxWithImages.java
@@ -53,6 +53,7 @@ import org.openstreetmap.josm.data.gpx.GpxData.GpxDataChangeListener;
 import org.openstreetmap.josm.data.gpx.GpxDataContainer;
 import org.openstreetmap.josm.data.gpx.GpxImageCorrelation;
 import org.openstreetmap.josm.data.gpx.GpxImageCorrelationSettings;
+import org.openstreetmap.josm.data.gpx.GpxImageExtendedSettings;
 import org.openstreetmap.josm.data.gpx.GpxTimeOffset;
 import org.openstreetmap.josm.data.gpx.GpxTimezone;
 import org.openstreetmap.josm.data.gpx.WayPoint;
@@ -168,6 +169,7 @@ public class CorrelateGpxWithImages extends AbstractAction implements ExpertMode
                 Config.getPref().put("geoimage.timezone", timezone.formatTimezone());
                 Config.getPref().put("geoimage.delta", delta.formatOffset());
                 Config.getPref().putBoolean("geoimage.showThumbs", yLayer.useThumbs);
+                Config.getPref().put("geoimage.datum", tfDatum.getText());
 
                 yLayer.useThumbs = cbShowThumbs.isSelected();
                 yLayer.startLoadThumbs();
@@ -246,6 +248,7 @@ public class CorrelateGpxWithImages extends AbstractAction implements ExpertMode
 
     private ExtendedDialog syncDialog;
     private JPanel outerPanel;
+    private JPanel expertPanel;
     private JosmComboBox<GpxDataWrapper> cbGpx;
     private JButton buttonSupport;
     private JosmTextField tfTimezone;
@@ -253,9 +256,14 @@ public class CorrelateGpxWithImages extends AbstractAction implements ExpertMode
     private JCheckBox cbExifImg;
     private JCheckBox cbTaggedImg;
     private JCheckBox cbShowThumbs;
+    private JSeparator sepExtendedTags;
+    private JLabel labelExtTags;
+    private JLabel labelDatum;
     private JLabel statusBarText;
     private JSeparator sepDirectionPosition;
     private ImageDirectionPositionPanel pDirectionPosition;
+    private JCheckBox cbAddGpsDatum;
+    private JosmTextField tfDatum;
 
     // remember the last number of matched photos
     private int lastNumMatched;
@@ -472,6 +480,11 @@ public class CorrelateGpxWithImages extends AbstractAction implements ExpertMode
         }
     }
 
+    static String loadGpsDatum() {
+        String gpsDatum = Config.getPref().get("geoimage.datum", "WGS-84");
+        return gpsDatum;
+    }
+
     @Override
     public void actionPerformed(ActionEvent ae) {
         NoGpxDataWrapper nogdw = new NoGpxDataWrapper();
@@ -619,6 +632,7 @@ public class CorrelateGpxWithImages extends AbstractAction implements ExpertMode
         gbc.gridy = y++;
         panelTf.add(cbShowThumbs, gbc);
 
+        //Image direction and position offset GUI
         gbc = GBC.eol().fill(GridBagConstraints.HORIZONTAL).insets(0, 12, 0, 0);
         sepDirectionPosition = new JSeparator(SwingConstants.HORIZONTAL);
         gbc.gridy = y++;
@@ -630,6 +644,51 @@ public class CorrelateGpxWithImages extends AbstractAction implements ExpertMode
         pDirectionPosition = ImageDirectionPositionPanel.forGpxTrace();
         panelTf.add(pDirectionPosition, gbc);
 
+        //Extended tags GUI panel
+        expertPanel = new JPanel(new GridBagLayout());
+        gbc = GBC.eol().fill(GridBagConstraints.HORIZONTAL).insets(0, 12, 0, 0);
+        sepExtendedTags = new JSeparator(SwingConstants.HORIZONTAL);
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        expertPanel.add(sepExtendedTags, gbc);
+
+        labelExtTags = new JLabel(tr("Extended tags"));
+        cbAddGpsDatum = new JCheckBox(tr("Set datum for images coordinates"));
+        cbAddGpsDatum.addActionListener(e -> tfDatum.setEnabled(!tfDatum.isEnabled()));
+
+        labelDatum = new JLabel(tr("Datum: "));
+        //TODO An AutoCompComboBox would be nice to list the recent datum values. I don't have the skill to add it.
+        tfDatum = new JosmTextField(loadGpsDatum(), 8);
+        tfDatum.setToolTipText(tr("<html>Enter the datum for your images coordinates. Default value is WGS-84.<br>" + 
+                                "For RTK it could be your local CRS epsg code.<br>(e.g. EPSG:9782 for France mainland.)</html>"));
+        tfDatum.setEnabled(false);
+
+        gbc = GBC.eol();
+        gbc.gridx = 0;
+        gbc.gridy = 1;
+        expertPanel.add(labelExtTags, gbc);
+
+        gbc = GBC.eol();
+        gbc.gridx = 0;
+        gbc.gridy = 2;
+        expertPanel.add(cbAddGpsDatum, gbc);
+
+        //TODO move this line a little more to the right 
+        gbc = GBC.std();
+        gbc.gridx = 1;
+        gbc.gridy = 3;
+        expertPanel.add(labelDatum);
+
+        gbc = GBC.eol();
+        gbc.gridx = 2;
+        gbc.gridy = 3;
+        expertPanel.add(tfDatum, gbc);
+
+        //Add expertPanel to panelTf
+        gbc = GBC.eol().fill(GridBagConstraints.HORIZONTAL).insets(0, 12, 0, 0);
+        gbc.gridy = y++;
+        panelTf.add(expertPanel, gbc);
+        
         final JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
         statusPanel.setBorder(BorderFactory.createLoweredBevelBorder());
         statusBarText = new JLabel(" ");
@@ -651,6 +710,8 @@ public class CorrelateGpxWithImages extends AbstractAction implements ExpertMode
         tfOffset.getDocument().addDocumentListener(statusBarUpdater);
         cbExifImg.addItemListener(statusBarUpdaterWithRepaint);
         cbTaggedImg.addItemListener(statusBarUpdaterWithRepaint);
+        cbAddGpsDatum.addItemListener(statusBarUpdaterWithRepaint);
+        tfDatum.getDocument().addDocumentListener(statusBarUpdater);
         pDirectionPosition.addChangeListenerOnComponents(statusBarUpdaterWithRepaint);
         pDirectionPosition.addItemListenerOnComponents(statusBarUpdaterWithRepaint);
 
@@ -678,6 +739,12 @@ public class CorrelateGpxWithImages extends AbstractAction implements ExpertMode
         }
     }
 
+    public GpxImageExtendedSettings getSettings() {
+        return new GpxImageExtendedSettings(
+            cbAddGpsDatum.isSelected(),
+            tfDatum.getText());
+    }
+
     @Override
     public void expertChanged(boolean isExpert) {
         if (buttonSupport != null) {
@@ -689,6 +756,9 @@ public class CorrelateGpxWithImages extends AbstractAction implements ExpertMode
         if (pDirectionPosition != null) {
             pDirectionPosition.setVisible(isExpert);
         }
+        if (expertPanel != null) {
+            expertPanel.setVisible(isExpert);
+        }
         if (syncDialog != null) {
             syncDialog.pack();
         }
@@ -786,7 +856,8 @@ public class CorrelateGpxWithImages extends AbstractAction implements ExpertMode
             final long offsetMs = ((long) (timezone.getHours() * TimeUnit.HOURS.toMillis(1))) + delta.getMilliseconds(); // in milliseconds
             lastNumMatched = GpxImageCorrelation.matchGpxTrack(dateImgLst, selGpx.data,
                     pDirectionPosition.isVisible() ?
-                            new GpxImageCorrelationSettings(offsetMs, forceTags, pDirectionPosition.getSettings()) :
+                            new GpxImageCorrelationSettings(offsetMs, forceTags, pDirectionPosition.getSettings(),
+                                                            new GpxImageExtendedSettings(cbAddGpsDatum.isSelected(), tfDatum.getText())) :
                             new GpxImageCorrelationSettings(offsetMs, forceTags));
 
             return trn("<html>Matched <b>{0}</b> of <b>{1}</b> photo to GPX track.</html>",
diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDirectionPositionPanel.java b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDirectionPositionPanel.java
index 1d998b0795..9057240185 100644
--- a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDirectionPositionPanel.java
+++ b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageDirectionPositionPanel.java
@@ -28,6 +28,7 @@ public class ImageDirectionPositionPanel extends JPanel {
 
     private final JCheckBox cChangeImageDirection = new JCheckBox();
     private final JSpinner sOffsetDegrees = new JSpinner(new SpinnerNumberModel(0, -360, 360, 1));
+    private final JCheckBox cSetGpxTrackTag = new JCheckBox();
 
     private final JSpinner sX = new JSpinner(new SpinnerNumberModel(0.0, -50.0, 50.0, 0.1));
     private final JSpinner sY = new JSpinner(new SpinnerNumberModel(0.0, -50.0, 50.0, 0.1));
@@ -37,7 +38,7 @@ public class ImageDirectionPositionPanel extends JPanel {
      * Constructs a new {@code ImageMetadataModificationPanel}
      * @param changeDirectionText the text displayed for the change image direction combobox
      */
-    protected ImageDirectionPositionPanel(String changeDirectionText) {
+    protected ImageDirectionPositionPanel(String changeDirectionText, boolean hideGpxTrack) {
         super(new GridBagLayout());
 
         cChangeImageDirection.setText(changeDirectionText);
@@ -45,6 +46,12 @@ public class ImageDirectionPositionPanel extends JPanel {
         cChangeImageDirection.addActionListener(e -> sOffsetDegrees.setEnabled(!sOffsetDegrees.isEnabled()));
         addSetting(tr("Offset angle in degrees:"), sOffsetDegrees);
         sOffsetDegrees.setEnabled(false);
+        if (!hideGpxTrack) {
+            cChangeImageDirection.addActionListener(e -> cSetGpxTrackTag.setEnabled(!cSetGpxTrackTag.isEnabled()));
+            cSetGpxTrackTag.setText(tr("Set image course direction (from gpx track)"));
+            add(cSetGpxTrackTag, GBC.eol().insets(0, 0, 0, 5));
+            cSetGpxTrackTag.setEnabled(false);
+        }
 
         add(new JSeparator(SwingConstants.HORIZONTAL),
                 GBC.eol().fill(GBC.HORIZONTAL).insets(0, 12, 0, 12));
@@ -61,7 +68,7 @@ public class ImageDirectionPositionPanel extends JPanel {
      * @return a new {@code ImageMetadataModificationPanel} in a GPX trace context
      */
     public static ImageDirectionPositionPanel forGpxTrace() {
-        return new ImageDirectionPositionPanel(tr("Set image direction towards the next GPX waypoint"));
+        return new ImageDirectionPositionPanel(tr("Set image direction towards the next GPX waypoint"), false);
     }
 
     /**
@@ -69,7 +76,7 @@ public class ImageDirectionPositionPanel extends JPanel {
      * @return a new {@code ImageMetadataModificationPanel} in an image sequence context
      */
     public static ImageDirectionPositionPanel forImageSequence() {
-        return new ImageDirectionPositionPanel(tr("Set image direction towards the next one"));
+        return new ImageDirectionPositionPanel(tr("Set image direction towards the next one"), true);
     }
 
     protected void addSetting(String text, JComponent component) {
@@ -86,6 +93,7 @@ public class ImageDirectionPositionPanel extends JPanel {
         return new GpxImageDirectionPositionSettings(
                 cChangeImageDirection.isSelected(),
                 (Integer) sOffsetDegrees.getValue(),
+                cSetGpxTrackTag.isSelected(),
                 (Double) sX.getValue(),
                 (Double) sY.getValue(),
                 (Double) sZ.getValue());
@@ -109,6 +117,7 @@ public class ImageDirectionPositionPanel extends JPanel {
      */
     public void addItemListenerOnComponents(ItemListener listener) {
         cChangeImageDirection.addItemListener(listener);
+        cSetGpxTrackTag.addItemListener(listener);
     }
 
     /**
diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageMetadata.java b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageMetadata.java
index 473e8e5752..c7eb8d3b77 100644
--- a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageMetadata.java
+++ b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageMetadata.java
@@ -128,7 +128,56 @@ public interface ImageMetadata {
     Double getExifImgDir();
 
     /**
-     * Get the last time the source was modified
+     * Get the exif GPS track direction.
+     * @return The GPS track direction
+     * @since xxx
+     */
+    Double getExifGpsTrack();
+
+    /**
+     * Get the exif Horizontal positioning error.
+     * @return The image horizontal positioning error
+     * @since xxx
+     */
+    Double getExifHPosErr();
+
+    /**
+     * Get the GPS Differential mode.
+     * @return The image gnss fix mode
+     * @since xxx
+     */
+    Integer getGpsDiffMode();
+    
+    /**
+     * Get the GPS 2d/3d mode.
+     * @return The image gnss 2d/3d mode
+     * @since xxx
+     */
+    Integer getGps2d3dMode();
+
+    /**
+     * Get the exif GPS DOP value.
+     * @return The image GPS DOP value
+     * @since xxx
+     */
+    Double getExifGpsDop();
+
+    /**
+     * Get the GPS datum value.
+     * @return The image GPS datum value
+     * @since xxx
+     */
+    String getExifGpsDatum();
+
+    /**
+     * Get the exif GPS processing method.
+     * @return The image GPS processing method
+     * @since xxx
+     */
+    String getExifGpsProcMethod();
+
+    /**
+     * Get the last time the source was modified.
      * @return The last time the source was modified
      */
     Instant getLastModified();
@@ -193,17 +242,66 @@ public interface ImageMetadata {
     void setGpsTime(Instant gpsTime);
 
     /**
-     * Set the exif coordinates
+     * Sets the exif coordinates
      * @param exifCoor The exif coordinates
      */
     void setExifCoor(ILatLon exifCoor);
 
     /**
-     * Set the exif direction
+     * Sets the exif direction
      * @param exifDir The direction
      */
     void setExifImgDir(Double exifDir);
 
+    /**
+     * Sets the exif GPS track direction.
+     * @param exifGpsTrack The GPS track direction
+     * @since xxx
+     */
+    void setExifGpsTrack(Double exifGpsTrack);
+
+    /**
+     * Sets the exif horizontal positioning error.
+     * @param exifHposErr the exif horizontal positionning error
+     * @since xxx
+     */
+    void setExifHPosErr(Double exifHPosErr);
+
+    /**
+     * Sets the exif GPS DOP value.
+     * @param exifGpsDop the exif GPS DOP value
+     * @since xxx
+     */
+    void setExifGpsDop(Double exifGpsDop);
+
+    /**
+     * Sets the GPS Differential mode.
+     * @param gpsDiffMode GPS Differential mode
+     * @since xxx
+     */
+    void setGpsDiffMode(Integer gpsDiffMode);
+
+    /**
+     * Sets the GPS 2d/3d mode.
+     * @param gps2d3dMode GPS 2d/3d mode
+     * @since xxx
+     */
+    void setGps2d3dMode(Integer gps2d3dMode);
+
+    /**
+     * Sets the GPS datum value.
+     * @param exifGpsDatum GPS datum
+     * @since xxx
+     */
+    void setExifGpsDatum(String exifGpsDatum);
+
+    /**
+     * Sets the GPS processing method.
+     * @param exifGpsProcMethod GPS processing method
+     * @since xxx
+     */
+    void setExifGpsProcMethod(String exifGpsProcMethod);
+
     /**
      * Sets the IPTC caption.
      * @param iptcCaption the IPTC caption
diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageUtils.java b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageUtils.java
index abe9e1f12c..19f0390c12 100644
--- a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageUtils.java
+++ b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageUtils.java
@@ -191,6 +191,48 @@ public final class ImageUtils {
             Logging.debug(ex);
         }
 
+        try {
+            ifNotNull(ExifReader.readGpsTrackDirection(dirGps), image::setExifGpsTrack);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+
+        try {
+            ifNotNull(ExifReader.readHpositioningError(dirGps), image::setExifHPosErr);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+        
+        try {
+            ifNotNull(ExifReader.readGpsDiffMode(dirGps), image::setGpsDiffMode);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+        
+        try {
+            ifNotNull(ExifReader.readGpsMeasureMode(dirGps), image::setGps2d3dMode);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+
+        try {
+            ifNotNull(ExifReader.readGpsDop(dirGps), image::setExifGpsDop);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+
+        try {
+            ifNotNull(ExifReader.readGpsDatum(dirGps), image::setExifGpsDatum);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+
+        try {
+            ifNotNull(ExifReader.readGpsProcessingMethod(dirGps), image::setExifGpsProcMethod);
+        } catch (IndexOutOfBoundsException ex) {
+            Logging.debug(ex);
+        }
+        
         ifNotNull(dirGps.getGpsDate(), d -> image.setExifGpsTime(d.toInstant()));
     }
 
diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
index d4b402296b..1ce375f9a4 100644
--- a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
+++ b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
@@ -88,6 +88,7 @@ public final class ImageViewerDialog extends ToggleDialog implements LayerChange
 
     private final ImageZoomAction imageZoomAction = new ImageZoomAction();
     private final ImageCenterViewAction imageCenterViewAction = new ImageCenterViewAction();
+    private final ImageExtendedInfoAction imageExtendedInfoAction = new ImageExtendedInfoAction();
     private final ImageNextAction imageNextAction = new ImageNextAction();
     private final ImageRemoveAction imageRemoveAction = new ImageRemoveAction();
     private final ImageRemoveFromDiskAction imageRemoveFromDiskAction = new ImageRemoveFromDiskAction();
@@ -103,6 +104,7 @@ public final class ImageViewerDialog extends ToggleDialog implements LayerChange
     private final ImageDisplay imgDisplay = new ImageDisplay(imageryFilterSettings);
     private Future<?> imgLoadingFuture;
     private boolean centerView;
+    private boolean extendedImgInfo;
 
     // Only one instance of that class is present at one time
     private static volatile ImageViewerDialog dialog;
@@ -163,6 +165,7 @@ public final class ImageViewerDialog extends ToggleDialog implements LayerChange
     private JButton btnOpenExternal;
     private JButton btnDeleteFromDisk;
     private JToggleButton tbCentre;
+    private JToggleButton tbImgExtInfo;
     /** The layer tab (used to select images when multiple layers provide images, makes for easy switching) */
     private final HideableTabbedPane layers = new HideableTabbedPane();
 
@@ -234,6 +237,11 @@ public final class ImageViewerDialog extends ToggleDialog implements LayerChange
         tbCentre.setSelected(centerView);
         tbCentre.setPreferredSize(buttonDim);
 
+        extendedImgInfo = Config.getPref().getBoolean("geoimage.viewer.extendedinfo", false);
+        tbImgExtInfo = new JToggleButton(imageExtendedInfoAction);
+        tbImgExtInfo.setSelected(extendedImgInfo);
+        tbImgExtInfo.setPreferredSize(buttonDim);
+
         JButton btnZoomBestFit = new JButton(imageZoomAction);
         btnZoomBestFit.setPreferredSize(buttonDim);
 
@@ -242,7 +250,7 @@ public final class ImageViewerDialog extends ToggleDialog implements LayerChange
 
         JPanel buttons = new JPanel();
         addButtonGroup(buttons, this.btnFirst, this.btnPrevious, this.btnNext, this.btnLast);
-        addButtonGroup(buttons, this.tbCentre, btnZoomBestFit);
+        addButtonGroup(buttons, this.tbCentre, btnZoomBestFit, this.tbImgExtInfo);
         addButtonGroup(buttons, this.btnDelete, this.btnDeleteFromDisk);
         addButtonGroup(buttons, this.btnCopyPath, this.btnOpenExternal);
         addButtonGroup(buttons, createButton(visibilityAction, buttonDim));
@@ -583,6 +591,23 @@ public final class ImageViewerDialog extends ToggleDialog implements LayerChange
         }
     }
 
+    private class ImageExtendedInfoAction extends JosmAction {
+        ImageExtendedInfoAction() {
+            super(null, new ImageProvider("info"), tr("Display image extended metadata"), Shortcut.registerShortcut(
+                    "geoimage:extendedinfos", tr(GEOIMAGE_FILLER, tr("Toggle Osd extended informations")),
+                    KeyEvent.CHAR_UNDEFINED, Shortcut.NONE),
+            false, null, false);
+        }
+
+        @Override
+        public void actionPerformed(ActionEvent e) {
+            final JToggleButton button = (JToggleButton) e.getSource();
+            extendedImgInfo = button.isEnabled() && button.isSelected();
+            Config.getPref().putBoolean("geoimage.viewer.extendedinfo", extendedImgInfo);
+            refresh(false);
+        }
+    }
+    
     private class ImageRemoveAction extends JosmAction {
         ImageRemoveAction() {
             super(null, new ImageProvider(DIALOG_FOLDER, "delete"), tr("Remove photo from layer"), Shortcut.registerShortcut(
@@ -999,20 +1024,49 @@ public final class ImageViewerDialog extends ToggleDialog implements LayerChange
         if (entry.getSpeed() != null) {
             osd.append(tr("\nSpeed: {0} km/h", Math.round(entry.getSpeed())));
         }
-        if (entry.getExifImgDir() != null) {
-            osd.append(tr("\nDirection {0}\u00b0", Math.round(entry.getExifImgDir())));
-        }
-
         DateTimeFormatter dtf = DateUtils.getDateTimeFormatter(FormatStyle.SHORT, FormatStyle.MEDIUM)
-                // Set timezone to UTC since UTC is assumed when parsing the EXIF timestamp,
-                // see see org.openstreetmap.josm.tools.ExifReader.readTime(com.drew.metadata.Metadata)
-                .withZone(ZoneOffset.UTC);
-
+                    // Set timezone to UTC since UTC is assumed when parsing the EXIF timestamp,
+                    // see see org.openstreetmap.josm.tools.ExifReader.readTime(com.drew.metadata.Metadata)
+                    .withZone(ZoneOffset.UTC);
         if (entry.hasExifTime()) {
-            osd.append(tr("\nEXIF time: {0}", dtf.format(entry.getExifInstant())));
+            if (Config.getPref().getBoolean("geoimage.viewer.extendedinfo", false)) {
+                osd.append(tr("\nEXIF DTO time: {0}", dtf.format(entry.getExifInstant())));
+            } else {
+                osd.append(tr("\nEXIF time: {0}", dtf.format(entry.getExifInstant())));        
+            }
         }
-        if (entry.hasGpsTime()) {
-            osd.append(tr("\nGPS time: {0}", dtf.format(entry.getGpsInstant())));
+
+        if (Config.getPref().getBoolean("geoimage.viewer.extendedinfo", false)) {
+            if (entry.getExifGpsInstant() != null) {
+                osd.append(tr("\nEXIF GPS time: {0}", dtf.format(entry.getExifGpsInstant())));
+            }
+            if (entry.hasGpsTime()) {
+                osd.append(tr("\nCorr GPS time: {0}", dtf.format(entry.getGpsInstant())));
+            }            
+            if (entry.getExifImgDir() != null) {
+                osd.append(tr("\nDirection {0}\u00b0", Math.round(entry.getExifImgDir())));
+            }
+            if (entry.getExifGpsTrack() != null) {
+                osd.append(tr("\nGPS direction: {0}\u00b0", Math.round(entry.getExifGpsTrack())));
+            }
+            if (entry.getExifHPosErr() != null) {
+                osd.append(tr("\nHpos errror: {0}m", entry.getExifHPosErr()));
+            }
+            if (entry.getGps2d3dMode() != null) {
+                osd.append(tr("\n2d/3d mode: {0}d", entry.getGps2d3dMode()));
+            }
+            if (entry.getGpsDiffMode() != null) {
+                osd.append(tr("\nDifferential: {0}", entry.getGpsDiffMode()));
+            }
+            if (entry.getExifGpsDop() != null) {
+                osd.append(tr("\nDOP: {0}", entry.getExifGpsDop()));
+            }
+            if (entry.getExifGpsDatum() != null) {
+                osd.append(tr("\nDatum: {0}", entry.getExifGpsDatum().toString()));
+            }
+            if (entry.getExifGpsProcMethod() != null) {
+                osd.append(tr("\nProc. method: {0}", entry.getExifGpsProcMethod().toString()));
+            }
         }
         Optional.ofNullable(entry.getIptcCaption()).map(s -> tr("\nCaption: {0}", s)).ifPresent(osd::append);
         Optional.ofNullable(entry.getIptcHeadline()).map(s -> tr("\nHeadline: {0}", s)).ifPresent(osd::append);
@@ -1145,6 +1199,19 @@ public final class ImageViewerDialog extends ToggleDialog implements LayerChange
         }
     }
 
+    /**
+     * Reload the image or reload only the image info. Call this if want to update the OSD.
+     * @param imageChanged reload the image if true. Reload only the OSD if false.
+     * @since xxx
+     */
+    public void refresh(boolean imageChanged) {
+        if (SwingUtilities.isEventDispatchThread()) {
+            this.updateButtonsNonNullEntry(currentEntry, imageChanged);
+        } else {
+            GuiHelper.runInEDT(this::refresh);
+        }
+    }
+    
     private void registerOnLayer(Layer layer) {
         if (layer instanceof IGeoImageLayer) {
             layer.addPropertyChangeListener(l -> {
diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/RemoteEntry.java b/src/org/openstreetmap/josm/gui/layer/geoimage/RemoteEntry.java
index ab87cd8c05..e2b5cd3c4c 100644
--- a/src/org/openstreetmap/josm/gui/layer/geoimage/RemoteEntry.java
+++ b/src/org/openstreetmap/josm/gui/layer/geoimage/RemoteEntry.java
@@ -37,8 +37,15 @@ public class RemoteEntry implements IImageEntry<RemoteEntry>, ImageMetadata {
     private ILatLon pos;
     private Integer exifOrientation;
     private Double elevation;
+    private Integer gpsDiffMode;
+    private Integer gps2d3dMode;
+    private Double exifHPosErr;
+    private Double exifGpsDop;
+    private String exifGpsDatum;
+    private String exifGpsProcMethod;
     private Double speed;
     private Double exifImgDir;
+    private Double exifGpsTrack;
     private ILatLon exifCoor;
     private Instant exifTime;
     private Instant exifGpsTime;
@@ -117,6 +124,38 @@ public class RemoteEntry implements IImageEntry<RemoteEntry>, ImageMetadata {
         this.speed = speed;
     }
 
+    /**
+     * @since xxx
+     */
+    @Override
+    public void setGpsDiffMode(Integer gpsDiffMode) {
+        this.gpsDiffMode = gpsDiffMode;
+    }
+
+    /**
+     * @since xxx
+     */
+    @Override
+    public void setGps2d3dMode(Integer gps2d3dMode) {
+        this.gps2d3dMode = gps2d3dMode;
+    }
+
+    /**
+     * @since xxx
+     */
+    @Override
+    public void setExifGpsDatum(String exifGpsDatum) {
+        this.exifGpsDatum = exifGpsDatum;
+    }
+
+    /**
+     * @since xxx
+     */
+    @Override
+    public void setExifGpsProcMethod(String exifGpsProcMethod) {
+        this.exifGpsProcMethod = exifGpsProcMethod;
+    }
+
     @Override
     public void setElevation(Double elevation) {
         this.elevation = elevation;
@@ -152,6 +191,30 @@ public class RemoteEntry implements IImageEntry<RemoteEntry>, ImageMetadata {
         this.exifImgDir = exifDir;
     }
 
+    /**
+     * @since xxx
+     */
+    @Override
+    public void setExifGpsTrack(Double exifGpsTrack) {
+        this.exifGpsTrack = exifGpsTrack;
+    }
+
+    /**
+     * @since xxx
+     */
+    @Override
+    public void setExifHPosErr(Double exifHPosError) {
+        this.exifHPosErr = exifHPosError;
+    }
+
+    /**
+     * @since xxx
+     */
+    @Override
+    public void setExifGpsDop(Double exifGpsDop) {
+        this.exifGpsDop = exifGpsDop;
+    }
+
     @Override
     public void setIptcCaption(String iptcCaption) {
         this.iptcCaption = iptcCaption;
@@ -212,11 +275,70 @@ public class RemoteEntry implements IImageEntry<RemoteEntry>, ImageMetadata {
         return this.elevation;
     }
 
+    /**
+     * @since xxx
+     */
+    @Override
+    public Integer getGpsDiffMode() {
+        return this.gpsDiffMode;
+    }
+    
+    /**
+     * @since xxx
+     */
+    @Override
+    public Integer getGps2d3dMode() {
+        return this.gps2d3dMode;
+    }
+
+    /**
+     * @since xxx
+     */
+    @Override
+    public String getExifGpsDatum() {
+        return this.exifGpsDatum;
+    }
+
+    /**
+     * @since xxx
+     */
+    @Override
+    public String getExifGpsProcMethod() {
+        return this.exifGpsProcMethod;
+    }
+
+    /**
+     * @since xxx
+     */
     @Override
     public Double getExifImgDir() {
         return this.exifImgDir;
     }
 
+    /**
+     * @since xxx
+     */
+    @Override
+    public Double getExifGpsTrack() {
+        return this.exifGpsTrack;
+    }
+
+    /**
+     * @since xxx
+     */
+    @Override
+    public Double getExifHPosErr() {
+        return this.exifHPosErr;
+    }
+
+    /**
+     * @since xxx
+     */
+    @Override
+    public Double getExifGpsDop() {
+        return this.exifGpsDop;
+    }
+
     @Override
     public Instant getLastModified() {
         if ("file".equals(this.getImageURI().getScheme())) {
@@ -335,9 +457,11 @@ public class RemoteEntry implements IImageEntry<RemoteEntry>, ImageMetadata {
     public int hashCode() {
         return Objects.hash(this.uri, this.pos,
                 this.exifOrientation, this.elevation, this.speed, this.exifImgDir,
-                this.exifCoor, this.exifTime, this.exifGpsTime, this.gpsTime,
-                this.iptcObjectName, this.iptcCaption, this.iptcHeadline, this.iptcKeywords,
-                this.projection, this.title);
+                this.exifGpsTrack, this.exifCoor, this.exifTime, this.exifGpsTime,
+                this.gpsTime, this.exifHPosErr, this.exifGpsDop, this.gpsDiffMode,
+                this.gps2d3dMode, this.exifGpsDatum, this.exifGpsProcMethod,
+                this.iptcObjectName, this.iptcCaption, this.iptcHeadline,
+                this.iptcKeywords, this.projection, this.title);
     }
 
     @Override
@@ -352,6 +476,9 @@ public class RemoteEntry implements IImageEntry<RemoteEntry>, ImageMetadata {
                     && Objects.equals(this.exifCoor, other.exifCoor)
                     && Objects.equals(this.exifGpsTime, other.exifGpsTime)
                     && Objects.equals(this.exifImgDir, other.exifImgDir)
+                    && Objects.equals(this.exifGpsTrack, other.exifGpsTrack)
+                    && Objects.equals(this.exifHPosErr, other.exifHPosErr)
+                    && Objects.equals(this.exifGpsDop, other.exifGpsDop)
                     && Objects.equals(this.exifOrientation, other.exifOrientation)
                     && Objects.equals(this.exifTime, other.exifTime)
                     && Objects.equals(this.gpsTime, other.gpsTime)
@@ -362,6 +489,10 @@ public class RemoteEntry implements IImageEntry<RemoteEntry>, ImageMetadata {
                     && Objects.equals(this.pos, other.pos)
                     && Objects.equals(this.projection, other.projection)
                     && Objects.equals(this.speed, other.speed)
+                    && Objects.equals(this.gpsDiffMode, other.gpsDiffMode)
+                    && Objects.equals(this.gps2d3dMode, other.gps2d3dMode)
+                    && Objects.equals(this.exifGpsDatum, other.exifGpsDatum)
+                    && Objects.equals(this.exifGpsProcMethod, other.exifGpsProcMethod)
                     && Objects.equals(this.title, other.title);
         }
         return false;
diff --git a/src/org/openstreetmap/josm/io/nmea/NmeaParser.java b/src/org/openstreetmap/josm/io/nmea/NmeaParser.java
index 3c6b82e12c..9631df402e 100644
--- a/src/org/openstreetmap/josm/io/nmea/NmeaParser.java
+++ b/src/org/openstreetmap/josm/io/nmea/NmeaParser.java
@@ -466,7 +466,7 @@ public class NmeaParser {
                     accu = e[VTG.COURSE.position];
                     if (!accu.isEmpty() && currentwp != null) {
                         Double.parseDouble(accu);
-                        currentwp.put("course", accu);
+                        currentwp.put(GpxConstants.PT_COURSE, accu);
                     }
                 }
                 // SPEED
@@ -542,7 +542,7 @@ public class NmeaParser {
                 accu = e[RMC.COURSE.position];
                 if (!accu.isEmpty() && !currentwp.attr.containsKey("course")) {
                     Double.parseDouble(accu);
-                    currentwp.put("course", accu);
+                    currentwp.put(GpxConstants.PT_COURSE, accu);
                 }
 
                 // TODO fix?
diff --git a/src/org/openstreetmap/josm/io/session/GeoImageSessionExporter.java b/src/org/openstreetmap/josm/io/session/GeoImageSessionExporter.java
index fa24a4d66a..47ff8ebb8d 100644
--- a/src/org/openstreetmap/josm/io/session/GeoImageSessionExporter.java
+++ b/src/org/openstreetmap/josm/io/session/GeoImageSessionExporter.java
@@ -22,6 +22,7 @@ import org.w3c.dom.Element;
 /**
  * Session exporter for {@link GeoImageLayer}.
  * @since 5505
+ * @since xxx exifGpsTrack, exifHPosErr, gpsDiffMode, gps2d3dMode, exifGpsDop, exifGpsDatum, exifGpsProcMethod exporter added
  */
 public class GeoImageSessionExporter extends AbstractSessionExporter<GeoImageLayer> {
 
@@ -105,6 +106,27 @@ public class GeoImageSessionExporter extends AbstractSessionExporter<GeoImageLay
             if (entry.getExifImgDir() != null) {
                 addAttr("exif-image-direction", entry.getExifImgDir().toString(), imgElem, support);
             }
+            if (entry.getExifGpsTrack() != null) {
+                addAttr("exif-gps-track", entry.getExifGpsTrack().toString(), imgElem, support);
+            }
+            if (entry.getExifHPosErr() != null) {
+                addAttr("exif-gps-hposerr", entry.getExifHPosErr().toString(), imgElem, support);
+            }
+            if (entry.getGpsDiffMode() != null) {
+                addAttr("exif-gps-diffmode", entry.getGpsDiffMode().toString(), imgElem, support);
+            }
+            if (entry.getGps2d3dMode() != null) {
+                addAttr("exif-gps-2d3dmode", entry.getGps2d3dMode().toString(), imgElem, support);
+            }
+            if (entry.getExifGpsDop() != null) {
+                addAttr("exif-gps-dop", entry.getExifGpsDop().toString(), imgElem, support);
+            }
+            if (entry.getExifGpsDatum() != null) {
+                addAttr("exif-gps-datum", entry.getExifGpsDatum().toString(), imgElem, support);
+            }
+            if (entry.getExifGpsProcMethod() != null) {
+                addAttr("exif-gps-procmethod", entry.getExifGpsProcMethod().toString(), imgElem, support);
+            }
             if (entry.hasNewGpsData()) {
                 addAttr("is-new-gps-data", Boolean.toString(entry.hasNewGpsData()), imgElem, support);
             }
diff --git a/src/org/openstreetmap/josm/io/session/GeoImageSessionImporter.java b/src/org/openstreetmap/josm/io/session/GeoImageSessionImporter.java
index 80f99b68ad..0914fe4c97 100644
--- a/src/org/openstreetmap/josm/io/session/GeoImageSessionImporter.java
+++ b/src/org/openstreetmap/josm/io/session/GeoImageSessionImporter.java
@@ -25,6 +25,7 @@ import org.w3c.dom.NodeList;
 /**
  * Session importer for {@link GeoImageLayer}.
  * @since 5505
+ * @since xxx exifGpsTrack, exifHPosErr, gpsDiffMode, gps2d3dMode, exifGpsDop, exifGpsDatum, exifGpsProcMethod importer added
  */
 public class GeoImageSessionImporter implements SessionLayerImporter {
 
@@ -108,6 +109,27 @@ public class GeoImageSessionImporter implements SessionLayerImporter {
             case "exif-image-direction":
                 entry.setExifImgDir(Double.valueOf(attrElem.getTextContent()));
                 break;
+            case "exif-gps-track":
+                entry.setExifGpsTrack(Double.valueOf(attrElem.getTextContent()));
+                break;
+            case "exif-gps-hposerr":
+                entry.setExifHPosErr(Double.valueOf(attrElem.getTextContent()));
+                break;
+            case "exif-gps-diffmode":
+                entry.setGpsDiffMode(Integer.valueOf(attrElem.getTextContent()));
+                break;
+            case "exif-gps-2d3dmode":
+                entry.setGps2d3dMode(Integer.valueOf(attrElem.getTextContent()));
+                break;
+            case "exif-gps-dop":
+                entry.setExifGpsDop(Double.valueOf(attrElem.getTextContent()));
+                break;
+            case "exif-gps-datum":
+                entry.setExifGpsDatum(attrElem.getTextContent());
+                break;
+            case "exif-gps-procmethod":
+                entry.setExifGpsProcMethod(attrElem.getTextContent());
+                break;
             case "is-new-gps-data":
                 if (Boolean.parseBoolean(attrElem.getTextContent())) {
                     entry.flagNewGpsData();
diff --git a/src/org/openstreetmap/josm/tools/ExifReader.java b/src/org/openstreetmap/josm/tools/ExifReader.java
index ad9e361c4f..404481b3a3 100644
--- a/src/org/openstreetmap/josm/tools/ExifReader.java
+++ b/src/org/openstreetmap/josm/tools/ExifReader.java
@@ -123,6 +123,41 @@ public final class ExifReader {
         return null;
     }
 
+    /**
+     * Returns the GPS date/time from the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS date/time read in the EXIF section, or {@code null} if not found
+     * @since xxx
+     */
+    public static Instant readGpsInstant(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsInstant(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+ 
+    /**
+     * Returns the GPS date/time from the given JPEG file.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS date/time read in the EXIF section, or {@code null} if not found
+     * @since xxx
+     */
+    public static Instant readGpsInstant(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            try {
+                Instant dateTimeStamp = dirGps.getGpsDate().toInstant();
+                return dateTimeStamp;
+            } catch (UncheckedParseException | DateTimeException e) {
+                Logging.error(e);
+            }
+        }
+        return null;
+    }
+ 
     /**
      * Returns the image orientation of the given JPEG file.
      * @param filename The JPEG file to read
@@ -218,6 +253,41 @@ public final class ExifReader {
         return null;
     }
 
+    /**
+     * Returns the GPS track direction of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS track direction of the image when it was captures (in degrees between 0.0 and 359.99),
+     * or {@code null} if not found
+     * @since xxx
+     */
+    public static Double readGpsTrackDirection(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsTrackDirection(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+    
+    /**
+     * Returns the GPS track direction of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS track direction of the image when it was captured (in degrees between 0.0 and 359.99),
+     * or {@code null} if missing or if {@code dirGps} is null
+     * @since xxx
+     */
+    public static Double readGpsTrackDirection(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            Rational trackDirection = dirGps.getRational(GpsDirectory.TAG_TRACK);
+            if (trackDirection != null) {
+                return trackDirection.doubleValue();
+            }
+        }
+        return null;
+    }
+
     private static double readAxis(GpsDirectory dirGps, int gpsTag, int gpsTagRef, char cRef) throws MetadataException {
         double value;
         Rational[] components = dirGps.getRationalArray(gpsTag);
@@ -323,6 +393,256 @@ public final class ExifReader {
         return null;
     }
 
+    /**
+     * Returns the GPS horizontal positionning error of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS horizontal positionning error of the camera when the image was captured (in m),
+     *         or {@code null} if not found
+     * @since xxx
+     */
+    public static Double readHpositioningError(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readHpositioningError(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS horizontal positionning error of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS horizontal positionning error of the camera when the image was captured (in m),
+     *         or {@code null} if missing or if {@code dirGps} is null
+     * @since xxx
+     */
+    public static Double readHpositioningError(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            Double hposerr = dirGps.getDoubleObject(GpsDirectory.TAG_H_POSITIONING_ERROR);
+            if (hposerr != null) {
+                return hposerr.doubleValue();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS differential mode of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS differential mode of the camera when the image was captured,
+     * <ul>
+     *  <li>0 : no differential correction</li>
+     *  <li>1 : differential correction</li>
+     *  <li>or {@code null} if not found</li>
+     * </ul>
+     * @since xxx
+     */
+    public static Integer readGpsDiffMode(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsDiffMode(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS differential mode of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS differential mode of the camera when the image was captured,
+     * <ul>
+     *  <li>0 : no differential correction</li>
+     *  <li>1 : differential correction</li>
+     *  <li>or {@code null} if missing or if {@code dirGps} is null</li>
+     * </ul>
+     * @since xxx
+     */    
+    public static Integer readGpsDiffMode(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            Integer gpsDiffMode = dirGps.getInteger(GpsDirectory.TAG_DIFFERENTIAL);
+            if (gpsDiffMode != null) {
+                return gpsDiffMode.intValue();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS 2d/3d mode of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS 2d/3d mode of the camera when the image was captured,
+     * <ul>
+     *  <li>2 : 2d mode</li>
+     *  <li>2 : 3d mode</li>
+     *  <li>or {@code null} if not found</li>
+     * </ul>
+     * @since xxx
+     */
+    public static Integer readGpsMeasureMode(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsMeasureMode(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS 2d/3d mode of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The 2d/3d mode of the camera when the image was captured,
+     * <ul>
+     *  <li>2 : 2d mode</li>
+     *  <li>3 : 3d mode</li>
+     *  <li>or {@code null} if missing or if {@code dirGps} is null</li>
+     * </ul>
+     * @since xxx
+     */    
+    public static Integer readGpsMeasureMode(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            Integer gps2d3dMode = dirGps.getInteger(GpsDirectory.TAG_MEASURE_MODE);
+            if (gps2d3dMode != null) {
+                return gps2d3dMode.intValue();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS DOP value of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS DOP value of the camera when the image was captured,
+     *         or {@code null} if not found
+     * @since xxx
+     */
+    public static Double readGpsDop(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsDop(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS DOP value of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS DOP value of the camera when the image was captured,
+     *         or {@code null} if missing or if {@code dirGps} is null
+     * @since xxx
+     */
+    public static Double readGpsDop(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            Double gpsDop = dirGps.getDoubleObject(GpsDirectory.TAG_DOP);
+            if (gpsDop != null) {
+                return gpsDop.doubleValue();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS datum value of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS datum value of the camera when the image was captured,
+     *         or {@code null} if not found
+     * @since xxx
+     */
+    public static String readGpsDatum(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsDatum(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GPS datum value of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS datum value of the camera when the image was captured,
+     *         or {@code null} if missing or if {@code dirGps} is null
+     * @since xxx
+     */
+    public static String readGpsDatum(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            String gpsDatum = dirGps.getString(GpsDirectory.TAG_MAP_DATUM);
+            if (gpsDatum != null) {
+                return gpsDatum.toString();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return the GPS processing method of the given JPEG file.
+     * @param filename The JPEG file to read
+     * @return The GPS processing method. Possible values from the EXIF specs are:
+     * <ul>
+     * <li>GPS</li>
+     * <li>QZSS</li>
+     * <li>GALILEO</li>
+     * <li>GLONASS</li>
+     * <li>BEIDOU</li>
+     * <li>NAVIC</li>
+     * <li>CELLID</li>
+     * <li>WLAN</li>
+     * <li>MANUAL</li>
+     * </ul>
+     * Other values, and combined space separated values are possible too.
+     * or {@code null} if missing
+     * @since xxx
+     */
+    public static String readGpsProcessingMethod(File filename) {
+        try {
+            final Metadata metadata = JpegMetadataReader.readMetadata(filename);
+            final GpsDirectory dirGps = metadata.getFirstDirectoryOfType(GpsDirectory.class);
+            return readGpsProcessingMethod(dirGps);
+        } catch (JpegProcessingException | IOException e) {
+            Logging.error(e);
+        }
+        return null;
+    }
+
+    /**
+     * Return the GPS processing method of the given EXIF GPS directory.
+     * @param dirGps The EXIF GPS directory
+     * @return The GPS processing method. Possible values from the EXIF specs are:
+     * <ul>
+     * <li>GPS</li>
+     * <li>QZSS</li>
+     * <li>GALILEO</li>
+     * <li>GLONASS</li>
+     * <li>BEIDOU</li>
+     * <li>NAVIC</li>
+     * <li>CELLID</li>
+     * <li>WLAN</li>
+     * <li>MANUAL</li>
+     * </ul>
+     * Other values, and combined space separated values are possible too.
+     * or {@code null} if missing or if {@code dirGps} is null
+     * @since xxx
+     */
+    public static String readGpsProcessingMethod(GpsDirectory dirGps) {
+        if (dirGps != null) {
+            String gpsProcessingMethod = dirGps.getDescription(GpsDirectory.TAG_PROCESSING_METHOD);
+            if (gpsProcessingMethod != null) {
+                return gpsProcessingMethod.toString();
+            }
+        }
+        return null;
+    }
+
     /**
      * Returns the caption of the given IPTC directory.
      * @param dirIptc The IPTC directory
diff --git a/test/unit/org/openstreetmap/josm/data/ImageDataTest.java b/test/unit/org/openstreetmap/josm/data/ImageDataTest.java
index 22dd7eff9f..3618721d8e 100644
--- a/test/unit/org/openstreetmap/josm/data/ImageDataTest.java
+++ b/test/unit/org/openstreetmap/josm/data/ImageDataTest.java
@@ -444,6 +444,90 @@ class ImageDataTest {
         data.updateImageDirection(list.get(0), 0);
     }
 
+    @Test
+    void testUpdateHPosErr() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setExifHPosErr(1.23);
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageHPosErr(list.get(0), 1.23);
+    }
+
+    @Test
+    void testUpdateGpsDatum() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setExifGpsDatum("WGS-84");
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageExifGpsDatum(list.get(0), "WGS-84");
+    }
+
+    @Test
+    void testUpdateGpsTrack() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setExifGpsTrack(180.5);
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageGpsTrack(list.get(0), 180.5);
+    }
+
+    @Test
+    void testUpdateGpsDop() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setExifGpsDop(1.9);
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageExifGpsDop(list.get(0), 1.9);
+    }
+
+    @Test
+    void testUpdateGpsProcMethod() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setExifGpsProcMethod("GNSS RTK CORRELATION");
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageExifGpsProcMethod(list.get(0), "GNSS RTK CORRELATION");
+    }
+
+    @Test
+    void testUpdateGpsDifferentialMode() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setGpsDiffMode(1);
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageGpsDiffMode(list.get(0), 1);
+    }
+
+    @Test
+    void testUpdateGps2d3dMode() {
+        List<ImageEntry> list = getOneImage();
+        ImageData data = new ImageData(list);
+
+        new Expectations(list.get(0)) {{
+            list.get(0).setGps2d3dMode(3);
+            list.get(0).flagNewGpsData();
+        }};
+        data.updateImageGps2d3dMode(list.get(0), 3);
+    }
+
     @Test
     void testTriggerListenerOnUpdate() {
         List<ImageEntry> list = getOneImage();
diff --git a/test/unit/org/openstreetmap/josm/data/gpx/GpxImageCorrelationTest.java b/test/unit/org/openstreetmap/josm/data/gpx/GpxImageCorrelationTest.java
index ad5029fba3..74b9316a31 100644
--- a/test/unit/org/openstreetmap/josm/data/gpx/GpxImageCorrelationTest.java
+++ b/test/unit/org/openstreetmap/josm/data/gpx/GpxImageCorrelationTest.java
@@ -350,4 +350,81 @@ class GpxImageCorrelationTest {
         wp.put(GpxConstants.PT_ELE, "150.0");
         assertEquals(Double.valueOf(150.0d), GpxImageCorrelation.getElevation(wp));
     }
+
+    /**
+     * Unit test of {@link GpxImageCorrelation#getHPosErr}
+     */
+    @Test
+    void testGetHorizontalPosError() {
+        assertNull(GpxImageCorrelation.getHPosErr(null));
+        WayPoint wp = new WayPoint(LatLon.ZERO);
+        assertNull(GpxImageCorrelation.getHPosErr(wp));
+        wp.put(GpxConstants.PT_STD_HDEV, 1.5f);
+        assertEquals(1.5f, GpxImageCorrelation.getHPosErr(wp));
+    }
+
+    /**
+     * Unit test of {@link GpxImageCorrelation#getGpsDop}
+     */
+    @Test
+    void testGetGpsDop() {
+        assertNull(GpxImageCorrelation.getGpsDop(null));
+        WayPoint wp = new WayPoint(LatLon.ZERO);
+        assertNull(GpxImageCorrelation.getGpsDop(wp));
+        wp.put(GpxConstants.PT_HDOP, 2.1f);
+        assertEquals(2.1f, GpxImageCorrelation.getGpsDop(wp));
+        wp.put(GpxConstants.PT_PDOP, 0.9f);
+        assertEquals(0.9f, GpxImageCorrelation.getGpsDop(wp));
+        wp.put(GpxConstants.PT_PDOP, 1.2d);
+        assertEquals(1.2d, GpxImageCorrelation.getGpsDop(wp));
+    }
+
+    /**
+     * Unit test of {@link GpxImageCorrelation#getGpsTrack}
+     */
+    @Test
+    void testGetGpsTrack() {
+        assertNull(GpxImageCorrelation.getHPosErr(null));
+        WayPoint wp = new WayPoint(LatLon.ZERO);
+        assertNull(GpxImageCorrelation.getGpsTrack(wp));
+        wp.put(GpxConstants.PT_COURSE, "");
+        assertNull(GpxImageCorrelation.getGpsTrack(wp));
+        wp.put(GpxConstants.PT_COURSE, "not a number");
+        assertNull(GpxImageCorrelation.getGpsTrack(wp));
+        wp.put(GpxConstants.PT_COURSE, "167.0");
+        assertEquals(Double.valueOf(167.0d), GpxImageCorrelation.getGpsTrack(wp), 0.01d);
+    }
+
+    /**
+     * Unit test of {@link GpxImageCorrelation#getGpsProcMethod}
+     */
+    @Test
+    void testGetGpsProcMethod() {
+        final List<String> positionningModes = Arrays.asList("none", "manual", "estimated", "2d", "3d", "dgps", "float rtk", "rtk");
+        assertNull(GpxImageCorrelation.getGpsProcMethod(null, null, positionningModes));
+        assertNull(GpxImageCorrelation.getGpsProcMethod("", "", positionningModes));
+        assertNull(GpxImageCorrelation.getGpsProcMethod("3d", null, positionningModes));
+        assertNull(GpxImageCorrelation.getGpsProcMethod("", "dgps", positionningModes));
+        assertEquals("MANUAL CORRELATION", GpxImageCorrelation.getGpsProcMethod("manual", "rtk", positionningModes));
+        assertEquals("ESTIMATED CORRELATION", GpxImageCorrelation.getGpsProcMethod("estimated", "2d", positionningModes));
+        assertEquals("GNSS DGPS CORRELATION", GpxImageCorrelation.getGpsProcMethod("rtk", "dgps", positionningModes));
+        assertEquals("GNSS RTK_FLOAT CORRELATION", GpxImageCorrelation.getGpsProcMethod("float rtk", "rtk", positionningModes));
+        assertEquals("GNSS RTK_FIX CORRELATION", GpxImageCorrelation.getGpsProcMethod("rtk", "rtk", positionningModes));
+    }
+
+    /**
+     * Unit test of {@link GpxImageCorrelation#getGps2d3dMode}
+     */
+    @Test
+    void testGetGps2d3dMode() {
+        final List<String> positionningModes = Arrays.asList("none", "manual", "estimated", "2d", "3d", "dgps", "float rtk", "rtk");
+        assertNull(GpxImageCorrelation.getGps2d3dMode(null, null, positionningModes));
+        assertNull(GpxImageCorrelation.getGps2d3dMode("", "", positionningModes));
+        assertNull(GpxImageCorrelation.getGps2d3dMode("3d", null, positionningModes));
+        assertNull(GpxImageCorrelation.getGps2d3dMode("", "dgps", positionningModes));
+        assertNull(GpxImageCorrelation.getGps2d3dMode("estimated", "rtk", positionningModes));
+        assertEquals(2, GpxImageCorrelation.getGps2d3dMode("2d", "2d", positionningModes));
+        assertEquals(2, GpxImageCorrelation.getGps2d3dMode("2d", "3d", positionningModes));
+        assertEquals(3, GpxImageCorrelation.getGps2d3dMode("3d", "dgps", positionningModes));
+    }
 }
diff --git a/test/unit/org/openstreetmap/josm/tools/ExifReaderTest.java b/test/unit/org/openstreetmap/josm/tools/ExifReaderTest.java
index 285acd9d55..9dcad6ca38 100644
--- a/test/unit/org/openstreetmap/josm/tools/ExifReaderTest.java
+++ b/test/unit/org/openstreetmap/josm/tools/ExifReaderTest.java
@@ -21,7 +21,7 @@ import org.openstreetmap.josm.data.coor.conversion.DMSCoordinateFormat;
  * @since 6209
  */
 class ExifReaderTest {
-    private File orientationSampleFile, directionSampleFile;
+    private File orientationSampleFile, directionSampleFile, positionErrorSampleFile;
 
     /**
      * Setup test
@@ -30,6 +30,7 @@ class ExifReaderTest {
     public void setUp() {
         directionSampleFile = new File("nodist/data/exif-example_direction.jpg");
         orientationSampleFile = new File("nodist/data/exif-example_orientation=6.jpg");
+        positionErrorSampleFile = new File("nodist/data/exif-position-error.jpg"); 
     }
 
     /**
@@ -55,6 +56,15 @@ class ExifReaderTest {
         assertEquals(Instant.parse(expectedDate), date);
     }
 
+    /**
+     * Test reading GPS date and time
+     */
+    @Test
+    void testReadGpsDateTime() {
+        Instant date = ExifReader.readGpsInstant(positionErrorSampleFile);
+        assertEquals(Instant.parse("2024-04-30T16:36:42Z"), date);
+    }
+ 
     /**
      * Test orientation extraction
      */
@@ -100,6 +110,62 @@ class ExifReaderTest {
         assertEquals(Double.valueOf(23.4), ExifReader.readElevation(new File("nodist/data/exif-example_speed_ele.jpg")));
     }
 
+    /**
+     * Test horizontal position error extraction
+     */
+    @Test
+    void testReadHorPosError() {
+        assertEquals(Double.valueOf(0.014), ExifReader.readHpositioningError(positionErrorSampleFile));
+    }
+
+    /**
+     * Test GPS track course extraction
+     */
+    @Test
+    void testReadGpsTrack() {
+        assertEquals(Double.valueOf(298), ExifReader.readGpsTrackDirection(positionErrorSampleFile));
+    }
+
+    /**
+     * Test GPS differential mode extraction
+     */
+    @Test
+    void testReadGpsDiffmode() {
+        assertEquals(Integer.valueOf(1), ExifReader.readGpsDiffMode(positionErrorSampleFile));
+    }
+
+    /**
+     * Test GPS DOP value extraction
+     */
+    @Test
+    void testReadGpsDop() {
+        assertEquals(Double.valueOf(0.92), ExifReader.readGpsDop(positionErrorSampleFile));
+    }
+
+    /**
+     * Test GPS measure mode (2D/3D) extraction
+     */
+    @Test
+    void testReadGps2d3dMode() {
+        assertEquals(Integer.valueOf(3), ExifReader.readGpsMeasureMode(positionErrorSampleFile));
+    }
+
+    /**
+     * Test GPS datum extraction
+     */
+    @Test
+    void testReadGpsDatum() {
+        assertEquals(String.valueOf("EPSG:9782"), ExifReader.readGpsDatum(positionErrorSampleFile));
+    }
+
+    /**
+     * Test GPS processing method extraction
+     */
+    @Test
+    void testReadGpsProcMethod() {
+        assertEquals(String.valueOf("GNSS RTK_FIX CORRELATION"), ExifReader.readGpsProcessingMethod(positionErrorSampleFile));
+    }
+
     /**
      * Non-regression test for ticket <a href="https://josm.openstreetmap.de/ticket/11685">#11685</a>
      * @throws IOException if an error occurs during reading
