Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
.cxx
local.properties
/.idea/
secrets.properties
39 changes: 39 additions & 0 deletions app/src/main/java/com/openpositioning/PositionMe/Traj.java
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
/**
* This class represents the Trajectory data structure generated from the Protocol Buffers definition.
* It contains various sensor data samples and metadata related to a trajectory data collection event.
*
* <p>Key Features:</p>
* <ul>
* <li>Contains optional and repeated fields for various sensor data types such as IMU, PDR, GNSS, WiFi, etc.</li>
* <li>Includes metadata like Android version, start timestamp, and data identifier.</li>
* <li>Supports relative timestamps for sensor data based on the start timestamp.</li>
* <li>Provides information about sensor hardware through Sensor_Info fields.</li>
* </ul>
*
* <p>Field Descriptions:</p>
* <ul>
* <li><code>android_version</code>: The Android version of the device collecting the data.</li>
* <li><code>imu_data</code>: List of motion samples from the IMU (Inertial Measurement Unit).</li>
* <li><code>pdr_data</code>: List of PDR (Pedestrian Dead Reckoning) samples.</li>
* <li><code>position_data</code>: List of position samples.</li>
* <li><code>pressure_data</code>: List of pressure sensor samples.</li>
* <li><code>light_data</code>: List of light sensor samples.</li>
* <li><code>gnss_data</code>: List of GNSS (Global Navigation Satellite System) samples.</li>
* <li><code>wifi_data</code>: List of WiFi samples.</li>
* <li><code>aps_data</code>: List of Access Point (AP) data samples.</li>
* <li><code>start_timestamp</code>: UNIX timestamp (in milliseconds) marking the start of the trajectory data collection.</li>
* <li><code>data_identifier</code>: A unique identifier for the data collection event.</li>
* <li><code>accelerometer_info</code>: Information about the accelerometer sensor.</li>
* <li><code>gyroscope_info</code>: Information about the gyroscope sensor.</li>
* <li><code>rotation_vector_info</code>: Information about the rotation vector sensor.</li>
* <li><code>magnetometer_info</code>: Information about the magnetometer sensor.</li>
* <li><code>barometer_info</code>: Information about the barometer sensor.</li>
* <li><code>light_sensor_info</code>: Information about the light sensor.</li>
* </ul>
*
* <p>Note:</p>
* <ul>
* <li>All timestamps in the sub-classes are relative to the <code>start_timestamp</code>.</li>
* <li>This class is auto-generated and should not be edited manually.</li>
* </ul>
*/
package com.openpositioning.PositionMe;// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: Cloud/app/src/main/proto/traj.proto

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@
import android.hardware.SensorManager;
import android.util.Log;

import com.android.volley.RequestQueue;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.google.android.gms.maps.model.LatLng;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.openpositioning.PositionMe.presentation.fragment.ReplayFragment;
import com.openpositioning.PositionMe.sensors.SensorFusion;
import com.openpositioning.PositionMe.sensors.WiFiPositioning;
import com.android.volley.Request;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
Expand All @@ -19,6 +26,8 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

/**
* Handles parsing of trajectory data stored in JSON files, combining IMU, PDR, and GNSS data
Expand Down Expand Up @@ -46,7 +55,7 @@
*
* @see ReplayFragment which uses parsed trajectory data for visualization.
* @see SensorFusion for motion processing and sensor integration.
* @see com.openpositioning.PositionMe.presentation.fragment.ReplayFragment for implementation details.
* @see ReplayFragment for implementation details.
*
* @author Shu Gu
* @author Lin Cheng
Expand All @@ -55,13 +64,17 @@ public class TrajParser {

private static final String TAG = "TrajParser";

private WiFiPositioning wiFiPositioning;

/**
* Represents a single replay point containing estimated PDR position, GNSS location,
* Represents a single replay point containing estimated PDR position, GNSS location, WiFi location
* orientation, speed, and timestamp.
*/
public static class ReplayPoint {
public LatLng wifiLocation;
public LatLng pdrLocation; // PDR-derived location estimate
public LatLng gnssLocation; // GNSS location (may be null if unavailable)
public LatLng wifiLocation; // WiFi location (may be null if unavailable)
public float orientation; // Orientation in degrees
public float speed; // Speed in meters per second
public long timestamp; // Relative timestamp
Expand All @@ -75,9 +88,10 @@ public static class ReplayPoint {
* @param speed The speed in meters per second.
* @param timestamp The timestamp associated with this point.
*/
public ReplayPoint(LatLng pdrLocation, LatLng gnssLocation, float orientation, float speed, long timestamp) {
public ReplayPoint(LatLng pdrLocation, LatLng gnssLocation, LatLng wifiLocation, float orientation, float speed, long timestamp) {
this.pdrLocation = pdrLocation;
this.gnssLocation = gnssLocation;
this.wifiLocation = wifiLocation;//更改构造函数,添加wifiLocation参数
this.orientation = orientation;
this.speed = speed;
this.timestamp = timestamp;
Expand All @@ -104,6 +118,17 @@ private static class GnssRecord {
public double latitude, longitude; // GNSS coordinates
}

private static class MacScan {
public String mac;
public double rssi;
public int timestamp;
}

private static class WiFiRecord{
public long relativeTimestamp;
public List<MacScan> macScans;
}

/**
* Parses trajectory data from a JSON file and reconstructs a list of replay points.
*
Expand Down Expand Up @@ -184,8 +209,80 @@ public static List<ReplayPoint> parseTrajectoryData(String filePath, Context con
GnssRecord closestGnss = findClosestGnssRecord(gnssList, pdr.relativeTimestamp);
LatLng gnssLocation = closestGnss != null ?
new LatLng(closestGnss.latitude, closestGnss.longitude) : null;
WifiRecord closestWifi = findClosestWifiRecord(wifiList, pdr.relativeTimestamp);
LatLng wifiLocation = closestWifi != null ?
new LatLng(closestWifi.latitude, closestWifi.longitude) : null;

WiFiRecord closestWiFi = findClosestWiFiRecord(WiFiList, pdr.relativeTimestamp);
AtomicReference<LatLng> wifilocation = new AtomicReference<>();
AtomicInteger floor = new AtomicInteger();
try {
// Creating a JSON object to store the WiFi access points
JSONObject wifiAccessPoints = new JSONObject();
for (MacScan scan : closestWiFi.macScans) {
wifiAccessPoints.put(scan.mac, scan.rssi);
}
// Creating POST Request
JSONObject wifiFingerPrint = new JSONObject();
wifiFingerPrint.put("wf", wifiAccessPoints);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
Request.Method.POST, "https://openpositioning.org/api/position/fine", wifiFingerPrint,
// Parses the response to obtain the WiFi location and WiFi floor
response -> {
try {
wifilocation.set(new LatLng(response.getDouble("lat"), response.getDouble("lon")));
floor.set(response.getInt("floor"));
} catch (JSONException e) {
// Error log to keep record of errors (for secure programming and maintainability)
Log.e("jsonErrors", "Error parsing response: " + e.getMessage() + " " + response);
}
// Block return when a message is received
synchronized (TrajParser.class) {
TrajParser.class.notify();
}
},
// Handles the errors obtained from the POST request
error -> {
// Validation Error
if (error.networkResponse != null && error.networkResponse.statusCode == 422) {
Log.e("WiFiPositioning", "Validation Error " + error.getMessage());
}
// Other Errors
else {
// When Response code is available
if (error.networkResponse != null) {
Log.e("WiFiPositioning", "Response Code: " + error.networkResponse.statusCode + ", " + error.getMessage());
} else {
Log.e("WiFiPositioning", "Error message: " + error.getMessage());
}
}
// Block return when an error occurs
synchronized (TrajParser.class) {
TrajParser.class.notify();
}
}
);

// Add the request to the RequestQueue
RequestQueue requestQueue = Volley.newRequestQueue(context);
requestQueue.add(jsonObjectRequest);

} catch (JSONException e) {
// Catching error while making JSON object, to prevent crashes
// Error log to keep record of errors (for secure programming and maintainability)
Log.e("jsonErrors","Error creating json object"+e.toString());
}

// Wait for the response or error to be processed
synchronized (TrajParser.class) {
try {
TrajParser.class.wait(1000); // Sleep for 1 second
} catch (InterruptedException e) {
Log.e(TAG, "Thread interrupted while waiting for WiFi positioning response", e);
}
}

result.add(new ReplayPoint(pdrLocation, gnssLocation, orientationDeg,
result.add(new ReplayPoint(pdrLocation, gnssLocation, wifilocation.get(), orientationDeg,
0f, pdr.relativeTimestamp));
}

Expand Down Expand Up @@ -229,17 +326,31 @@ private static List<GnssRecord> parseGnssData(JsonArray gnssArray) {
gnssList.add(record);
}
return gnssList;
}/** Finds the closest IMU record to the given timestamp. */
}/**
* Finds the closest IMU record to the given timestamp.
*/
private static List<WiFiRecord> parseWiFiData(JsonArray WiFiArray) {
List<WiFiRecord> WiFiList = new ArrayList<>();
if (WiFiArray == null) return WiFiList;
Gson gson = new Gson();
for (int i = 0; i < WiFiArray.size(); i++) {
WiFiRecord record = gson.fromJson(WiFiArray.get(i), WiFiRecord.class);
WiFiList.add(record);
}
return WiFiList;
}
private static ImuRecord findClosestImuRecord(List<ImuRecord> imuList, long targetTimestamp) {
return imuList.stream().min(Comparator.comparingLong(imu -> Math.abs(imu.relativeTimestamp - targetTimestamp)))
.orElse(null);

}/** Finds the closest GNSS record to the given timestamp. */
private static GnssRecord findClosestGnssRecord(List<GnssRecord> gnssList, long targetTimestamp) {
return gnssList.stream().min(Comparator.comparingLong(gnss -> Math.abs(gnss.relativeTimestamp - targetTimestamp)))
.orElse(null);

}/** Computes the orientation from a rotation vector. */
private static WiFiRecord findClosestWiFiRecord(List<WiFiRecord> WiFiList, long targetTimestamp) {
return WiFiList.stream().min(Comparator.comparingLong(wifi -> Math.abs(wifi.relativeTimestamp - targetTimestamp)))
.orElse(null);
}
private static float computeOrientationFromRotationVector(float rx, float ry, float rz, float rw, Context context) {
float[] rotationVector = new float[]{rx, ry, rz, rw};
float[] rotationMatrix = new float[9];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,16 @@ private void updateUIandPosition() {
}
}

// WiFi location example
//sensorFusion.getWifiFloor() // Returns the current floor the user is on using WiFi positioning.
if(trajectoryMapFragment.isWiFiLocationOn()){
LatLng wifiLocation = sensorFusion.getLatLngWifiPositioning(); // Returns the user's position obtained using WiFi positioning.
if(wifiLocation != null) {
trajectoryMapFragment.updateWifiLocation(wifiLocation);
}
}
//sensorFusion.getWifiList() // Returns the most recent list of WiFi names and levels.

// Update previous
previousPosX = pdrValues[0];
previousPosY = pdrValues[1];
Expand Down
Loading