Index: src/org/openstreetmap/josm/plugins/photo_geotagging/ExifGPSTagger.java
===================================================================
--- src/org/openstreetmap/josm/plugins/photo_geotagging/ExifGPSTagger.java	(revision 36433)
+++ src/org/openstreetmap/josm/plugins/photo_geotagging/ExifGPSTagger.java	(working copy)
@@ -46,13 +46,25 @@
      * @param speed speed in km/h - can be null if not available
      * @param ele elevation - can be null if not available
      * @param imgDir image direction in degrees (0..360) - can be null if not available
+     * @param gpsTrack image course direction in degrees (0...360) - can be null if not available
+     * @param gpsDiffMode Gps differential mode (0 or 1)
+     * @param gpsMeasureMode Gps measure mode (2 for 2d, 3 for 3d)
+     * @param exifGpsProcMethod Gps processing method
+     * @param exifHPosErr image horizontal position error estimation
+     * @param exifGpsDop image gps dop value
+     * @param exifGpsDatum image coordinates datum
      * @param lossy whether to use lossy approach when writing metadata (overwriting unknown tags)
      * @throws IOException in case of I/O error
+     * @since xxx param added: gpsTrack, gpsDiffMode, gpsMeasureMode, exifGpsProcMethod, exifHPosErr, exifGpsDop, exifGpsDatum
      */
+
     public static void setExifGPSTag(File imageFile, File dst, double lat, double lon, Instant gpsTime, Double speed,
-            Double ele, Double imgDir, boolean lossy) throws IOException {
+            Double ele, Double imgDir, Double gpsTrack, Integer gpsDiffMode, Integer gpsMeasureMode,
+            String exifGpsProcMethod, Double exifHPosErr, Double exifGpsDop, String exifGpsDatum,
+            boolean lossy) throws IOException {
         try {
-            setExifGPSTagWorker(imageFile, dst, lat, lon, gpsTime, speed, ele, imgDir, lossy);
+            setExifGPSTagWorker(imageFile, dst, lat, lon, gpsTime, speed, ele, imgDir, gpsTrack, gpsDiffMode,
+            gpsMeasureMode, exifGpsProcMethod, exifHPosErr, exifGpsDop, exifGpsDatum, lossy);
         } catch (ImagingException ire) {
             // This used to be two separate exceptions; ImageReadException and imageWriteException
             throw new IOException(tr("Read/write error: " + ire.getMessage()), ire);
@@ -59,8 +71,10 @@
         }
     }
 
-    public static void setExifGPSTagWorker(File imageFile, File dst, double lat, double lon, Instant gpsTime, Double speed,
-            Double ele, Double imgDir, boolean lossy) throws IOException {
+    public static void setExifGPSTagWorker(File imageFile, File dst, double lat, double lon, Instant gpsTime,
+            Double speed, Double ele, Double imgDir, Double gpsTrack, Integer gpsDiffMode, Integer gpsMeasureMode,
+            String exifGpsProcMethod, Double exifHPosErr, Double exifGpsDop, String exifGpsDatum,
+            boolean lossy) throws IOException {
 
         TiffOutputSet outputSet = null;
         ImageMetadata metadata = Imaging.getMetadata(imageFile);
@@ -141,18 +155,54 @@
             gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF);
             gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF,
                              GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF_VALUE_TRUE_NORTH);
-            // make sure the value is in the range 0.0...<360.0
-            if (imgDir < 0.0) {
-                imgDir %= 360.0; // >-360.0...-0.0
-                imgDir += 360.0; // >0.0...360.0
-            }
-            if (imgDir >= 360.0) {
-                imgDir %= 360.0;
-            }
+            imgDir = checkAngle(imgDir);
             gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION);
             gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION, RationalNumber.valueOf(imgDir));
         }
 
+        if (gpsTrack != null) {
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_TRACK_REF);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_TRACK_REF,
+                             GpsTagConstants.GPS_TAG_GPS_TRACK_REF_VALUE_TRUE_NORTH);
+            // make sure the value is in the range 0.0...<360.0
+            gpsTrack = checkAngle(gpsTrack);
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_TRACK);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_TRACK, RationalNumber.valueOf(gpsTrack));
+        }
+
+        if (gpsDiffMode != null) {
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_DIFFERENTIAL);
+            // make sure the gpsDiffMode value is 0 (no diffential) or 1 (differential)
+            if (gpsDiffMode.equals(0) || gpsDiffMode.equals(1)) {
+                gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_DIFFERENTIAL, gpsDiffMode.shortValue());
+            }
+        }
+        
+        if (gpsMeasureMode != null) {
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_MEASURE_MODE);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_MEASURE_MODE, gpsMeasureMode.toString());
+        }
+
+        if (exifGpsProcMethod != null ) {
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_PROCESSING_METHOD);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_PROCESSING_METHOD, exifGpsProcMethod);
+        }
+
+        if (exifGpsDatum != null) {
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_MAP_DATUM);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_MAP_DATUM, exifGpsDatum.toString());
+        }
+
+        if (exifHPosErr != null) {
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_HOR_POSITIONING_ERROR);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_HOR_POSITIONING_ERROR, RationalNumber.valueOf(exifHPosErr));
+        }
+
+        if (exifGpsDop != null) {
+            gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_DOP);
+            gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_DOP, RationalNumber.valueOf(exifGpsDop));
+        }
+
         try (BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(dst))) {
             if (metadata instanceof JpegImageMetadata) {
                 if (lossy) {
@@ -165,4 +215,21 @@
             }
         }
     }
+
+    /**
+     * Normalizes an angle to the range [0.0, 360.0[ degrees.
+     * This will fix any angle value <0 and >= 360 
+     * @param angle the angle to normalize (in degrees)
+     * @return the equivalent angle value in the range [0.0, 360.0[
+     */
+    private static Double checkAngle(Double angle) {
+        if (angle < 0.0) {
+            angle %= 360.0; // >-360.0...-0.0
+            angle += 360.0; // >0.0...360.0
+        }
+        if (angle >= 360.0) {
+            angle %= 360.0;
+        }
+        return angle;
+    }
 }
Index: src/org/openstreetmap/josm/plugins/photo_geotagging/GeotaggingAction.java
===================================================================
--- src/org/openstreetmap/josm/plugins/photo_geotagging/GeotaggingAction.java	(revision 36433)
+++ src/org/openstreetmap/josm/plugins/photo_geotagging/GeotaggingAction.java	(working copy)
@@ -371,7 +371,10 @@
             chooseFiles(e.getFile());
             if (canceled) return;
             ExifGPSTagger.setExifGPSTag(fileFrom, fileTo, e.getPos().lat(), e.getPos().lon(),
-                    e.getGpsInstant(), e.getSpeed(), e.getElevation(), e.getExifImgDir(), lossy);
+                    e.getGpsInstant(), e.getSpeed(), e.getElevation(), e.getExifImgDir(),
+                    e.getExifGpsTrack(), e.getGpsDiffMode(), e.getGps2d3dMode(),
+                    e.getExifGpsProcMethod(), e.getExifHPosErr(), e.getExifGpsDop(),
+                    e.getExifGpsDatum(), lossy);
 
             if (mTime != null) {
                 if (!fileTo.setLastModified(mTime.toEpochMilli()))
Index: test/unit/org/openstreetmap/josm/plugins/photo_geotagging/ExifGPSTaggerTest.java
===================================================================
--- test/unit/org/openstreetmap/josm/plugins/photo_geotagging/ExifGPSTaggerTest.java	(revision 36433)
+++ test/unit/org/openstreetmap/josm/plugins/photo_geotagging/ExifGPSTaggerTest.java	(working copy)
@@ -28,7 +28,7 @@
     void testTicket11757() {
         final File in = new File(TestUtils.getTestDataRoot(), "_DSC1234.jpg");
         final File out = new File(tempFolder, in.getName());
-        assertDoesNotThrow(() -> ExifGPSTagger.setExifGPSTag(in, out, 12, 34, Instant.now(), 12.34, Math.E, Math.PI, true));
+        assertDoesNotThrow(() -> ExifGPSTagger.setExifGPSTag(in, out, 12, 34, Instant.now(), 12.34, Math.E, Math.PI, Math.PI, 2, 3, "GPS", 1.2, 2.5, "WGS84", true));
     }
 
     @Test
@@ -46,7 +46,7 @@
     void testTicket11902() throws Exception {
         final File in = new File(TestUtils.getTestDataRoot(), "IMG_7250_small.JPG");
         final File out = new File(tempFolder, in.getName());
-        ExifGPSTagger.setExifGPSTag(in, out, 12, 34, Instant.now(), 12.34, Math.E, Math.PI, false);
+        ExifGPSTagger.setExifGPSTag(in, out, 12, 34, Instant.now(), 12.34, Math.E, Math.PI, Math.PI, 2, 3, "GPS", 1.2, 2.5, "WGS84", true);
         final Process jhead = Runtime.getRuntime().exec(new String[]{"jhead", out.getAbsolutePath()});
         final String stdout = new Scanner(jhead.getErrorStream()).useDelimiter("\\A").next();
         System.out.println(stdout);
