source: josm/trunk/src/org/openstreetmap/josm/io/rtklib/RtkLibPosReader.java@ 15343

Last change on this file since 15343 was 15343, checked in by Don-vip, 6 years ago

fix #18114 - support short date/time format in RTKLib .pos files

  • Property svn:eol-style set to native
File size: 5.7 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io.rtklib;
3
4import java.io.BufferedReader;
5import java.io.IOException;
6import java.io.InputStream;
7import java.io.InputStreamReader;
8import java.nio.charset.StandardCharsets;
9import java.text.ParseException;
10import java.text.SimpleDateFormat;
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.Collections;
14import java.util.Date;
15import java.util.Locale;
16import java.util.Objects;
17
18import org.openstreetmap.josm.data.coor.LatLon;
19import org.openstreetmap.josm.data.gpx.GpxConstants;
20import org.openstreetmap.josm.data.gpx.GpxData;
21import org.openstreetmap.josm.data.gpx.ImmutableGpxTrack;
22import org.openstreetmap.josm.data.gpx.WayPoint;
23import org.openstreetmap.josm.io.IGpxReader;
24import org.openstreetmap.josm.tools.Logging;
25import org.openstreetmap.josm.tools.date.DateUtils;
26import org.xml.sax.SAXException;
27
28/**
29 * Reads a RTKLib Positioning Solution file.
30 * <p>
31 * See <a href="https://github.com/tomojitakasu/RTKLIB/blob/rtklib_2.4.3/doc/manual_2.4.2.pdf">RTKLIB Manual</a>.
32 * @since 15247
33 */
34public class RtkLibPosReader implements IGpxReader {
35
36 private static final int IDX_DATE = 0;
37 private static final int IDX_TIME = 1;
38 private static final int IDX_LAT = 2;
39 private static final int IDX_LON = 3;
40 private static final int IDX_HEIGHT = 4;
41 private static final int IDX_Q = 5;
42 private static final int IDX_NS = 6;
43 private static final int IDX_SDN = 7;
44 private static final int IDX_SDE = 8;
45 private static final int IDX_SDU = 9;
46 private static final int IDX_SDNE = 10;
47 private static final int IDX_SDEU = 11;
48 private static final int IDX_SDUN = 12;
49 private static final int IDX_AGE = 13;
50 private static final int IDX_RATIO = 14;
51
52 private final SimpleDateFormat dateTimeFmtS = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.ENGLISH); // 2019/06/08 08:23:15
53 private final SimpleDateFormat dateTimeFmtL = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS", Locale.ENGLISH); // 2019/06/08 08:23:15.000
54
55 private final InputStream source;
56 private GpxData data;
57 private int success; // number of successfully parsed lines
58
59 /**
60 * Constructs a new {@code RtkLibPosReader}
61 * @param source RTKLib .pos file input stream
62 * @throws IOException if an I/O error occurs
63 */
64 public RtkLibPosReader(InputStream source) throws IOException {
65 this.source = Objects.requireNonNull(source);
66 dateTimeFmtS.setTimeZone(DateUtils.UTC);
67 dateTimeFmtL.setTimeZone(DateUtils.UTC);
68 }
69
70 private Date parseDate(String date) throws ParseException {
71 return (date.length() > 20 ? dateTimeFmtL : dateTimeFmtS).parse(date);
72 }
73
74 @Override
75 public boolean parse(boolean tryToFinish) throws SAXException, IOException {
76 data = new GpxData();
77 Collection<Collection<WayPoint>> currentTrack = new ArrayList<>();
78 Collection<WayPoint> waypoints = new ArrayList<>();
79 try (BufferedReader rd = new BufferedReader(new InputStreamReader(source, StandardCharsets.UTF_8))) {
80 String line = null;
81 do {
82 line = rd.readLine();
83 if (line != null) {
84 if (line.startsWith("% ref pos :")) {
85 // TODO add marker
86 } else if (!line.startsWith("%")) {
87 try {
88 String[] fields = line.split("[ ]+");
89 WayPoint currentwp = new WayPoint(new LatLon(
90 Double.parseDouble(fields[IDX_LAT]),
91 Double.parseDouble(fields[IDX_LON])));
92 currentwp.put(GpxConstants.PT_ELE, fields[IDX_HEIGHT]);
93 currentwp.setTime(parseDate(fields[IDX_DATE]+" "+fields[IDX_TIME]));
94 currentwp.put(GpxConstants.RTKLIB_Q, Integer.parseInt(fields[IDX_Q]));
95 currentwp.put(GpxConstants.PT_SAT, fields[IDX_NS]);
96 currentwp.put(GpxConstants.RTKLIB_SDN, fields[IDX_SDN]);
97 currentwp.put(GpxConstants.RTKLIB_SDE, fields[IDX_SDE]);
98 currentwp.put(GpxConstants.RTKLIB_SDE, fields[IDX_SDU]);
99 currentwp.put(GpxConstants.RTKLIB_SDNE, fields[IDX_SDNE]);
100 currentwp.put(GpxConstants.RTKLIB_SDEU, fields[IDX_SDEU]);
101 currentwp.put(GpxConstants.RTKLIB_SDUN, fields[IDX_SDUN]);
102 currentwp.put(GpxConstants.RTKLIB_AGE, fields[IDX_AGE]);
103 currentwp.put(GpxConstants.RTKLIB_RATIO, fields[IDX_RATIO]);
104 double sdn = Double.parseDouble(fields[IDX_SDN]);
105 double sde = Double.parseDouble(fields[IDX_SDN]);
106 currentwp.put(GpxConstants.PT_HDOP, (float) Math.sqrt(sdn*sdn + sde*sde));
107 waypoints.add(currentwp);
108 success++;
109 } catch (ParseException | IllegalArgumentException e) {
110 Logging.error(e);
111 }
112 }
113 }
114 } while (line != null);
115 }
116 currentTrack.add(waypoints);
117 data.tracks.add(new ImmutableGpxTrack(currentTrack, Collections.<String, Object>emptyMap()));
118 return true;
119 }
120
121 @Override
122 public GpxData getGpxData() {
123 return data;
124 }
125
126 /**
127 * Returns the number of coordinates that have been successfuly read.
128 * @return the number of coordinates that have been successfuly read
129 */
130 public int getNumberOfCoordinates() {
131 return success;
132 }
133}
Note: See TracBrowser for help on using the repository browser.