diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..3502bc99 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,22 @@ +# Summary + +One or two line summary of what this PR's changes do, and why you're making them. + +If this closes an issue, include the phrase: Closes (hashtag-issue_number) + +## Details + +- List of key changes made +- Can be functional changes, or non-functional (eg, style, linting, refactoring) + +## Action Items + +- [ ] Test + - [ ] Minimum SDK (Android 9) + - [ ] Latest SDK +- [ ] If there are any other outstanding items to be completed before merging, put them here + - Remember to request at least one code review! (You don't need to list this as an item here, as GitHub will already track code reviews for you) + +> # **NOTICE! Do not merge a pull request if it is not your assigned pull request!** +> +> Do not merge just because you are a code reviewer and you are okay with it. _Only_ merge if you are (one of) the author(s)! diff --git a/.github/workflows/android-16.yml b/.github/workflows/android-16.yml new file mode 100644 index 00000000..3879929c --- /dev/null +++ b/.github/workflows/android-16.yml @@ -0,0 +1,36 @@ +name: Android 16 Build + +on: + push: + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 21.0.3 + uses: actions/setup-java@v4 + with: + java-version: '21.0.3' + distribution: 'jetbrains' + cache: gradle + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v5 + + - name: Add (empty) local.properties + run: touch ./local.properties + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Setup Android 16.0 SDK + uses: android-actions/setup-android@v3.2.2 + with: + cmdline-tools-version: 12266719 + + - name: gradle build + run: ./gradlew --no-daemon --parallel build \ No newline at end of file diff --git a/.github/workflows/android-9.yml b/.github/workflows/android-9.yml new file mode 100644 index 00000000..2312fc09 --- /dev/null +++ b/.github/workflows/android-9.yml @@ -0,0 +1,36 @@ +name: Android 9 Build + +on: + push: + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 21.0.3 + uses: actions/setup-java@v4 + with: + java-version: '21.0.3' + distribution: 'jetbrains' + cache: gradle + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v5 + + - name: Add (empty) local.properties + run: touch ./local.properties + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Setup Android 9.0 SDK + uses: android-actions/setup-android@v3.2.2 + with: + cmdline-tools-version: 9477386 + + - name: gradle build + run: ./gradlew --no-daemon --parallel build \ No newline at end of file diff --git a/.gitignore b/.gitignore index d4c3a57e..a231a4bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,10 @@ *.iml .gradle /local.properties -/.idea/caches -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml -/.idea/navEditor.xml -/.idea/assetWizardSettings.xml .DS_Store /build /captures .externalNativeBuild .cxx -local.properties /.idea/ +**/.vscode/ diff --git a/README.md b/README.md index c4a9f02d..dfb5bd54 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -**PositionMe** is an indoor positioning data collection application initially developed for the University of Edinburgh's Embedded Wireless course. The application now includes enhanced features, including **trajectory playback**, improved UI design, and comprehensive location tracking. +# Embedded Mobile and Wireless Systems (EWireless) 5 2025/26 +## Coursework 2 - Group 13 + +[![Android 9](https://github.com/sa-fx/ENG-EMWSE5/actions/workflows/android-9.yml/badge.svg)](https://github.com/sa-fx/ENG-EMWSE5/actions/workflows/android-9.yml) [![Android 16](https://github.com/sa-fx/ENG-EMWSE5/actions/workflows/android-16.yml/badge.svg)](https://github.com/sa-fx/ENG-EMWSE5/actions/workflows/android-16.yml) + +**PositionMe** is an indoor positioning data collection application initially developed for the [University of Edinburgh's Embedded Wireless course](https://www.drps.ed.ac.uk/25-26/dpt/cxelee11083.htm). The application now includes enhanced features, including **trajectory playback**, improved UI design, and comprehensive location tracking. ## Features @@ -13,19 +18,6 @@ - **Progress bar for tracking playback status**. - **Redesigned UI**: Modern and user-friendly interface for enhanced usability. -## Requirements - -- **Android Studio 4.2** or later -- **Android SDK 30** or later - -## Installation - -1. **Clone the repository.** -2. **Open the project in Android Studio**. -3. Add your own API key for Google Maps in AndroidManifest.xml -4. Set the website where you want to send your data. The application was built for use with [openpositioning.org](http://openpositioning.org/). -5. **Build and run the project on your Android device**. - ## Usage 1. **Install the application** using Android Studio. @@ -43,3 +35,41 @@ 6. **Control playback**: - Pause, restart, or jump to the end using playback controls. +## Requirements + +- **Android Studio 4.2** or later +- **Android SDK 28** or later + +For developers, the latest commits have been tested using the following configuration: +- [Android Studio 2024.2.1 Patch 1 ('Ladybird')](https://developer.android.com/studio/archive) + - Android Gradle Plugin 8.7.3 + - Gradle 8.10.2 + - Google Services 4.4.2 + - [Spotless](https://github.com/diffplug/spotless) 8.3.0 +- Android SDK 28 ('Android 9') + +## Installation + +1. Clone the repository (`git clone`). +2. Open the project in Android Studio. +3. Add your own API keys for Google Maps and OpenPositioning in `secrets.properties`. +4. Build and run the project on your Android device. + +## Build + +This project uses [Spotless](https://github.com/diffplug/spotless) for automatic linting against the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html). To build the project with linting, run: + +```bash +$ chmod +x ./gradlew +$ ./gradlew clean build +``` + +This will run `spotlessCheck` as a pre-requisite for `build`. Any lint errors will cause the build to fail. + +If there are lint errors, you can either resolve these manually or run: + +```bash +$ ./gradlew spotlessApply +``` + +This will use Spotless to let you resolve the errors identified during `spotlessCheck`. diff --git a/app/build.gradle b/app/build.gradle index 3e29b13f..11c12078 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,15 +3,43 @@ plugins { id 'com.google.gms.google-services' id 'androidx.navigation.safeargs' id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin' + id 'com.diffplug.spotless' version "8.3.0" } -// (Optional) load local secrets file: +// Load local secrets file: def localProperties = new Properties() def localPropertiesFile = rootProject.file('secrets.properties') if (localPropertiesFile.exists()) { localProperties.load(new FileInputStream(localPropertiesFile)) } +spotless { + format 'misc', { + // Define the files to apply `misc` to + target '*.gradle', '.gitattributes', '.gitignore' + + // Define the steps to apply to those files + trimTrailingWhitespace() + leadingTabsToSpaces(2) + endWithNewline() + } + java { + // All Java files, except autogenerated Traj.java + target "**/*.java" + targetExclude "**/Traj.java" + + // Checks to be applied (on top of Google's Java style guide) + endWithNewline() + forbidWildcardImports() + formatAnnotations() + leadingTabsToSpaces(2) + removeUnusedImports() + trimTrailingWhitespace() + + googleJavaFormat('1.35.0').aosp().reflowLongStrings() + } +} + android { namespace "com.openpositioning.PositionMe" compileSdk 34 @@ -28,10 +56,11 @@ android { // Example of referencing secrets (if you use secrets.properties): buildConfigField "String", "MAPS_API_KEY", "\"${localProperties['MAPS_API_KEY'] ?: ''}\"" - buildConfigField "String", "OPENPOSITIONING_API_KEY", - "\"${localProperties['OPENPOSITIONING_API_KEY'] ?: ''}\"" buildConfigField "String", "OPENPOSITIONING_MASTER_KEY", "\"${localProperties['OPENPOSITIONING_MASTER_KEY'] ?: ''}\"" + + // Add reference to maps API key for manifest file + manifestPlaceholders = [MAPS_API_KEY:localProperties['MAPS_API_KEY']?:""] } buildFeatures { @@ -55,29 +84,37 @@ android { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } + + // Add lint support (Android linting) + lintOptions { + abortOnError true + baseline file("lint-baseline.xml") + } } dependencies { // Core AndroidX implementation 'androidx.appcompat:appcompat:1.7.0-alpha03' // or stable: 1.6.1 - implementation 'androidx.core:core-ktx:1.12.0' implementation 'androidx.constraintlayout:constraintlayout:2.2.0' - implementation 'androidx.preference:preference:1.2.1' + implementation 'androidx.core:core-ktx:1.12.0' + implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.preference:preference:1.2.1' implementation 'com.android.volley:volley:1.2.1' implementation 'androidx.gridlayout:gridlayout:1.0.0' - // Material Components (Material 3 support is in 1.12.0+) - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.2.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' implementation 'com.google.android.material:material:1.12.0' - implementation 'com.google.protobuf:protobuf-java:3.0.0' - implementation 'com.squareup.okhttp3:okhttp:4.10.0' - implementation "com.google.protobuf:protobuf-java-util:3.0.0" - implementation "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" implementation 'com.google.android.gms:play-services-maps:19.0.0' + implementation 'com.google.android.gms:play-services-location:21.3.0' + implementation "com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" + implementation 'com.google.protobuf:protobuf-java:3.20.1' + implementation "com.google.protobuf:protobuf-java-util:3.20.1" + implementation 'com.squareup.okhttp3:okhttp:4.10.0' + + // Secure credential storage + implementation 'androidx.datastore:datastore-preferences-rxjava3:1.2.1' + implementation "androidx.security:security-crypto:1.1.0" // Navigation components def nav_version = "2.8.6" @@ -88,8 +125,10 @@ dependencies { // implementation "androidx.compose.material3:material3:1.3.1" // implementation "androidx.activity:activity-compose:1.7.2" + implementation "org.ejml:ejml-all:0.38" + // Testing testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' androidTestImplementation 'androidx.test.ext:junit:1.2.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' } diff --git a/app/lint-baseline.xml b/app/lint-baseline.xml new file mode 100644 index 00000000..2429dfc0 --- /dev/null +++ b/app/lint-baseline.xml @@ -0,0 +1,2956 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/androidTest/java/com/openpositioning/PositionMe/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/openpositioning/PositionMe/ExampleInstrumentedTest.java deleted file mode 100644 index ace7cabb..00000000 --- a/app/src/androidTest/java/com/openpositioning/PositionMe/ExampleInstrumentedTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.openpositioning.PositionMe; - -import android.content.Context; - -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import static org.junit.Assert.*; - -/** - * Instrumented test, which will execute on an Android device. - * - * @see Testing documentation - */ -@RunWith(AndroidJUnit4.class) -public class ExampleInstrumentedTest { - @Test - public void useAppContext() { - // Context of the app under test. - Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - assertEquals("com.openpositioning.PositionMe", appContext.getPackageName()); - } -} \ No newline at end of file diff --git a/app/src/androidTest/java/com/openpositioning/PositionMe/TrajectoryMetadataTest.java b/app/src/androidTest/java/com/openpositioning/PositionMe/TrajectoryMetadataTest.java new file mode 100644 index 00000000..bd7f6235 --- /dev/null +++ b/app/src/androidTest/java/com/openpositioning/PositionMe/TrajectoryMetadataTest.java @@ -0,0 +1,57 @@ +package com.openpositioning.PositionMe; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class TrajectoryMetadataTest { + + @Test + public void testTrajectoryIdGeneration() { + String trajectoryId = generateTrajectoryId(); + + assertNotNull("Trajectory ID should not be null", trajectoryId); + assertTrue( + "Trajectory ID should start with 'android_'", trajectoryId.startsWith("android_")); + assertTrue( + "Trajectory ID should contain device model", + trajectoryId.contains(android.os.Build.MODEL.replaceAll("\\s+", "_"))); + assertTrue("Trajectory ID should contain timestamp", trajectoryId.length() > 20); + } + + @Test + public void testTrajectoryVersionIsCorrect() { + Traj.Trajectory.Builder builder = + Traj.Trajectory.newBuilder().setTrajectoryVersion(2.0f).setTrajectoryId("test_id"); + + Traj.Trajectory trajectory = builder.build(); + + assertEquals( + "Trajectory version should be 2.0", + 2.0f, + trajectory.getTrajectoryVersion(), + 0.001f); + } + + @Test + public void testTrajectoryIdUniqueness() { + String id1 = generateTrajectoryId(); + // Small delay to ensure different timestamp + try { + Thread.sleep(10); + } catch (InterruptedException e) { + } + String id2 = generateTrajectoryId(); + + assertNotEquals("Two trajectory IDs should be different", id1, id2); + } + + private String generateTrajectoryId() { + String deviceModel = android.os.Build.MODEL.replaceAll("\\s+", "_"); + long timestamp = System.currentTimeMillis(); + return String.format("android_%s_%d", deviceModel, timestamp); + } +} diff --git a/app/src/androidTest/java/com/openpositioning/PositionMe/sensors/BleDataProcessorTest.java b/app/src/androidTest/java/com/openpositioning/PositionMe/sensors/BleDataProcessorTest.java new file mode 100644 index 00000000..ffede20c --- /dev/null +++ b/app/src/androidTest/java/com/openpositioning/PositionMe/sensors/BleDataProcessorTest.java @@ -0,0 +1,36 @@ +package com.openpositioning.PositionMe.sensors; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class BleDataProcessorTest { + + @Test + public void testBleProcessorInitialisation() { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + BleDataProcessor processor = new BleDataProcessor(context); + assertNotNull("BLE processor should initialise", processor); + } + + @Test + public void testObserverRegistration() { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + BleDataProcessor processor = new BleDataProcessor(context); + + Observer testObserver = + objList -> { + // Test observer + }; + + processor.registerObserver(testObserver); + // If no exception, test passes + assertTrue(true); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 678711fd..54f6a40b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ + xmlns:tools="http://schemas.android.com/tools"> - + + + + + + + + + - - - + @@ -56,6 +57,8 @@ + + + + + android:requestLegacyExternalStorage="true"> - - - + + + + android:screenOrientation="portrait" + tools:ignore="LockedOrientationActivity"> + + + diff --git a/app/src/main/java/com/openpositioning/PositionMe/Traj.java b/app/src/main/java/com/openpositioning/PositionMe/Traj.java index 7925fa55..133e0d84 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/Traj.java +++ b/app/src/main/java/com/openpositioning/PositionMe/Traj.java @@ -1,5 +1,5 @@ package com.openpositioning.PositionMe;// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: Cloud/app/src/main/proto/traj.proto +// source: app/src/main/proto/traj.proto public final class Traj { private Traj() {} @@ -17,205 +17,333 @@ public interface TrajectoryOrBuilder extends com.google.protobuf.MessageOrBuilder { /** - * optional string android_version = 1; + * string android_version = 1; + * @return The androidVersion. */ - String getAndroidVersion(); + java.lang.String getAndroidVersion(); /** - * optional string android_version = 1; + * string android_version = 1; + * @return The bytes for androidVersion. */ com.google.protobuf.ByteString getAndroidVersionBytes(); /** - * repeated .Motion_Sample imu_data = 2; + *
+     * version 2.0
+     * 
+ * + * float trajectory_version = 2; + * @return The trajectoryVersion. + */ + float getTrajectoryVersion(); + + /** + *
+     * trajectory id/name for identification
+     * 
+ * + * string trajectory_id = 3; + * @return The trajectoryId. + */ + java.lang.String getTrajectoryId(); + /** + *
+     * trajectory id/name for identification
+     * 
+ * + * string trajectory_id = 3; + * @return The bytes for trajectoryId. + */ + com.google.protobuf.ByteString + getTrajectoryIdBytes(); + + /** + * repeated .IMUReading imu_data = 4; */ - java.util.List + java.util.List getImuDataList(); /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - Motion_Sample getImuData(int index); + Traj.IMUReading getImuData(int index); /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ int getImuDataCount(); /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - java.util.List + java.util.List getImuDataOrBuilderList(); /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - Motion_SampleOrBuilder getImuDataOrBuilder( + Traj.IMUReadingOrBuilder getImuDataOrBuilder( int index); /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - java.util.List + java.util.List getPdrDataList(); /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - Pdr_Sample getPdrData(int index); + Traj.RelativePosition getPdrData(int index); /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ int getPdrDataCount(); /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - java.util.List + java.util.List getPdrDataOrBuilderList(); /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - Pdr_SampleOrBuilder getPdrDataOrBuilder( + Traj.RelativePositionOrBuilder getPdrDataOrBuilder( int index); /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - java.util.List - getPositionDataList(); + java.util.List + getMagnetometerDataList(); /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - Position_Sample getPositionData(int index); + Traj.MagnetometerReading getMagnetometerData(int index); /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - int getPositionDataCount(); + int getMagnetometerDataCount(); /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - java.util.List - getPositionDataOrBuilderList(); + java.util.List + getMagnetometerDataOrBuilderList(); /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - Position_SampleOrBuilder getPositionDataOrBuilder( + Traj.MagnetometerReadingOrBuilder getMagnetometerDataOrBuilder( int index); /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - java.util.List + java.util.List getPressureDataList(); /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - Pressure_Sample getPressureData(int index); + Traj.BarometerReading getPressureData(int index); /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ int getPressureDataCount(); /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - java.util.List + java.util.List getPressureDataOrBuilderList(); /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - Pressure_SampleOrBuilder getPressureDataOrBuilder( + Traj.BarometerReadingOrBuilder getPressureDataOrBuilder( int index); /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - java.util.List + java.util.List getLightDataList(); /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - Light_Sample getLightData(int index); + Traj.LightReading getLightData(int index); /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ int getLightDataCount(); /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - java.util.List + java.util.List getLightDataOrBuilderList(); /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; + */ + Traj.LightReadingOrBuilder getLightDataOrBuilder( + int index); + + /** + * repeated .ProximityReading proximity_data = 9; + */ + java.util.List + getProximityDataList(); + /** + * repeated .ProximityReading proximity_data = 9; */ - Light_SampleOrBuilder getLightDataOrBuilder( + Traj.ProximityReading getProximityData(int index); + /** + * repeated .ProximityReading proximity_data = 9; + */ + int getProximityDataCount(); + /** + * repeated .ProximityReading proximity_data = 9; + */ + java.util.List + getProximityDataOrBuilderList(); + /** + * repeated .ProximityReading proximity_data = 9; + */ + Traj.ProximityReadingOrBuilder getProximityDataOrBuilder( int index); /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .GNSSReading gnss_data = 10; */ - java.util.List + java.util.List getGnssDataList(); /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .GNSSReading gnss_data = 10; */ - GNSS_Sample getGnssData(int index); + Traj.GNSSReading getGnssData(int index); /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .GNSSReading gnss_data = 10; */ int getGnssDataCount(); /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .GNSSReading gnss_data = 10; */ - java.util.List + java.util.List getGnssDataOrBuilderList(); /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .GNSSReading gnss_data = 10; */ - GNSS_SampleOrBuilder getGnssDataOrBuilder( + Traj.GNSSReadingOrBuilder getGnssDataOrBuilder( int index); /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - java.util.List - getWifiDataList(); + java.util.List + getWifiFingerprintsList(); /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - WiFi_Sample getWifiData(int index); + Traj.Fingerprint getWifiFingerprints(int index); /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - int getWifiDataCount(); + int getWifiFingerprintsCount(); /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - java.util.List - getWifiDataOrBuilderList(); + java.util.List + getWifiFingerprintsOrBuilderList(); /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - WiFi_SampleOrBuilder getWifiDataOrBuilder( + Traj.FingerprintOrBuilder getWifiFingerprintsOrBuilder( int index); /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - java.util.List + java.util.List getApsDataList(); /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - AP_Data getApsData(int index); + Traj.WiFiAPData getApsData(int index); /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ int getApsDataCount(); /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - java.util.List + java.util.List getApsDataOrBuilderList(); /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; + */ + Traj.WiFiAPDataOrBuilder getApsDataOrBuilder( + int index); + + /** + * repeated .WiFiRTTReading wifi_rtt_data = 13; + */ + java.util.List + getWifiRttDataList(); + /** + * repeated .WiFiRTTReading wifi_rtt_data = 13; + */ + Traj.WiFiRTTReading getWifiRttData(int index); + /** + * repeated .WiFiRTTReading wifi_rtt_data = 13; + */ + int getWifiRttDataCount(); + /** + * repeated .WiFiRTTReading wifi_rtt_data = 13; + */ + java.util.List + getWifiRttDataOrBuilderList(); + /** + * repeated .WiFiRTTReading wifi_rtt_data = 13; + */ + Traj.WiFiRTTReadingOrBuilder getWifiRttDataOrBuilder( + int index); + + /** + * repeated .Fingerprint ble_fingerprints = 14; + */ + java.util.List + getBleFingerprintsList(); + /** + * repeated .Fingerprint ble_fingerprints = 14; + */ + Traj.Fingerprint getBleFingerprints(int index); + /** + * repeated .Fingerprint ble_fingerprints = 14; + */ + int getBleFingerprintsCount(); + /** + * repeated .Fingerprint ble_fingerprints = 14; + */ + java.util.List + getBleFingerprintsOrBuilderList(); + /** + * repeated .Fingerprint ble_fingerprints = 14; + */ + Traj.FingerprintOrBuilder getBleFingerprintsOrBuilder( + int index); + + /** + * repeated .BleData ble_data = 15; + */ + java.util.List + getBleDataList(); + /** + * repeated .BleData ble_data = 15; + */ + Traj.BleData getBleData(int index); + /** + * repeated .BleData ble_data = 15; + */ + int getBleDataCount(); + /** + * repeated .BleData ble_data = 15; */ - AP_DataOrBuilder getApsDataOrBuilder( + java.util.List + getBleDataOrBuilderList(); + /** + * repeated .BleData ble_data = 15; + */ + Traj.BleDataOrBuilder getBleDataOrBuilder( int index); /** @@ -229,134 +357,233 @@ AP_DataOrBuilder getApsDataOrBuilder( * relative_timestamp = 3000 (3s) * * - * optional int64 start_timestamp = 10; + * int64 start_timestamp = 16; + * @return The startTimestamp. */ long getStartTimestamp(); /** - * optional string data_identifier = 11; + * .GNSSPosition initial_position = 17; + * @return Whether the initialPosition field is set. */ - String getDataIdentifier(); + boolean hasInitialPosition(); /** - * optional string data_identifier = 11; + * .GNSSPosition initial_position = 17; + * @return The initialPosition. */ - com.google.protobuf.ByteString - getDataIdentifierBytes(); + Traj.GNSSPosition getInitialPosition(); + /** + * .GNSSPosition initial_position = 17; + */ + Traj.GNSSPositionOrBuilder getInitialPositionOrBuilder(); + + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + java.util.List + getCorrectedPositionsList(); + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + Traj.GNSSPosition getCorrectedPositions(int index); + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + int getCorrectedPositionsCount(); + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + java.util.List + getCorrectedPositionsOrBuilderList(); + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + Traj.GNSSPositionOrBuilder getCorrectedPositionsOrBuilder( + int index); /** - * optional .Sensor_Info accelerometer_info = 12; + * .SensorInfo accelerometer_info = 19; + * @return Whether the accelerometerInfo field is set. */ boolean hasAccelerometerInfo(); /** - * optional .Sensor_Info accelerometer_info = 12; + * .SensorInfo accelerometer_info = 19; + * @return The accelerometerInfo. */ - Sensor_Info getAccelerometerInfo(); + Traj.SensorInfo getAccelerometerInfo(); /** - * optional .Sensor_Info accelerometer_info = 12; + * .SensorInfo accelerometer_info = 19; */ - Sensor_InfoOrBuilder getAccelerometerInfoOrBuilder(); + Traj.SensorInfoOrBuilder getAccelerometerInfoOrBuilder(); /** - * optional .Sensor_Info gyroscope_info = 13; + * .SensorInfo gyroscope_info = 20; + * @return Whether the gyroscopeInfo field is set. */ boolean hasGyroscopeInfo(); /** - * optional .Sensor_Info gyroscope_info = 13; + * .SensorInfo gyroscope_info = 20; + * @return The gyroscopeInfo. */ - Sensor_Info getGyroscopeInfo(); + Traj.SensorInfo getGyroscopeInfo(); /** - * optional .Sensor_Info gyroscope_info = 13; + * .SensorInfo gyroscope_info = 20; */ - Sensor_InfoOrBuilder getGyroscopeInfoOrBuilder(); + Traj.SensorInfoOrBuilder getGyroscopeInfoOrBuilder(); /** - * optional .Sensor_Info rotation_vector_info = 14; + * .SensorInfo rotation_vector_info = 21; + * @return Whether the rotationVectorInfo field is set. */ boolean hasRotationVectorInfo(); /** - * optional .Sensor_Info rotation_vector_info = 14; + * .SensorInfo rotation_vector_info = 21; + * @return The rotationVectorInfo. */ - Sensor_Info getRotationVectorInfo(); + Traj.SensorInfo getRotationVectorInfo(); /** - * optional .Sensor_Info rotation_vector_info = 14; + * .SensorInfo rotation_vector_info = 21; */ - Sensor_InfoOrBuilder getRotationVectorInfoOrBuilder(); + Traj.SensorInfoOrBuilder getRotationVectorInfoOrBuilder(); /** - * optional .Sensor_Info magnetometer_info = 15; + * .SensorInfo magnetometer_info = 22; + * @return Whether the magnetometerInfo field is set. */ boolean hasMagnetometerInfo(); /** - * optional .Sensor_Info magnetometer_info = 15; + * .SensorInfo magnetometer_info = 22; + * @return The magnetometerInfo. */ - Sensor_Info getMagnetometerInfo(); + Traj.SensorInfo getMagnetometerInfo(); /** - * optional .Sensor_Info magnetometer_info = 15; + * .SensorInfo magnetometer_info = 22; */ - Sensor_InfoOrBuilder getMagnetometerInfoOrBuilder(); + Traj.SensorInfoOrBuilder getMagnetometerInfoOrBuilder(); /** - * optional .Sensor_Info barometer_info = 16; + * .SensorInfo barometer_info = 23; + * @return Whether the barometerInfo field is set. */ boolean hasBarometerInfo(); /** - * optional .Sensor_Info barometer_info = 16; + * .SensorInfo barometer_info = 23; + * @return The barometerInfo. */ - Sensor_Info getBarometerInfo(); + Traj.SensorInfo getBarometerInfo(); /** - * optional .Sensor_Info barometer_info = 16; + * .SensorInfo barometer_info = 23; */ - Sensor_InfoOrBuilder getBarometerInfoOrBuilder(); + Traj.SensorInfoOrBuilder getBarometerInfoOrBuilder(); /** - * optional .Sensor_Info light_sensor_info = 17; + * .SensorInfo light_sensor_info = 24; + * @return Whether the lightSensorInfo field is set. */ boolean hasLightSensorInfo(); /** - * optional .Sensor_Info light_sensor_info = 17; + * .SensorInfo light_sensor_info = 24; + * @return The lightSensorInfo. + */ + Traj.SensorInfo getLightSensorInfo(); + /** + * .SensorInfo light_sensor_info = 24; + */ + Traj.SensorInfoOrBuilder getLightSensorInfoOrBuilder(); + + /** + * .SensorInfo proximity_info = 25; + * @return Whether the proximityInfo field is set. + */ + boolean hasProximityInfo(); + /** + * .SensorInfo proximity_info = 25; + * @return The proximityInfo. + */ + Traj.SensorInfo getProximityInfo(); + /** + * .SensorInfo proximity_info = 25; + */ + Traj.SensorInfoOrBuilder getProximityInfoOrBuilder(); + + /** + * repeated .GNSSPosition test_points = 26; + */ + java.util.List + getTestPointsList(); + /** + * repeated .GNSSPosition test_points = 26; + */ + Traj.GNSSPosition getTestPoints(int index); + /** + * repeated .GNSSPosition test_points = 26; + */ + int getTestPointsCount(); + /** + * repeated .GNSSPosition test_points = 26; */ - Sensor_Info getLightSensorInfo(); + java.util.List + getTestPointsOrBuilderList(); /** - * optional .Sensor_Info light_sensor_info = 17; + * repeated .GNSSPosition test_points = 26; */ - Sensor_InfoOrBuilder getLightSensorInfoOrBuilder(); + Traj.GNSSPositionOrBuilder getTestPointsOrBuilder( + int index); } /** * Protobuf type {@code Trajectory} */ - public static final class Trajectory extends + public static final class Trajectory extends com.google.protobuf.GeneratedMessageV3 implements // @@protoc_insertion_point(message_implements:Trajectory) TrajectoryOrBuilder { + private static final long serialVersionUID = 0L; // Use Trajectory.newBuilder() to construct. private Trajectory(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } private Trajectory() { androidVersion_ = ""; + trajectoryId_ = ""; imuData_ = java.util.Collections.emptyList(); pdrData_ = java.util.Collections.emptyList(); - positionData_ = java.util.Collections.emptyList(); + magnetometerData_ = java.util.Collections.emptyList(); pressureData_ = java.util.Collections.emptyList(); lightData_ = java.util.Collections.emptyList(); + proximityData_ = java.util.Collections.emptyList(); gnssData_ = java.util.Collections.emptyList(); - wifiData_ = java.util.Collections.emptyList(); + wifiFingerprints_ = java.util.Collections.emptyList(); apsData_ = java.util.Collections.emptyList(); - startTimestamp_ = 0L; - dataIdentifier_ = ""; + wifiRttData_ = java.util.Collections.emptyList(); + bleFingerprints_ = java.util.Collections.emptyList(); + bleData_ = java.util.Collections.emptyList(); + correctedPositions_ = java.util.Collections.emptyList(); + testPoints_ = java.util.Collections.emptyList(); } - @Override + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new Trajectory(); + } + + @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + return this.unknownFields; } private Trajectory( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { @@ -365,107 +592,164 @@ private Trajectory( case 0: done = true; break; - default: { - if (!input.skipField(tag)) { - done = true; - } - break; - } case 10: { - String s = input.readStringRequireUtf8(); + java.lang.String s = input.readStringRequireUtf8(); androidVersion_ = s; break; } - case 18: { - if (!((mutable_bitField0_ & 0x00000002) == 0x00000002)) { - imuData_ = new java.util.ArrayList(); - mutable_bitField0_ |= 0x00000002; + case 21: { + + trajectoryVersion_ = input.readFloat(); + break; + } + case 26: { + java.lang.String s = input.readStringRequireUtf8(); + + trajectoryId_ = s; + break; + } + case 34: { + if (!((mutable_bitField0_ & 0x00000001) != 0)) { + imuData_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000001; } imuData_.add( - input.readMessage(Motion_Sample.parser(), extensionRegistry)); + input.readMessage(Traj.IMUReading.parser(), extensionRegistry)); break; } - case 26: { - if (!((mutable_bitField0_ & 0x00000004) == 0x00000004)) { - pdrData_ = new java.util.ArrayList(); - mutable_bitField0_ |= 0x00000004; + case 42: { + if (!((mutable_bitField0_ & 0x00000002) != 0)) { + pdrData_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000002; } pdrData_.add( - input.readMessage(Pdr_Sample.parser(), extensionRegistry)); + input.readMessage(Traj.RelativePosition.parser(), extensionRegistry)); break; } - case 34: { - if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) { - positionData_ = new java.util.ArrayList(); + case 50: { + if (!((mutable_bitField0_ & 0x00000004) != 0)) { + magnetometerData_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000004; + } + magnetometerData_.add( + input.readMessage(Traj.MagnetometerReading.parser(), extensionRegistry)); + break; + } + case 58: { + if (!((mutable_bitField0_ & 0x00000008) != 0)) { + pressureData_ = new java.util.ArrayList(); mutable_bitField0_ |= 0x00000008; } - positionData_.add( - input.readMessage(Position_Sample.parser(), extensionRegistry)); + pressureData_.add( + input.readMessage(Traj.BarometerReading.parser(), extensionRegistry)); break; } - case 42: { - if (!((mutable_bitField0_ & 0x00000010) == 0x00000010)) { - pressureData_ = new java.util.ArrayList(); + case 66: { + if (!((mutable_bitField0_ & 0x00000010) != 0)) { + lightData_ = new java.util.ArrayList(); mutable_bitField0_ |= 0x00000010; } - pressureData_.add( - input.readMessage(Pressure_Sample.parser(), extensionRegistry)); + lightData_.add( + input.readMessage(Traj.LightReading.parser(), extensionRegistry)); break; } - case 50: { - if (!((mutable_bitField0_ & 0x00000020) == 0x00000020)) { - lightData_ = new java.util.ArrayList(); + case 74: { + if (!((mutable_bitField0_ & 0x00000020) != 0)) { + proximityData_ = new java.util.ArrayList(); mutable_bitField0_ |= 0x00000020; } - lightData_.add( - input.readMessage(Light_Sample.parser(), extensionRegistry)); + proximityData_.add( + input.readMessage(Traj.ProximityReading.parser(), extensionRegistry)); break; } - case 58: { - if (!((mutable_bitField0_ & 0x00000040) == 0x00000040)) { - gnssData_ = new java.util.ArrayList(); + case 82: { + if (!((mutable_bitField0_ & 0x00000040) != 0)) { + gnssData_ = new java.util.ArrayList(); mutable_bitField0_ |= 0x00000040; } gnssData_.add( - input.readMessage(GNSS_Sample.parser(), extensionRegistry)); + input.readMessage(Traj.GNSSReading.parser(), extensionRegistry)); break; } - case 66: { - if (!((mutable_bitField0_ & 0x00000080) == 0x00000080)) { - wifiData_ = new java.util.ArrayList(); + case 90: { + if (!((mutable_bitField0_ & 0x00000080) != 0)) { + wifiFingerprints_ = new java.util.ArrayList(); mutable_bitField0_ |= 0x00000080; } - wifiData_.add( - input.readMessage(WiFi_Sample.parser(), extensionRegistry)); + wifiFingerprints_.add( + input.readMessage(Traj.Fingerprint.parser(), extensionRegistry)); break; } - case 74: { - if (!((mutable_bitField0_ & 0x00000100) == 0x00000100)) { - apsData_ = new java.util.ArrayList(); + case 98: { + if (!((mutable_bitField0_ & 0x00000100) != 0)) { + apsData_ = new java.util.ArrayList(); mutable_bitField0_ |= 0x00000100; } apsData_.add( - input.readMessage(AP_Data.parser(), extensionRegistry)); + input.readMessage(Traj.WiFiAPData.parser(), extensionRegistry)); + break; + } + case 106: { + if (!((mutable_bitField0_ & 0x00000200) != 0)) { + wifiRttData_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000200; + } + wifiRttData_.add( + input.readMessage(Traj.WiFiRTTReading.parser(), extensionRegistry)); + break; + } + case 114: { + if (!((mutable_bitField0_ & 0x00000400) != 0)) { + bleFingerprints_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000400; + } + bleFingerprints_.add( + input.readMessage(Traj.Fingerprint.parser(), extensionRegistry)); + break; + } + case 122: { + if (!((mutable_bitField0_ & 0x00000800) != 0)) { + bleData_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000800; + } + bleData_.add( + input.readMessage(Traj.BleData.parser(), extensionRegistry)); break; } - case 80: { + case 128: { startTimestamp_ = input.readInt64(); break; } - case 90: { - String s = input.readStringRequireUtf8(); + case 138: { + Traj.GNSSPosition.Builder subBuilder = null; + if (initialPosition_ != null) { + subBuilder = initialPosition_.toBuilder(); + } + initialPosition_ = input.readMessage(Traj.GNSSPosition.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(initialPosition_); + initialPosition_ = subBuilder.buildPartial(); + } - dataIdentifier_ = s; break; } - case 98: { - Sensor_Info.Builder subBuilder = null; + case 146: { + if (!((mutable_bitField0_ & 0x00001000) != 0)) { + correctedPositions_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00001000; + } + correctedPositions_.add( + input.readMessage(Traj.GNSSPosition.parser(), extensionRegistry)); + break; + } + case 154: { + Traj.SensorInfo.Builder subBuilder = null; if (accelerometerInfo_ != null) { subBuilder = accelerometerInfo_.toBuilder(); } - accelerometerInfo_ = input.readMessage(Sensor_Info.parser(), extensionRegistry); + accelerometerInfo_ = input.readMessage(Traj.SensorInfo.parser(), extensionRegistry); if (subBuilder != null) { subBuilder.mergeFrom(accelerometerInfo_); accelerometerInfo_ = subBuilder.buildPartial(); @@ -473,12 +757,12 @@ private Trajectory( break; } - case 106: { - Sensor_Info.Builder subBuilder = null; + case 162: { + Traj.SensorInfo.Builder subBuilder = null; if (gyroscopeInfo_ != null) { subBuilder = gyroscopeInfo_.toBuilder(); } - gyroscopeInfo_ = input.readMessage(Sensor_Info.parser(), extensionRegistry); + gyroscopeInfo_ = input.readMessage(Traj.SensorInfo.parser(), extensionRegistry); if (subBuilder != null) { subBuilder.mergeFrom(gyroscopeInfo_); gyroscopeInfo_ = subBuilder.buildPartial(); @@ -486,12 +770,12 @@ private Trajectory( break; } - case 114: { - Sensor_Info.Builder subBuilder = null; + case 170: { + Traj.SensorInfo.Builder subBuilder = null; if (rotationVectorInfo_ != null) { subBuilder = rotationVectorInfo_.toBuilder(); } - rotationVectorInfo_ = input.readMessage(Sensor_Info.parser(), extensionRegistry); + rotationVectorInfo_ = input.readMessage(Traj.SensorInfo.parser(), extensionRegistry); if (subBuilder != null) { subBuilder.mergeFrom(rotationVectorInfo_); rotationVectorInfo_ = subBuilder.buildPartial(); @@ -499,12 +783,12 @@ private Trajectory( break; } - case 122: { - Sensor_Info.Builder subBuilder = null; + case 178: { + Traj.SensorInfo.Builder subBuilder = null; if (magnetometerInfo_ != null) { subBuilder = magnetometerInfo_.toBuilder(); } - magnetometerInfo_ = input.readMessage(Sensor_Info.parser(), extensionRegistry); + magnetometerInfo_ = input.readMessage(Traj.SensorInfo.parser(), extensionRegistry); if (subBuilder != null) { subBuilder.mergeFrom(magnetometerInfo_); magnetometerInfo_ = subBuilder.buildPartial(); @@ -512,12 +796,12 @@ private Trajectory( break; } - case 130: { - Sensor_Info.Builder subBuilder = null; + case 186: { + Traj.SensorInfo.Builder subBuilder = null; if (barometerInfo_ != null) { subBuilder = barometerInfo_.toBuilder(); } - barometerInfo_ = input.readMessage(Sensor_Info.parser(), extensionRegistry); + barometerInfo_ = input.readMessage(Traj.SensorInfo.parser(), extensionRegistry); if (subBuilder != null) { subBuilder.mergeFrom(barometerInfo_); barometerInfo_ = subBuilder.buildPartial(); @@ -525,12 +809,12 @@ private Trajectory( break; } - case 138: { - Sensor_Info.Builder subBuilder = null; + case 194: { + Traj.SensorInfo.Builder subBuilder = null; if (lightSensorInfo_ != null) { subBuilder = lightSensorInfo_.toBuilder(); } - lightSensorInfo_ = input.readMessage(Sensor_Info.parser(), extensionRegistry); + lightSensorInfo_ = input.readMessage(Traj.SensorInfo.parser(), extensionRegistry); if (subBuilder != null) { subBuilder.mergeFrom(lightSensorInfo_); lightSensorInfo_ = subBuilder.buildPartial(); @@ -538,38 +822,88 @@ private Trajectory( break; } + case 202: { + Traj.SensorInfo.Builder subBuilder = null; + if (proximityInfo_ != null) { + subBuilder = proximityInfo_.toBuilder(); + } + proximityInfo_ = input.readMessage(Traj.SensorInfo.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(proximityInfo_); + proximityInfo_ = subBuilder.buildPartial(); + } + + break; + } + case 210: { + if (!((mutable_bitField0_ & 0x00002000) != 0)) { + testPoints_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00002000; + } + testPoints_.add( + input.readMessage(Traj.GNSSPosition.parser(), extensionRegistry)); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { - if (((mutable_bitField0_ & 0x00000002) == 0x00000002)) { + if (((mutable_bitField0_ & 0x00000001) != 0)) { imuData_ = java.util.Collections.unmodifiableList(imuData_); } - if (((mutable_bitField0_ & 0x00000004) == 0x00000004)) { + if (((mutable_bitField0_ & 0x00000002) != 0)) { pdrData_ = java.util.Collections.unmodifiableList(pdrData_); } - if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) { - positionData_ = java.util.Collections.unmodifiableList(positionData_); + if (((mutable_bitField0_ & 0x00000004) != 0)) { + magnetometerData_ = java.util.Collections.unmodifiableList(magnetometerData_); } - if (((mutable_bitField0_ & 0x00000010) == 0x00000010)) { + if (((mutable_bitField0_ & 0x00000008) != 0)) { pressureData_ = java.util.Collections.unmodifiableList(pressureData_); } - if (((mutable_bitField0_ & 0x00000020) == 0x00000020)) { + if (((mutable_bitField0_ & 0x00000010) != 0)) { lightData_ = java.util.Collections.unmodifiableList(lightData_); } - if (((mutable_bitField0_ & 0x00000040) == 0x00000040)) { + if (((mutable_bitField0_ & 0x00000020) != 0)) { + proximityData_ = java.util.Collections.unmodifiableList(proximityData_); + } + if (((mutable_bitField0_ & 0x00000040) != 0)) { gnssData_ = java.util.Collections.unmodifiableList(gnssData_); } - if (((mutable_bitField0_ & 0x00000080) == 0x00000080)) { - wifiData_ = java.util.Collections.unmodifiableList(wifiData_); + if (((mutable_bitField0_ & 0x00000080) != 0)) { + wifiFingerprints_ = java.util.Collections.unmodifiableList(wifiFingerprints_); } - if (((mutable_bitField0_ & 0x00000100) == 0x00000100)) { + if (((mutable_bitField0_ & 0x00000100) != 0)) { apsData_ = java.util.Collections.unmodifiableList(apsData_); } + if (((mutable_bitField0_ & 0x00000200) != 0)) { + wifiRttData_ = java.util.Collections.unmodifiableList(wifiRttData_); + } + if (((mutable_bitField0_ & 0x00000400) != 0)) { + bleFingerprints_ = java.util.Collections.unmodifiableList(bleFingerprints_); + } + if (((mutable_bitField0_ & 0x00000800) != 0)) { + bleData_ = java.util.Collections.unmodifiableList(bleData_); + } + if (((mutable_bitField0_ & 0x00001000) != 0)) { + correctedPositions_ = java.util.Collections.unmodifiableList(correctedPositions_); + } + if (((mutable_bitField0_ & 0x00002000) != 0)) { + testPoints_ = java.util.Collections.unmodifiableList(testPoints_); + } + this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } @@ -578,41 +912,45 @@ private Trajectory( return Traj.internal_static_Trajectory_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { return Traj.internal_static_Trajectory_fieldAccessorTable .ensureFieldAccessorsInitialized( - Trajectory.class, Builder.class); + Traj.Trajectory.class, Traj.Trajectory.Builder.class); } - private int bitField0_; public static final int ANDROID_VERSION_FIELD_NUMBER = 1; - private volatile Object androidVersion_; + private volatile java.lang.Object androidVersion_; /** - * optional string android_version = 1; + * string android_version = 1; + * @return The androidVersion. */ - public String getAndroidVersion() { - Object ref = androidVersion_; - if (ref instanceof String) { - return (String) ref; + @java.lang.Override + public java.lang.String getAndroidVersion() { + java.lang.Object ref = androidVersion_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); + java.lang.String s = bs.toStringUtf8(); androidVersion_ = s; return s; } } /** - * optional string android_version = 1; + * string android_version = 1; + * @return The bytes for androidVersion. */ + @java.lang.Override public com.google.protobuf.ByteString getAndroidVersionBytes() { - Object ref = androidVersion_; - if (ref instanceof String) { + java.lang.Object ref = androidVersion_; + if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); + (java.lang.String) ref); androidVersion_ = b; return b; } else { @@ -620,466 +958,858 @@ public String getAndroidVersion() { } } - public static final int IMU_DATA_FIELD_NUMBER = 2; - private java.util.List imuData_; + public static final int TRAJECTORY_VERSION_FIELD_NUMBER = 2; + private float trajectoryVersion_; + /** + *
+     * version 2.0
+     * 
+ * + * float trajectory_version = 2; + * @return The trajectoryVersion. + */ + @java.lang.Override + public float getTrajectoryVersion() { + return trajectoryVersion_; + } + + public static final int TRAJECTORY_ID_FIELD_NUMBER = 3; + private volatile java.lang.Object trajectoryId_; + /** + *
+     * trajectory id/name for identification
+     * 
+ * + * string trajectory_id = 3; + * @return The trajectoryId. + */ + @java.lang.Override + public java.lang.String getTrajectoryId() { + java.lang.Object ref = trajectoryId_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + trajectoryId_ = s; + return s; + } + } + /** + *
+     * trajectory id/name for identification
+     * 
+ * + * string trajectory_id = 3; + * @return The bytes for trajectoryId. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getTrajectoryIdBytes() { + java.lang.Object ref = trajectoryId_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + trajectoryId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int IMU_DATA_FIELD_NUMBER = 4; + private java.util.List imuData_; /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public java.util.List getImuDataList() { + @java.lang.Override + public java.util.List getImuDataList() { return imuData_; } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public java.util.List + @java.lang.Override + public java.util.List getImuDataOrBuilderList() { return imuData_; } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ + @java.lang.Override public int getImuDataCount() { return imuData_.size(); } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public Motion_Sample getImuData(int index) { + @java.lang.Override + public Traj.IMUReading getImuData(int index) { return imuData_.get(index); } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public Motion_SampleOrBuilder getImuDataOrBuilder( + @java.lang.Override + public Traj.IMUReadingOrBuilder getImuDataOrBuilder( int index) { return imuData_.get(index); } - public static final int PDR_DATA_FIELD_NUMBER = 3; - private java.util.List pdrData_; + public static final int PDR_DATA_FIELD_NUMBER = 5; + private java.util.List pdrData_; /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public java.util.List getPdrDataList() { + @java.lang.Override + public java.util.List getPdrDataList() { return pdrData_; } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public java.util.List + @java.lang.Override + public java.util.List getPdrDataOrBuilderList() { return pdrData_; } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ + @java.lang.Override public int getPdrDataCount() { return pdrData_.size(); } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public Pdr_Sample getPdrData(int index) { + @java.lang.Override + public Traj.RelativePosition getPdrData(int index) { return pdrData_.get(index); } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public Pdr_SampleOrBuilder getPdrDataOrBuilder( + @java.lang.Override + public Traj.RelativePositionOrBuilder getPdrDataOrBuilder( int index) { return pdrData_.get(index); } - public static final int POSITION_DATA_FIELD_NUMBER = 4; - private java.util.List positionData_; + public static final int MAGNETOMETER_DATA_FIELD_NUMBER = 6; + private java.util.List magnetometerData_; /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public java.util.List getPositionDataList() { - return positionData_; + @java.lang.Override + public java.util.List getMagnetometerDataList() { + return magnetometerData_; } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public java.util.List - getPositionDataOrBuilderList() { - return positionData_; + @java.lang.Override + public java.util.List + getMagnetometerDataOrBuilderList() { + return magnetometerData_; } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public int getPositionDataCount() { - return positionData_.size(); + @java.lang.Override + public int getMagnetometerDataCount() { + return magnetometerData_.size(); } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Position_Sample getPositionData(int index) { - return positionData_.get(index); + @java.lang.Override + public Traj.MagnetometerReading getMagnetometerData(int index) { + return magnetometerData_.get(index); } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Position_SampleOrBuilder getPositionDataOrBuilder( + @java.lang.Override + public Traj.MagnetometerReadingOrBuilder getMagnetometerDataOrBuilder( int index) { - return positionData_.get(index); + return magnetometerData_.get(index); } - public static final int PRESSURE_DATA_FIELD_NUMBER = 5; - private java.util.List pressureData_; + public static final int PRESSURE_DATA_FIELD_NUMBER = 7; + private java.util.List pressureData_; /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public java.util.List getPressureDataList() { + @java.lang.Override + public java.util.List getPressureDataList() { return pressureData_; } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public java.util.List + @java.lang.Override + public java.util.List getPressureDataOrBuilderList() { return pressureData_; } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ + @java.lang.Override public int getPressureDataCount() { return pressureData_.size(); } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public Pressure_Sample getPressureData(int index) { + @java.lang.Override + public Traj.BarometerReading getPressureData(int index) { return pressureData_.get(index); } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public Pressure_SampleOrBuilder getPressureDataOrBuilder( + @java.lang.Override + public Traj.BarometerReadingOrBuilder getPressureDataOrBuilder( int index) { return pressureData_.get(index); } - public static final int LIGHT_DATA_FIELD_NUMBER = 6; - private java.util.List lightData_; + public static final int LIGHT_DATA_FIELD_NUMBER = 8; + private java.util.List lightData_; /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public java.util.List getLightDataList() { + @java.lang.Override + public java.util.List getLightDataList() { return lightData_; } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public java.util.List + @java.lang.Override + public java.util.List getLightDataOrBuilderList() { return lightData_; } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ + @java.lang.Override public int getLightDataCount() { return lightData_.size(); } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public Light_Sample getLightData(int index) { + @java.lang.Override + public Traj.LightReading getLightData(int index) { return lightData_.get(index); } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public Light_SampleOrBuilder getLightDataOrBuilder( + @java.lang.Override + public Traj.LightReadingOrBuilder getLightDataOrBuilder( int index) { return lightData_.get(index); } - public static final int GNSS_DATA_FIELD_NUMBER = 7; - private java.util.List gnssData_; + public static final int PROXIMITY_DATA_FIELD_NUMBER = 9; + private java.util.List proximityData_; + /** + * repeated .ProximityReading proximity_data = 9; + */ + @java.lang.Override + public java.util.List getProximityDataList() { + return proximityData_; + } + /** + * repeated .ProximityReading proximity_data = 9; + */ + @java.lang.Override + public java.util.List + getProximityDataOrBuilderList() { + return proximityData_; + } + /** + * repeated .ProximityReading proximity_data = 9; + */ + @java.lang.Override + public int getProximityDataCount() { + return proximityData_.size(); + } + /** + * repeated .ProximityReading proximity_data = 9; + */ + @java.lang.Override + public Traj.ProximityReading getProximityData(int index) { + return proximityData_.get(index); + } + /** + * repeated .ProximityReading proximity_data = 9; + */ + @java.lang.Override + public Traj.ProximityReadingOrBuilder getProximityDataOrBuilder( + int index) { + return proximityData_.get(index); + } + + public static final int GNSS_DATA_FIELD_NUMBER = 10; + private java.util.List gnssData_; /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .GNSSReading gnss_data = 10; */ - public java.util.List getGnssDataList() { + @java.lang.Override + public java.util.List getGnssDataList() { return gnssData_; } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .GNSSReading gnss_data = 10; */ - public java.util.List + @java.lang.Override + public java.util.List getGnssDataOrBuilderList() { return gnssData_; } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .GNSSReading gnss_data = 10; */ + @java.lang.Override public int getGnssDataCount() { return gnssData_.size(); } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .GNSSReading gnss_data = 10; */ - public GNSS_Sample getGnssData(int index) { + @java.lang.Override + public Traj.GNSSReading getGnssData(int index) { return gnssData_.get(index); } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .GNSSReading gnss_data = 10; */ - public GNSS_SampleOrBuilder getGnssDataOrBuilder( + @java.lang.Override + public Traj.GNSSReadingOrBuilder getGnssDataOrBuilder( int index) { return gnssData_.get(index); } - public static final int WIFI_DATA_FIELD_NUMBER = 8; - private java.util.List wifiData_; + public static final int WIFI_FINGERPRINTS_FIELD_NUMBER = 11; + private java.util.List wifiFingerprints_; /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public java.util.List getWifiDataList() { - return wifiData_; + @java.lang.Override + public java.util.List getWifiFingerprintsList() { + return wifiFingerprints_; } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public java.util.List - getWifiDataOrBuilderList() { - return wifiData_; + @java.lang.Override + public java.util.List + getWifiFingerprintsOrBuilderList() { + return wifiFingerprints_; } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public int getWifiDataCount() { - return wifiData_.size(); + @java.lang.Override + public int getWifiFingerprintsCount() { + return wifiFingerprints_.size(); } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public WiFi_Sample getWifiData(int index) { - return wifiData_.get(index); + @java.lang.Override + public Traj.Fingerprint getWifiFingerprints(int index) { + return wifiFingerprints_.get(index); } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public WiFi_SampleOrBuilder getWifiDataOrBuilder( + @java.lang.Override + public Traj.FingerprintOrBuilder getWifiFingerprintsOrBuilder( int index) { - return wifiData_.get(index); + return wifiFingerprints_.get(index); } - public static final int APS_DATA_FIELD_NUMBER = 9; - private java.util.List apsData_; + public static final int APS_DATA_FIELD_NUMBER = 12; + private java.util.List apsData_; /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public java.util.List getApsDataList() { + @java.lang.Override + public java.util.List getApsDataList() { return apsData_; } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public java.util.List + @java.lang.Override + public java.util.List getApsDataOrBuilderList() { return apsData_; } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ + @java.lang.Override public int getApsDataCount() { return apsData_.size(); } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public AP_Data getApsData(int index) { + @java.lang.Override + public Traj.WiFiAPData getApsData(int index) { return apsData_.get(index); } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public AP_DataOrBuilder getApsDataOrBuilder( + @java.lang.Override + public Traj.WiFiAPDataOrBuilder getApsDataOrBuilder( int index) { return apsData_.get(index); } - public static final int START_TIMESTAMP_FIELD_NUMBER = 10; - private long startTimestamp_; + public static final int WIFI_RTT_DATA_FIELD_NUMBER = 13; + private java.util.List wifiRttData_; /** - *
-     * UNIX timestamp (in milliseconds) recorded from the start of this
-     * trajectory data collection event. All future
-     * timestamps in sub classes are to be RELATIVE timestamps
-     * (in milliseconds) to this start time.
-     * E.g.
-     * start_timestamp = 1674819807315 (UTC 27 Jan 2023 in the morning)
-     * relative_timestamp = 3000 (3s)
-     * 
- * - * optional int64 start_timestamp = 10; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public long getStartTimestamp() { - return startTimestamp_; + @java.lang.Override + public java.util.List getWifiRttDataList() { + return wifiRttData_; } - - public static final int DATA_IDENTIFIER_FIELD_NUMBER = 11; - private volatile Object dataIdentifier_; /** - * optional string data_identifier = 11; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public String getDataIdentifier() { - Object ref = dataIdentifier_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - dataIdentifier_ = s; - return s; - } + @java.lang.Override + public java.util.List + getWifiRttDataOrBuilderList() { + return wifiRttData_; } /** - * optional string data_identifier = 11; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public com.google.protobuf.ByteString - getDataIdentifierBytes() { - Object ref = dataIdentifier_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - dataIdentifier_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } + @java.lang.Override + public int getWifiRttDataCount() { + return wifiRttData_.size(); + } + /** + * repeated .WiFiRTTReading wifi_rtt_data = 13; + */ + @java.lang.Override + public Traj.WiFiRTTReading getWifiRttData(int index) { + return wifiRttData_.get(index); + } + /** + * repeated .WiFiRTTReading wifi_rtt_data = 13; + */ + @java.lang.Override + public Traj.WiFiRTTReadingOrBuilder getWifiRttDataOrBuilder( + int index) { + return wifiRttData_.get(index); + } + + public static final int BLE_FINGERPRINTS_FIELD_NUMBER = 14; + private java.util.List bleFingerprints_; + /** + * repeated .Fingerprint ble_fingerprints = 14; + */ + @java.lang.Override + public java.util.List getBleFingerprintsList() { + return bleFingerprints_; + } + /** + * repeated .Fingerprint ble_fingerprints = 14; + */ + @java.lang.Override + public java.util.List + getBleFingerprintsOrBuilderList() { + return bleFingerprints_; + } + /** + * repeated .Fingerprint ble_fingerprints = 14; + */ + @java.lang.Override + public int getBleFingerprintsCount() { + return bleFingerprints_.size(); + } + /** + * repeated .Fingerprint ble_fingerprints = 14; + */ + @java.lang.Override + public Traj.Fingerprint getBleFingerprints(int index) { + return bleFingerprints_.get(index); + } + /** + * repeated .Fingerprint ble_fingerprints = 14; + */ + @java.lang.Override + public Traj.FingerprintOrBuilder getBleFingerprintsOrBuilder( + int index) { + return bleFingerprints_.get(index); + } + + public static final int BLE_DATA_FIELD_NUMBER = 15; + private java.util.List bleData_; + /** + * repeated .BleData ble_data = 15; + */ + @java.lang.Override + public java.util.List getBleDataList() { + return bleData_; + } + /** + * repeated .BleData ble_data = 15; + */ + @java.lang.Override + public java.util.List + getBleDataOrBuilderList() { + return bleData_; + } + /** + * repeated .BleData ble_data = 15; + */ + @java.lang.Override + public int getBleDataCount() { + return bleData_.size(); + } + /** + * repeated .BleData ble_data = 15; + */ + @java.lang.Override + public Traj.BleData getBleData(int index) { + return bleData_.get(index); + } + /** + * repeated .BleData ble_data = 15; + */ + @java.lang.Override + public Traj.BleDataOrBuilder getBleDataOrBuilder( + int index) { + return bleData_.get(index); + } + + public static final int START_TIMESTAMP_FIELD_NUMBER = 16; + private long startTimestamp_; + /** + *
+     * UNIX timestamp (in milliseconds) recorded from the start of this
+     * trajectory data collection event. All future
+     * timestamps in sub classes are to be RELATIVE timestamps
+     * (in milliseconds) to this start time.
+     * E.g.
+     * start_timestamp = 1674819807315 (UTC 27 Jan 2023 in the morning)
+     * relative_timestamp = 3000 (3s)
+     * 
+ * + * int64 start_timestamp = 16; + * @return The startTimestamp. + */ + @java.lang.Override + public long getStartTimestamp() { + return startTimestamp_; + } + + public static final int INITIAL_POSITION_FIELD_NUMBER = 17; + private Traj.GNSSPosition initialPosition_; + /** + * .GNSSPosition initial_position = 17; + * @return Whether the initialPosition field is set. + */ + @java.lang.Override + public boolean hasInitialPosition() { + return initialPosition_ != null; + } + /** + * .GNSSPosition initial_position = 17; + * @return The initialPosition. + */ + @java.lang.Override + public Traj.GNSSPosition getInitialPosition() { + return initialPosition_ == null ? Traj.GNSSPosition.getDefaultInstance() : initialPosition_; + } + /** + * .GNSSPosition initial_position = 17; + */ + @java.lang.Override + public Traj.GNSSPositionOrBuilder getInitialPositionOrBuilder() { + return getInitialPosition(); + } + + public static final int CORRECTED_POSITIONS_FIELD_NUMBER = 18; + private java.util.List correctedPositions_; + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + @java.lang.Override + public java.util.List getCorrectedPositionsList() { + return correctedPositions_; + } + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + @java.lang.Override + public java.util.List + getCorrectedPositionsOrBuilderList() { + return correctedPositions_; + } + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + @java.lang.Override + public int getCorrectedPositionsCount() { + return correctedPositions_.size(); + } + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + @java.lang.Override + public Traj.GNSSPosition getCorrectedPositions(int index) { + return correctedPositions_.get(index); + } + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + @java.lang.Override + public Traj.GNSSPositionOrBuilder getCorrectedPositionsOrBuilder( + int index) { + return correctedPositions_.get(index); } - public static final int ACCELEROMETER_INFO_FIELD_NUMBER = 12; - private Sensor_Info accelerometerInfo_; + public static final int ACCELEROMETER_INFO_FIELD_NUMBER = 19; + private Traj.SensorInfo accelerometerInfo_; /** - * optional .Sensor_Info accelerometer_info = 12; + * .SensorInfo accelerometer_info = 19; + * @return Whether the accelerometerInfo field is set. */ + @java.lang.Override public boolean hasAccelerometerInfo() { return accelerometerInfo_ != null; } /** - * optional .Sensor_Info accelerometer_info = 12; + * .SensorInfo accelerometer_info = 19; + * @return The accelerometerInfo. */ - public Sensor_Info getAccelerometerInfo() { - return accelerometerInfo_ == null ? Sensor_Info.getDefaultInstance() : accelerometerInfo_; + @java.lang.Override + public Traj.SensorInfo getAccelerometerInfo() { + return accelerometerInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : accelerometerInfo_; } /** - * optional .Sensor_Info accelerometer_info = 12; + * .SensorInfo accelerometer_info = 19; */ - public Sensor_InfoOrBuilder getAccelerometerInfoOrBuilder() { + @java.lang.Override + public Traj.SensorInfoOrBuilder getAccelerometerInfoOrBuilder() { return getAccelerometerInfo(); } - public static final int GYROSCOPE_INFO_FIELD_NUMBER = 13; - private Sensor_Info gyroscopeInfo_; + public static final int GYROSCOPE_INFO_FIELD_NUMBER = 20; + private Traj.SensorInfo gyroscopeInfo_; /** - * optional .Sensor_Info gyroscope_info = 13; + * .SensorInfo gyroscope_info = 20; + * @return Whether the gyroscopeInfo field is set. */ + @java.lang.Override public boolean hasGyroscopeInfo() { return gyroscopeInfo_ != null; } /** - * optional .Sensor_Info gyroscope_info = 13; + * .SensorInfo gyroscope_info = 20; + * @return The gyroscopeInfo. */ - public Sensor_Info getGyroscopeInfo() { - return gyroscopeInfo_ == null ? Sensor_Info.getDefaultInstance() : gyroscopeInfo_; + @java.lang.Override + public Traj.SensorInfo getGyroscopeInfo() { + return gyroscopeInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : gyroscopeInfo_; } /** - * optional .Sensor_Info gyroscope_info = 13; + * .SensorInfo gyroscope_info = 20; */ - public Sensor_InfoOrBuilder getGyroscopeInfoOrBuilder() { + @java.lang.Override + public Traj.SensorInfoOrBuilder getGyroscopeInfoOrBuilder() { return getGyroscopeInfo(); } - public static final int ROTATION_VECTOR_INFO_FIELD_NUMBER = 14; - private Sensor_Info rotationVectorInfo_; + public static final int ROTATION_VECTOR_INFO_FIELD_NUMBER = 21; + private Traj.SensorInfo rotationVectorInfo_; /** - * optional .Sensor_Info rotation_vector_info = 14; + * .SensorInfo rotation_vector_info = 21; + * @return Whether the rotationVectorInfo field is set. */ + @java.lang.Override public boolean hasRotationVectorInfo() { return rotationVectorInfo_ != null; } /** - * optional .Sensor_Info rotation_vector_info = 14; + * .SensorInfo rotation_vector_info = 21; + * @return The rotationVectorInfo. */ - public Sensor_Info getRotationVectorInfo() { - return rotationVectorInfo_ == null ? Sensor_Info.getDefaultInstance() : rotationVectorInfo_; + @java.lang.Override + public Traj.SensorInfo getRotationVectorInfo() { + return rotationVectorInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : rotationVectorInfo_; } /** - * optional .Sensor_Info rotation_vector_info = 14; + * .SensorInfo rotation_vector_info = 21; */ - public Sensor_InfoOrBuilder getRotationVectorInfoOrBuilder() { + @java.lang.Override + public Traj.SensorInfoOrBuilder getRotationVectorInfoOrBuilder() { return getRotationVectorInfo(); } - public static final int MAGNETOMETER_INFO_FIELD_NUMBER = 15; - private Sensor_Info magnetometerInfo_; + public static final int MAGNETOMETER_INFO_FIELD_NUMBER = 22; + private Traj.SensorInfo magnetometerInfo_; /** - * optional .Sensor_Info magnetometer_info = 15; + * .SensorInfo magnetometer_info = 22; + * @return Whether the magnetometerInfo field is set. */ + @java.lang.Override public boolean hasMagnetometerInfo() { return magnetometerInfo_ != null; } /** - * optional .Sensor_Info magnetometer_info = 15; + * .SensorInfo magnetometer_info = 22; + * @return The magnetometerInfo. */ - public Sensor_Info getMagnetometerInfo() { - return magnetometerInfo_ == null ? Sensor_Info.getDefaultInstance() : magnetometerInfo_; + @java.lang.Override + public Traj.SensorInfo getMagnetometerInfo() { + return magnetometerInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : magnetometerInfo_; } /** - * optional .Sensor_Info magnetometer_info = 15; + * .SensorInfo magnetometer_info = 22; */ - public Sensor_InfoOrBuilder getMagnetometerInfoOrBuilder() { + @java.lang.Override + public Traj.SensorInfoOrBuilder getMagnetometerInfoOrBuilder() { return getMagnetometerInfo(); } - public static final int BAROMETER_INFO_FIELD_NUMBER = 16; - private Sensor_Info barometerInfo_; + public static final int BAROMETER_INFO_FIELD_NUMBER = 23; + private Traj.SensorInfo barometerInfo_; /** - * optional .Sensor_Info barometer_info = 16; + * .SensorInfo barometer_info = 23; + * @return Whether the barometerInfo field is set. */ + @java.lang.Override public boolean hasBarometerInfo() { return barometerInfo_ != null; } /** - * optional .Sensor_Info barometer_info = 16; + * .SensorInfo barometer_info = 23; + * @return The barometerInfo. */ - public Sensor_Info getBarometerInfo() { - return barometerInfo_ == null ? Sensor_Info.getDefaultInstance() : barometerInfo_; + @java.lang.Override + public Traj.SensorInfo getBarometerInfo() { + return barometerInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : barometerInfo_; } /** - * optional .Sensor_Info barometer_info = 16; + * .SensorInfo barometer_info = 23; */ - public Sensor_InfoOrBuilder getBarometerInfoOrBuilder() { + @java.lang.Override + public Traj.SensorInfoOrBuilder getBarometerInfoOrBuilder() { return getBarometerInfo(); } - public static final int LIGHT_SENSOR_INFO_FIELD_NUMBER = 17; - private Sensor_Info lightSensorInfo_; + public static final int LIGHT_SENSOR_INFO_FIELD_NUMBER = 24; + private Traj.SensorInfo lightSensorInfo_; /** - * optional .Sensor_Info light_sensor_info = 17; + * .SensorInfo light_sensor_info = 24; + * @return Whether the lightSensorInfo field is set. */ + @java.lang.Override public boolean hasLightSensorInfo() { return lightSensorInfo_ != null; } /** - * optional .Sensor_Info light_sensor_info = 17; + * .SensorInfo light_sensor_info = 24; + * @return The lightSensorInfo. */ - public Sensor_Info getLightSensorInfo() { - return lightSensorInfo_ == null ? Sensor_Info.getDefaultInstance() : lightSensorInfo_; + @java.lang.Override + public Traj.SensorInfo getLightSensorInfo() { + return lightSensorInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : lightSensorInfo_; } /** - * optional .Sensor_Info light_sensor_info = 17; + * .SensorInfo light_sensor_info = 24; */ - public Sensor_InfoOrBuilder getLightSensorInfoOrBuilder() { + @java.lang.Override + public Traj.SensorInfoOrBuilder getLightSensorInfoOrBuilder() { return getLightSensorInfo(); } + public static final int PROXIMITY_INFO_FIELD_NUMBER = 25; + private Traj.SensorInfo proximityInfo_; + /** + * .SensorInfo proximity_info = 25; + * @return Whether the proximityInfo field is set. + */ + @java.lang.Override + public boolean hasProximityInfo() { + return proximityInfo_ != null; + } + /** + * .SensorInfo proximity_info = 25; + * @return The proximityInfo. + */ + @java.lang.Override + public Traj.SensorInfo getProximityInfo() { + return proximityInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : proximityInfo_; + } + /** + * .SensorInfo proximity_info = 25; + */ + @java.lang.Override + public Traj.SensorInfoOrBuilder getProximityInfoOrBuilder() { + return getProximityInfo(); + } + + public static final int TEST_POINTS_FIELD_NUMBER = 26; + private java.util.List testPoints_; + /** + * repeated .GNSSPosition test_points = 26; + */ + @java.lang.Override + public java.util.List getTestPointsList() { + return testPoints_; + } + /** + * repeated .GNSSPosition test_points = 26; + */ + @java.lang.Override + public java.util.List + getTestPointsOrBuilderList() { + return testPoints_; + } + /** + * repeated .GNSSPosition test_points = 26; + */ + @java.lang.Override + public int getTestPointsCount() { + return testPoints_.size(); + } + /** + * repeated .GNSSPosition test_points = 26; + */ + @java.lang.Override + public Traj.GNSSPosition getTestPoints(int index) { + return testPoints_.get(index); + } + /** + * repeated .GNSSPosition test_points = 26; + */ + @java.lang.Override + public Traj.GNSSPositionOrBuilder getTestPointsOrBuilder( + int index) { + return testPoints_.get(index); + } + private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; @@ -1089,212 +1819,308 @@ public final boolean isInitialized() { return true; } + @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!getAndroidVersionBytes().isEmpty()) { + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(androidVersion_)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 1, androidVersion_); } + if (java.lang.Float.floatToRawIntBits(trajectoryVersion_) != 0) { + output.writeFloat(2, trajectoryVersion_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(trajectoryId_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 3, trajectoryId_); + } for (int i = 0; i < imuData_.size(); i++) { - output.writeMessage(2, imuData_.get(i)); + output.writeMessage(4, imuData_.get(i)); } for (int i = 0; i < pdrData_.size(); i++) { - output.writeMessage(3, pdrData_.get(i)); + output.writeMessage(5, pdrData_.get(i)); } - for (int i = 0; i < positionData_.size(); i++) { - output.writeMessage(4, positionData_.get(i)); + for (int i = 0; i < magnetometerData_.size(); i++) { + output.writeMessage(6, magnetometerData_.get(i)); } for (int i = 0; i < pressureData_.size(); i++) { - output.writeMessage(5, pressureData_.get(i)); + output.writeMessage(7, pressureData_.get(i)); } for (int i = 0; i < lightData_.size(); i++) { - output.writeMessage(6, lightData_.get(i)); + output.writeMessage(8, lightData_.get(i)); + } + for (int i = 0; i < proximityData_.size(); i++) { + output.writeMessage(9, proximityData_.get(i)); } for (int i = 0; i < gnssData_.size(); i++) { - output.writeMessage(7, gnssData_.get(i)); + output.writeMessage(10, gnssData_.get(i)); } - for (int i = 0; i < wifiData_.size(); i++) { - output.writeMessage(8, wifiData_.get(i)); + for (int i = 0; i < wifiFingerprints_.size(); i++) { + output.writeMessage(11, wifiFingerprints_.get(i)); } for (int i = 0; i < apsData_.size(); i++) { - output.writeMessage(9, apsData_.get(i)); + output.writeMessage(12, apsData_.get(i)); + } + for (int i = 0; i < wifiRttData_.size(); i++) { + output.writeMessage(13, wifiRttData_.get(i)); + } + for (int i = 0; i < bleFingerprints_.size(); i++) { + output.writeMessage(14, bleFingerprints_.get(i)); + } + for (int i = 0; i < bleData_.size(); i++) { + output.writeMessage(15, bleData_.get(i)); } if (startTimestamp_ != 0L) { - output.writeInt64(10, startTimestamp_); + output.writeInt64(16, startTimestamp_); } - if (!getDataIdentifierBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 11, dataIdentifier_); + if (initialPosition_ != null) { + output.writeMessage(17, getInitialPosition()); + } + for (int i = 0; i < correctedPositions_.size(); i++) { + output.writeMessage(18, correctedPositions_.get(i)); } if (accelerometerInfo_ != null) { - output.writeMessage(12, getAccelerometerInfo()); + output.writeMessage(19, getAccelerometerInfo()); } if (gyroscopeInfo_ != null) { - output.writeMessage(13, getGyroscopeInfo()); + output.writeMessage(20, getGyroscopeInfo()); } if (rotationVectorInfo_ != null) { - output.writeMessage(14, getRotationVectorInfo()); + output.writeMessage(21, getRotationVectorInfo()); } if (magnetometerInfo_ != null) { - output.writeMessage(15, getMagnetometerInfo()); + output.writeMessage(22, getMagnetometerInfo()); } if (barometerInfo_ != null) { - output.writeMessage(16, getBarometerInfo()); + output.writeMessage(23, getBarometerInfo()); } if (lightSensorInfo_ != null) { - output.writeMessage(17, getLightSensorInfo()); + output.writeMessage(24, getLightSensorInfo()); + } + if (proximityInfo_ != null) { + output.writeMessage(25, getProximityInfo()); } + for (int i = 0; i < testPoints_.size(); i++) { + output.writeMessage(26, testPoints_.get(i)); + } + unknownFields.writeTo(output); } + @java.lang.Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; size = 0; - if (!getAndroidVersionBytes().isEmpty()) { + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(androidVersion_)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, androidVersion_); } + if (java.lang.Float.floatToRawIntBits(trajectoryVersion_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeFloatSize(2, trajectoryVersion_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(trajectoryId_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, trajectoryId_); + } for (int i = 0; i < imuData_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, imuData_.get(i)); + .computeMessageSize(4, imuData_.get(i)); } for (int i = 0; i < pdrData_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(3, pdrData_.get(i)); + .computeMessageSize(5, pdrData_.get(i)); } - for (int i = 0; i < positionData_.size(); i++) { + for (int i = 0; i < magnetometerData_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(4, positionData_.get(i)); + .computeMessageSize(6, magnetometerData_.get(i)); } for (int i = 0; i < pressureData_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(5, pressureData_.get(i)); + .computeMessageSize(7, pressureData_.get(i)); } for (int i = 0; i < lightData_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(6, lightData_.get(i)); + .computeMessageSize(8, lightData_.get(i)); + } + for (int i = 0; i < proximityData_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(9, proximityData_.get(i)); } for (int i = 0; i < gnssData_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(7, gnssData_.get(i)); + .computeMessageSize(10, gnssData_.get(i)); } - for (int i = 0; i < wifiData_.size(); i++) { + for (int i = 0; i < wifiFingerprints_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(8, wifiData_.get(i)); + .computeMessageSize(11, wifiFingerprints_.get(i)); } for (int i = 0; i < apsData_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(9, apsData_.get(i)); + .computeMessageSize(12, apsData_.get(i)); + } + for (int i = 0; i < wifiRttData_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(13, wifiRttData_.get(i)); + } + for (int i = 0; i < bleFingerprints_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(14, bleFingerprints_.get(i)); + } + for (int i = 0; i < bleData_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(15, bleData_.get(i)); } if (startTimestamp_ != 0L) { size += com.google.protobuf.CodedOutputStream - .computeInt64Size(10, startTimestamp_); + .computeInt64Size(16, startTimestamp_); } - if (!getDataIdentifierBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(11, dataIdentifier_); + if (initialPosition_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(17, getInitialPosition()); + } + for (int i = 0; i < correctedPositions_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(18, correctedPositions_.get(i)); } if (accelerometerInfo_ != null) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(12, getAccelerometerInfo()); + .computeMessageSize(19, getAccelerometerInfo()); } if (gyroscopeInfo_ != null) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(13, getGyroscopeInfo()); + .computeMessageSize(20, getGyroscopeInfo()); } if (rotationVectorInfo_ != null) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(14, getRotationVectorInfo()); + .computeMessageSize(21, getRotationVectorInfo()); } if (magnetometerInfo_ != null) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(15, getMagnetometerInfo()); + .computeMessageSize(22, getMagnetometerInfo()); } if (barometerInfo_ != null) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(16, getBarometerInfo()); + .computeMessageSize(23, getBarometerInfo()); } if (lightSensorInfo_ != null) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(17, getLightSensorInfo()); + .computeMessageSize(24, getLightSensorInfo()); + } + if (proximityInfo_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(25, getProximityInfo()); + } + for (int i = 0; i < testPoints_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(26, testPoints_.get(i)); } + size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } - private static final long serialVersionUID = 0L; - @Override - public boolean equals(final Object obj) { + @java.lang.Override + public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof Trajectory)) { + if (!(obj instanceof Traj.Trajectory)) { return super.equals(obj); } - Trajectory other = (Trajectory) obj; - - boolean result = true; - result = result && getAndroidVersion() - .equals(other.getAndroidVersion()); - result = result && getImuDataList() - .equals(other.getImuDataList()); - result = result && getPdrDataList() - .equals(other.getPdrDataList()); - result = result && getPositionDataList() - .equals(other.getPositionDataList()); - result = result && getPressureDataList() - .equals(other.getPressureDataList()); - result = result && getLightDataList() - .equals(other.getLightDataList()); - result = result && getGnssDataList() - .equals(other.getGnssDataList()); - result = result && getWifiDataList() - .equals(other.getWifiDataList()); - result = result && getApsDataList() - .equals(other.getApsDataList()); - result = result && (getStartTimestamp() - == other.getStartTimestamp()); - result = result && getDataIdentifier() - .equals(other.getDataIdentifier()); - result = result && (hasAccelerometerInfo() == other.hasAccelerometerInfo()); + Traj.Trajectory other = (Traj.Trajectory) obj; + + if (!getAndroidVersion() + .equals(other.getAndroidVersion())) return false; + if (java.lang.Float.floatToIntBits(getTrajectoryVersion()) + != java.lang.Float.floatToIntBits( + other.getTrajectoryVersion())) return false; + if (!getTrajectoryId() + .equals(other.getTrajectoryId())) return false; + if (!getImuDataList() + .equals(other.getImuDataList())) return false; + if (!getPdrDataList() + .equals(other.getPdrDataList())) return false; + if (!getMagnetometerDataList() + .equals(other.getMagnetometerDataList())) return false; + if (!getPressureDataList() + .equals(other.getPressureDataList())) return false; + if (!getLightDataList() + .equals(other.getLightDataList())) return false; + if (!getProximityDataList() + .equals(other.getProximityDataList())) return false; + if (!getGnssDataList() + .equals(other.getGnssDataList())) return false; + if (!getWifiFingerprintsList() + .equals(other.getWifiFingerprintsList())) return false; + if (!getApsDataList() + .equals(other.getApsDataList())) return false; + if (!getWifiRttDataList() + .equals(other.getWifiRttDataList())) return false; + if (!getBleFingerprintsList() + .equals(other.getBleFingerprintsList())) return false; + if (!getBleDataList() + .equals(other.getBleDataList())) return false; + if (getStartTimestamp() + != other.getStartTimestamp()) return false; + if (hasInitialPosition() != other.hasInitialPosition()) return false; + if (hasInitialPosition()) { + if (!getInitialPosition() + .equals(other.getInitialPosition())) return false; + } + if (!getCorrectedPositionsList() + .equals(other.getCorrectedPositionsList())) return false; + if (hasAccelerometerInfo() != other.hasAccelerometerInfo()) return false; if (hasAccelerometerInfo()) { - result = result && getAccelerometerInfo() - .equals(other.getAccelerometerInfo()); + if (!getAccelerometerInfo() + .equals(other.getAccelerometerInfo())) return false; } - result = result && (hasGyroscopeInfo() == other.hasGyroscopeInfo()); + if (hasGyroscopeInfo() != other.hasGyroscopeInfo()) return false; if (hasGyroscopeInfo()) { - result = result && getGyroscopeInfo() - .equals(other.getGyroscopeInfo()); + if (!getGyroscopeInfo() + .equals(other.getGyroscopeInfo())) return false; } - result = result && (hasRotationVectorInfo() == other.hasRotationVectorInfo()); + if (hasRotationVectorInfo() != other.hasRotationVectorInfo()) return false; if (hasRotationVectorInfo()) { - result = result && getRotationVectorInfo() - .equals(other.getRotationVectorInfo()); + if (!getRotationVectorInfo() + .equals(other.getRotationVectorInfo())) return false; } - result = result && (hasMagnetometerInfo() == other.hasMagnetometerInfo()); + if (hasMagnetometerInfo() != other.hasMagnetometerInfo()) return false; if (hasMagnetometerInfo()) { - result = result && getMagnetometerInfo() - .equals(other.getMagnetometerInfo()); + if (!getMagnetometerInfo() + .equals(other.getMagnetometerInfo())) return false; } - result = result && (hasBarometerInfo() == other.hasBarometerInfo()); + if (hasBarometerInfo() != other.hasBarometerInfo()) return false; if (hasBarometerInfo()) { - result = result && getBarometerInfo() - .equals(other.getBarometerInfo()); + if (!getBarometerInfo() + .equals(other.getBarometerInfo())) return false; } - result = result && (hasLightSensorInfo() == other.hasLightSensorInfo()); + if (hasLightSensorInfo() != other.hasLightSensorInfo()) return false; if (hasLightSensorInfo()) { - result = result && getLightSensorInfo() - .equals(other.getLightSensorInfo()); + if (!getLightSensorInfo() + .equals(other.getLightSensorInfo())) return false; + } + if (hasProximityInfo() != other.hasProximityInfo()) return false; + if (hasProximityInfo()) { + if (!getProximityInfo() + .equals(other.getProximityInfo())) return false; } - return result; + if (!getTestPointsList() + .equals(other.getTestPointsList())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; } - @Override + @java.lang.Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; - hash = (19 * hash) + getDescriptorForType().hashCode(); + hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + ANDROID_VERSION_FIELD_NUMBER; hash = (53 * hash) + getAndroidVersion().hashCode(); + hash = (37 * hash) + TRAJECTORY_VERSION_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getTrajectoryVersion()); + hash = (37 * hash) + TRAJECTORY_ID_FIELD_NUMBER; + hash = (53 * hash) + getTrajectoryId().hashCode(); if (getImuDataCount() > 0) { hash = (37 * hash) + IMU_DATA_FIELD_NUMBER; hash = (53 * hash) + getImuDataList().hashCode(); @@ -1303,9 +2129,9 @@ public int hashCode() { hash = (37 * hash) + PDR_DATA_FIELD_NUMBER; hash = (53 * hash) + getPdrDataList().hashCode(); } - if (getPositionDataCount() > 0) { - hash = (37 * hash) + POSITION_DATA_FIELD_NUMBER; - hash = (53 * hash) + getPositionDataList().hashCode(); + if (getMagnetometerDataCount() > 0) { + hash = (37 * hash) + MAGNETOMETER_DATA_FIELD_NUMBER; + hash = (53 * hash) + getMagnetometerDataList().hashCode(); } if (getPressureDataCount() > 0) { hash = (37 * hash) + PRESSURE_DATA_FIELD_NUMBER; @@ -1315,23 +2141,45 @@ public int hashCode() { hash = (37 * hash) + LIGHT_DATA_FIELD_NUMBER; hash = (53 * hash) + getLightDataList().hashCode(); } + if (getProximityDataCount() > 0) { + hash = (37 * hash) + PROXIMITY_DATA_FIELD_NUMBER; + hash = (53 * hash) + getProximityDataList().hashCode(); + } if (getGnssDataCount() > 0) { hash = (37 * hash) + GNSS_DATA_FIELD_NUMBER; hash = (53 * hash) + getGnssDataList().hashCode(); } - if (getWifiDataCount() > 0) { - hash = (37 * hash) + WIFI_DATA_FIELD_NUMBER; - hash = (53 * hash) + getWifiDataList().hashCode(); + if (getWifiFingerprintsCount() > 0) { + hash = (37 * hash) + WIFI_FINGERPRINTS_FIELD_NUMBER; + hash = (53 * hash) + getWifiFingerprintsList().hashCode(); } if (getApsDataCount() > 0) { hash = (37 * hash) + APS_DATA_FIELD_NUMBER; hash = (53 * hash) + getApsDataList().hashCode(); } + if (getWifiRttDataCount() > 0) { + hash = (37 * hash) + WIFI_RTT_DATA_FIELD_NUMBER; + hash = (53 * hash) + getWifiRttDataList().hashCode(); + } + if (getBleFingerprintsCount() > 0) { + hash = (37 * hash) + BLE_FINGERPRINTS_FIELD_NUMBER; + hash = (53 * hash) + getBleFingerprintsList().hashCode(); + } + if (getBleDataCount() > 0) { + hash = (37 * hash) + BLE_DATA_FIELD_NUMBER; + hash = (53 * hash) + getBleDataList().hashCode(); + } hash = (37 * hash) + START_TIMESTAMP_FIELD_NUMBER; hash = (53 * hash) + com.google.protobuf.Internal.hashLong( getStartTimestamp()); - hash = (37 * hash) + DATA_IDENTIFIER_FIELD_NUMBER; - hash = (53 * hash) + getDataIdentifier().hashCode(); + if (hasInitialPosition()) { + hash = (37 * hash) + INITIAL_POSITION_FIELD_NUMBER; + hash = (53 * hash) + getInitialPosition().hashCode(); + } + if (getCorrectedPositionsCount() > 0) { + hash = (37 * hash) + CORRECTED_POSITIONS_FIELD_NUMBER; + hash = (53 * hash) + getCorrectedPositionsList().hashCode(); + } if (hasAccelerometerInfo()) { hash = (37 * hash) + ACCELEROMETER_INFO_FIELD_NUMBER; hash = (53 * hash) + getAccelerometerInfo().hashCode(); @@ -1356,63 +2204,82 @@ public int hashCode() { hash = (37 * hash) + LIGHT_SENSOR_INFO_FIELD_NUMBER; hash = (53 * hash) + getLightSensorInfo().hashCode(); } + if (hasProximityInfo()) { + hash = (37 * hash) + PROXIMITY_INFO_FIELD_NUMBER; + hash = (53 * hash) + getProximityInfo().hashCode(); + } + if (getTestPointsCount() > 0) { + hash = (37 * hash) + TEST_POINTS_FIELD_NUMBER; + hash = (53 * hash) + getTestPointsList().hashCode(); + } hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } - public static Trajectory parseFrom( + public static Traj.Trajectory parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.Trajectory parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.Trajectory parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Trajectory parseFrom( + public static Traj.Trajectory parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Trajectory parseFrom(byte[] data) + public static Traj.Trajectory parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Trajectory parseFrom( + public static Traj.Trajectory parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Trajectory parseFrom(java.io.InputStream input) + public static Traj.Trajectory parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Trajectory parseFrom( + public static Traj.Trajectory parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static Trajectory parseDelimitedFrom(java.io.InputStream input) + public static Traj.Trajectory parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static Trajectory parseDelimitedFrom( + public static Traj.Trajectory parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static Trajectory parseFrom( + public static Traj.Trajectory parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Trajectory parseFrom( + public static Traj.Trajectory parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -1420,19 +2287,21 @@ public static Trajectory parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } + @java.lang.Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(Trajectory prototype) { + public static Builder newBuilder(Traj.Trajectory prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } - @Override + @java.lang.Override protected Builder newBuilderForType( com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { Builder builder = new Builder(parent); @@ -1444,17 +2313,18 @@ protected Builder newBuilderForType( public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements // @@protoc_insertion_point(builder_implements:Trajectory) - TrajectoryOrBuilder { + Traj.TrajectoryOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { return Traj.internal_static_Trajectory_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { return Traj.internal_static_Trajectory_fieldAccessorTable .ensureFieldAccessorsInitialized( - Trajectory.class, Builder.class); + Traj.Trajectory.class, Traj.Trajectory.Builder.class); } // Construct using Traj.Trajectory.newBuilder() @@ -1472,59 +2342,76 @@ private void maybeForceBuilderInitialization() { .alwaysUseFieldBuilders) { getImuDataFieldBuilder(); getPdrDataFieldBuilder(); - getPositionDataFieldBuilder(); + getMagnetometerDataFieldBuilder(); getPressureDataFieldBuilder(); getLightDataFieldBuilder(); + getProximityDataFieldBuilder(); getGnssDataFieldBuilder(); - getWifiDataFieldBuilder(); + getWifiFingerprintsFieldBuilder(); getApsDataFieldBuilder(); + getWifiRttDataFieldBuilder(); + getBleFingerprintsFieldBuilder(); + getBleDataFieldBuilder(); + getCorrectedPositionsFieldBuilder(); + getTestPointsFieldBuilder(); } } + @java.lang.Override public Builder clear() { super.clear(); androidVersion_ = ""; + trajectoryVersion_ = 0F; + + trajectoryId_ = ""; + if (imuDataBuilder_ == null) { imuData_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); + bitField0_ = (bitField0_ & ~0x00000001); } else { imuDataBuilder_.clear(); } if (pdrDataBuilder_ == null) { pdrData_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000002); } else { pdrDataBuilder_.clear(); } - if (positionDataBuilder_ == null) { - positionData_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000008); + if (magnetometerDataBuilder_ == null) { + magnetometerData_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000004); } else { - positionDataBuilder_.clear(); + magnetometerDataBuilder_.clear(); } if (pressureDataBuilder_ == null) { pressureData_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000010); + bitField0_ = (bitField0_ & ~0x00000008); } else { pressureDataBuilder_.clear(); } if (lightDataBuilder_ == null) { lightData_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000020); + bitField0_ = (bitField0_ & ~0x00000010); } else { lightDataBuilder_.clear(); } + if (proximityDataBuilder_ == null) { + proximityData_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000020); + } else { + proximityDataBuilder_.clear(); + } if (gnssDataBuilder_ == null) { gnssData_ = java.util.Collections.emptyList(); bitField0_ = (bitField0_ & ~0x00000040); } else { gnssDataBuilder_.clear(); } - if (wifiDataBuilder_ == null) { - wifiData_ = java.util.Collections.emptyList(); + if (wifiFingerprintsBuilder_ == null) { + wifiFingerprints_ = java.util.Collections.emptyList(); bitField0_ = (bitField0_ & ~0x00000080); } else { - wifiDataBuilder_.clear(); + wifiFingerprintsBuilder_.clear(); } if (apsDataBuilder_ == null) { apsData_ = java.util.Collections.emptyList(); @@ -1532,10 +2419,38 @@ public Builder clear() { } else { apsDataBuilder_.clear(); } + if (wifiRttDataBuilder_ == null) { + wifiRttData_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000200); + } else { + wifiRttDataBuilder_.clear(); + } + if (bleFingerprintsBuilder_ == null) { + bleFingerprints_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000400); + } else { + bleFingerprintsBuilder_.clear(); + } + if (bleDataBuilder_ == null) { + bleData_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000800); + } else { + bleDataBuilder_.clear(); + } startTimestamp_ = 0L; - dataIdentifier_ = ""; - + if (initialPositionBuilder_ == null) { + initialPosition_ = null; + } else { + initialPosition_ = null; + initialPositionBuilder_ = null; + } + if (correctedPositionsBuilder_ == null) { + correctedPositions_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00001000); + } else { + correctedPositionsBuilder_.clear(); + } if (accelerometerInfoBuilder_ == null) { accelerometerInfo_ = null; } else { @@ -1572,78 +2487,104 @@ public Builder clear() { lightSensorInfo_ = null; lightSensorInfoBuilder_ = null; } + if (proximityInfoBuilder_ == null) { + proximityInfo_ = null; + } else { + proximityInfo_ = null; + proximityInfoBuilder_ = null; + } + if (testPointsBuilder_ == null) { + testPoints_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00002000); + } else { + testPointsBuilder_.clear(); + } return this; } + @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { return Traj.internal_static_Trajectory_descriptor; } - public Trajectory getDefaultInstanceForType() { - return Trajectory.getDefaultInstance(); + @java.lang.Override + public Traj.Trajectory getDefaultInstanceForType() { + return Traj.Trajectory.getDefaultInstance(); } - public Trajectory build() { - Trajectory result = buildPartial(); + @java.lang.Override + public Traj.Trajectory build() { + Traj.Trajectory result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } - public Trajectory buildPartial() { - Trajectory result = new Trajectory(this); + @java.lang.Override + public Traj.Trajectory buildPartial() { + Traj.Trajectory result = new Traj.Trajectory(this); int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; result.androidVersion_ = androidVersion_; + result.trajectoryVersion_ = trajectoryVersion_; + result.trajectoryId_ = trajectoryId_; if (imuDataBuilder_ == null) { - if (((bitField0_ & 0x00000002) == 0x00000002)) { + if (((bitField0_ & 0x00000001) != 0)) { imuData_ = java.util.Collections.unmodifiableList(imuData_); - bitField0_ = (bitField0_ & ~0x00000002); + bitField0_ = (bitField0_ & ~0x00000001); } result.imuData_ = imuData_; } else { result.imuData_ = imuDataBuilder_.build(); } if (pdrDataBuilder_ == null) { - if (((bitField0_ & 0x00000004) == 0x00000004)) { + if (((bitField0_ & 0x00000002) != 0)) { pdrData_ = java.util.Collections.unmodifiableList(pdrData_); - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000002); } result.pdrData_ = pdrData_; } else { result.pdrData_ = pdrDataBuilder_.build(); } - if (positionDataBuilder_ == null) { - if (((bitField0_ & 0x00000008) == 0x00000008)) { - positionData_ = java.util.Collections.unmodifiableList(positionData_); - bitField0_ = (bitField0_ & ~0x00000008); + if (magnetometerDataBuilder_ == null) { + if (((bitField0_ & 0x00000004) != 0)) { + magnetometerData_ = java.util.Collections.unmodifiableList(magnetometerData_); + bitField0_ = (bitField0_ & ~0x00000004); } - result.positionData_ = positionData_; + result.magnetometerData_ = magnetometerData_; } else { - result.positionData_ = positionDataBuilder_.build(); + result.magnetometerData_ = magnetometerDataBuilder_.build(); } if (pressureDataBuilder_ == null) { - if (((bitField0_ & 0x00000010) == 0x00000010)) { + if (((bitField0_ & 0x00000008) != 0)) { pressureData_ = java.util.Collections.unmodifiableList(pressureData_); - bitField0_ = (bitField0_ & ~0x00000010); + bitField0_ = (bitField0_ & ~0x00000008); } result.pressureData_ = pressureData_; } else { result.pressureData_ = pressureDataBuilder_.build(); } if (lightDataBuilder_ == null) { - if (((bitField0_ & 0x00000020) == 0x00000020)) { + if (((bitField0_ & 0x00000010) != 0)) { lightData_ = java.util.Collections.unmodifiableList(lightData_); - bitField0_ = (bitField0_ & ~0x00000020); + bitField0_ = (bitField0_ & ~0x00000010); } result.lightData_ = lightData_; } else { result.lightData_ = lightDataBuilder_.build(); } + if (proximityDataBuilder_ == null) { + if (((bitField0_ & 0x00000020) != 0)) { + proximityData_ = java.util.Collections.unmodifiableList(proximityData_); + bitField0_ = (bitField0_ & ~0x00000020); + } + result.proximityData_ = proximityData_; + } else { + result.proximityData_ = proximityDataBuilder_.build(); + } if (gnssDataBuilder_ == null) { - if (((bitField0_ & 0x00000040) == 0x00000040)) { + if (((bitField0_ & 0x00000040) != 0)) { gnssData_ = java.util.Collections.unmodifiableList(gnssData_); bitField0_ = (bitField0_ & ~0x00000040); } @@ -1651,17 +2592,17 @@ public Trajectory buildPartial() { } else { result.gnssData_ = gnssDataBuilder_.build(); } - if (wifiDataBuilder_ == null) { - if (((bitField0_ & 0x00000080) == 0x00000080)) { - wifiData_ = java.util.Collections.unmodifiableList(wifiData_); + if (wifiFingerprintsBuilder_ == null) { + if (((bitField0_ & 0x00000080) != 0)) { + wifiFingerprints_ = java.util.Collections.unmodifiableList(wifiFingerprints_); bitField0_ = (bitField0_ & ~0x00000080); } - result.wifiData_ = wifiData_; + result.wifiFingerprints_ = wifiFingerprints_; } else { - result.wifiData_ = wifiDataBuilder_.build(); + result.wifiFingerprints_ = wifiFingerprintsBuilder_.build(); } if (apsDataBuilder_ == null) { - if (((bitField0_ & 0x00000100) == 0x00000100)) { + if (((bitField0_ & 0x00000100) != 0)) { apsData_ = java.util.Collections.unmodifiableList(apsData_); bitField0_ = (bitField0_ & ~0x00000100); } @@ -1669,8 +2610,48 @@ public Trajectory buildPartial() { } else { result.apsData_ = apsDataBuilder_.build(); } + if (wifiRttDataBuilder_ == null) { + if (((bitField0_ & 0x00000200) != 0)) { + wifiRttData_ = java.util.Collections.unmodifiableList(wifiRttData_); + bitField0_ = (bitField0_ & ~0x00000200); + } + result.wifiRttData_ = wifiRttData_; + } else { + result.wifiRttData_ = wifiRttDataBuilder_.build(); + } + if (bleFingerprintsBuilder_ == null) { + if (((bitField0_ & 0x00000400) != 0)) { + bleFingerprints_ = java.util.Collections.unmodifiableList(bleFingerprints_); + bitField0_ = (bitField0_ & ~0x00000400); + } + result.bleFingerprints_ = bleFingerprints_; + } else { + result.bleFingerprints_ = bleFingerprintsBuilder_.build(); + } + if (bleDataBuilder_ == null) { + if (((bitField0_ & 0x00000800) != 0)) { + bleData_ = java.util.Collections.unmodifiableList(bleData_); + bitField0_ = (bitField0_ & ~0x00000800); + } + result.bleData_ = bleData_; + } else { + result.bleData_ = bleDataBuilder_.build(); + } result.startTimestamp_ = startTimestamp_; - result.dataIdentifier_ = dataIdentifier_; + if (initialPositionBuilder_ == null) { + result.initialPosition_ = initialPosition_; + } else { + result.initialPosition_ = initialPositionBuilder_.build(); + } + if (correctedPositionsBuilder_ == null) { + if (((bitField0_ & 0x00001000) != 0)) { + correctedPositions_ = java.util.Collections.unmodifiableList(correctedPositions_); + bitField0_ = (bitField0_ & ~0x00001000); + } + result.correctedPositions_ = correctedPositions_; + } else { + result.correctedPositions_ = correctedPositionsBuilder_.build(); + } if (accelerometerInfoBuilder_ == null) { result.accelerometerInfo_ = accelerometerInfo_; } else { @@ -1701,57 +2682,84 @@ public Trajectory buildPartial() { } else { result.lightSensorInfo_ = lightSensorInfoBuilder_.build(); } - result.bitField0_ = to_bitField0_; + if (proximityInfoBuilder_ == null) { + result.proximityInfo_ = proximityInfo_; + } else { + result.proximityInfo_ = proximityInfoBuilder_.build(); + } + if (testPointsBuilder_ == null) { + if (((bitField0_ & 0x00002000) != 0)) { + testPoints_ = java.util.Collections.unmodifiableList(testPoints_); + bitField0_ = (bitField0_ & ~0x00002000); + } + result.testPoints_ = testPoints_; + } else { + result.testPoints_ = testPointsBuilder_.build(); + } onBuilt(); return result; } + @java.lang.Override public Builder clone() { - return (Builder) super.clone(); + return super.clone(); } + @java.lang.Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); + java.lang.Object value) { + return super.setField(field, value); } + @java.lang.Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); + return super.clearField(field); } + @java.lang.Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); + return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); + java.lang.Object value) { + return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof Trajectory) { - return mergeFrom((Trajectory)other); + if (other instanceof Traj.Trajectory) { + return mergeFrom((Traj.Trajectory)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(Trajectory other) { - if (other == Trajectory.getDefaultInstance()) return this; + public Builder mergeFrom(Traj.Trajectory other) { + if (other == Traj.Trajectory.getDefaultInstance()) return this; if (!other.getAndroidVersion().isEmpty()) { androidVersion_ = other.androidVersion_; onChanged(); } + if (other.getTrajectoryVersion() != 0F) { + setTrajectoryVersion(other.getTrajectoryVersion()); + } + if (!other.getTrajectoryId().isEmpty()) { + trajectoryId_ = other.trajectoryId_; + onChanged(); + } if (imuDataBuilder_ == null) { if (!other.imuData_.isEmpty()) { if (imuData_.isEmpty()) { imuData_ = other.imuData_; - bitField0_ = (bitField0_ & ~0x00000002); + bitField0_ = (bitField0_ & ~0x00000001); } else { ensureImuDataIsMutable(); imuData_.addAll(other.imuData_); @@ -1764,7 +2772,7 @@ public Builder mergeFrom(Trajectory other) { imuDataBuilder_.dispose(); imuDataBuilder_ = null; imuData_ = other.imuData_; - bitField0_ = (bitField0_ & ~0x00000002); + bitField0_ = (bitField0_ & ~0x00000001); imuDataBuilder_ = com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? getImuDataFieldBuilder() : null; @@ -1777,7 +2785,7 @@ public Builder mergeFrom(Trajectory other) { if (!other.pdrData_.isEmpty()) { if (pdrData_.isEmpty()) { pdrData_ = other.pdrData_; - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000002); } else { ensurePdrDataIsMutable(); pdrData_.addAll(other.pdrData_); @@ -1790,7 +2798,7 @@ public Builder mergeFrom(Trajectory other) { pdrDataBuilder_.dispose(); pdrDataBuilder_ = null; pdrData_ = other.pdrData_; - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000002); pdrDataBuilder_ = com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? getPdrDataFieldBuilder() : null; @@ -1799,29 +2807,29 @@ public Builder mergeFrom(Trajectory other) { } } } - if (positionDataBuilder_ == null) { - if (!other.positionData_.isEmpty()) { - if (positionData_.isEmpty()) { - positionData_ = other.positionData_; - bitField0_ = (bitField0_ & ~0x00000008); + if (magnetometerDataBuilder_ == null) { + if (!other.magnetometerData_.isEmpty()) { + if (magnetometerData_.isEmpty()) { + magnetometerData_ = other.magnetometerData_; + bitField0_ = (bitField0_ & ~0x00000004); } else { - ensurePositionDataIsMutable(); - positionData_.addAll(other.positionData_); + ensureMagnetometerDataIsMutable(); + magnetometerData_.addAll(other.magnetometerData_); } onChanged(); } } else { - if (!other.positionData_.isEmpty()) { - if (positionDataBuilder_.isEmpty()) { - positionDataBuilder_.dispose(); - positionDataBuilder_ = null; - positionData_ = other.positionData_; - bitField0_ = (bitField0_ & ~0x00000008); - positionDataBuilder_ = + if (!other.magnetometerData_.isEmpty()) { + if (magnetometerDataBuilder_.isEmpty()) { + magnetometerDataBuilder_.dispose(); + magnetometerDataBuilder_ = null; + magnetometerData_ = other.magnetometerData_; + bitField0_ = (bitField0_ & ~0x00000004); + magnetometerDataBuilder_ = com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? - getPositionDataFieldBuilder() : null; + getMagnetometerDataFieldBuilder() : null; } else { - positionDataBuilder_.addAllMessages(other.positionData_); + magnetometerDataBuilder_.addAllMessages(other.magnetometerData_); } } } @@ -1829,7 +2837,7 @@ public Builder mergeFrom(Trajectory other) { if (!other.pressureData_.isEmpty()) { if (pressureData_.isEmpty()) { pressureData_ = other.pressureData_; - bitField0_ = (bitField0_ & ~0x00000010); + bitField0_ = (bitField0_ & ~0x00000008); } else { ensurePressureDataIsMutable(); pressureData_.addAll(other.pressureData_); @@ -1842,7 +2850,7 @@ public Builder mergeFrom(Trajectory other) { pressureDataBuilder_.dispose(); pressureDataBuilder_ = null; pressureData_ = other.pressureData_; - bitField0_ = (bitField0_ & ~0x00000010); + bitField0_ = (bitField0_ & ~0x00000008); pressureDataBuilder_ = com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? getPressureDataFieldBuilder() : null; @@ -1855,7 +2863,7 @@ public Builder mergeFrom(Trajectory other) { if (!other.lightData_.isEmpty()) { if (lightData_.isEmpty()) { lightData_ = other.lightData_; - bitField0_ = (bitField0_ & ~0x00000020); + bitField0_ = (bitField0_ & ~0x00000010); } else { ensureLightDataIsMutable(); lightData_.addAll(other.lightData_); @@ -1868,7 +2876,7 @@ public Builder mergeFrom(Trajectory other) { lightDataBuilder_.dispose(); lightDataBuilder_ = null; lightData_ = other.lightData_; - bitField0_ = (bitField0_ & ~0x00000020); + bitField0_ = (bitField0_ & ~0x00000010); lightDataBuilder_ = com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? getLightDataFieldBuilder() : null; @@ -1877,14 +2885,40 @@ public Builder mergeFrom(Trajectory other) { } } } - if (gnssDataBuilder_ == null) { - if (!other.gnssData_.isEmpty()) { - if (gnssData_.isEmpty()) { - gnssData_ = other.gnssData_; - bitField0_ = (bitField0_ & ~0x00000040); + if (proximityDataBuilder_ == null) { + if (!other.proximityData_.isEmpty()) { + if (proximityData_.isEmpty()) { + proximityData_ = other.proximityData_; + bitField0_ = (bitField0_ & ~0x00000020); } else { - ensureGnssDataIsMutable(); - gnssData_.addAll(other.gnssData_); + ensureProximityDataIsMutable(); + proximityData_.addAll(other.proximityData_); + } + onChanged(); + } + } else { + if (!other.proximityData_.isEmpty()) { + if (proximityDataBuilder_.isEmpty()) { + proximityDataBuilder_.dispose(); + proximityDataBuilder_ = null; + proximityData_ = other.proximityData_; + bitField0_ = (bitField0_ & ~0x00000020); + proximityDataBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getProximityDataFieldBuilder() : null; + } else { + proximityDataBuilder_.addAllMessages(other.proximityData_); + } + } + } + if (gnssDataBuilder_ == null) { + if (!other.gnssData_.isEmpty()) { + if (gnssData_.isEmpty()) { + gnssData_ = other.gnssData_; + bitField0_ = (bitField0_ & ~0x00000040); + } else { + ensureGnssDataIsMutable(); + gnssData_.addAll(other.gnssData_); } onChanged(); } @@ -1903,29 +2937,29 @@ public Builder mergeFrom(Trajectory other) { } } } - if (wifiDataBuilder_ == null) { - if (!other.wifiData_.isEmpty()) { - if (wifiData_.isEmpty()) { - wifiData_ = other.wifiData_; + if (wifiFingerprintsBuilder_ == null) { + if (!other.wifiFingerprints_.isEmpty()) { + if (wifiFingerprints_.isEmpty()) { + wifiFingerprints_ = other.wifiFingerprints_; bitField0_ = (bitField0_ & ~0x00000080); } else { - ensureWifiDataIsMutable(); - wifiData_.addAll(other.wifiData_); + ensureWifiFingerprintsIsMutable(); + wifiFingerprints_.addAll(other.wifiFingerprints_); } onChanged(); } } else { - if (!other.wifiData_.isEmpty()) { - if (wifiDataBuilder_.isEmpty()) { - wifiDataBuilder_.dispose(); - wifiDataBuilder_ = null; - wifiData_ = other.wifiData_; + if (!other.wifiFingerprints_.isEmpty()) { + if (wifiFingerprintsBuilder_.isEmpty()) { + wifiFingerprintsBuilder_.dispose(); + wifiFingerprintsBuilder_ = null; + wifiFingerprints_ = other.wifiFingerprints_; bitField0_ = (bitField0_ & ~0x00000080); - wifiDataBuilder_ = + wifiFingerprintsBuilder_ = com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? - getWifiDataFieldBuilder() : null; + getWifiFingerprintsFieldBuilder() : null; } else { - wifiDataBuilder_.addAllMessages(other.wifiData_); + wifiFingerprintsBuilder_.addAllMessages(other.wifiFingerprints_); } } } @@ -1955,12 +2989,115 @@ public Builder mergeFrom(Trajectory other) { } } } + if (wifiRttDataBuilder_ == null) { + if (!other.wifiRttData_.isEmpty()) { + if (wifiRttData_.isEmpty()) { + wifiRttData_ = other.wifiRttData_; + bitField0_ = (bitField0_ & ~0x00000200); + } else { + ensureWifiRttDataIsMutable(); + wifiRttData_.addAll(other.wifiRttData_); + } + onChanged(); + } + } else { + if (!other.wifiRttData_.isEmpty()) { + if (wifiRttDataBuilder_.isEmpty()) { + wifiRttDataBuilder_.dispose(); + wifiRttDataBuilder_ = null; + wifiRttData_ = other.wifiRttData_; + bitField0_ = (bitField0_ & ~0x00000200); + wifiRttDataBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getWifiRttDataFieldBuilder() : null; + } else { + wifiRttDataBuilder_.addAllMessages(other.wifiRttData_); + } + } + } + if (bleFingerprintsBuilder_ == null) { + if (!other.bleFingerprints_.isEmpty()) { + if (bleFingerprints_.isEmpty()) { + bleFingerprints_ = other.bleFingerprints_; + bitField0_ = (bitField0_ & ~0x00000400); + } else { + ensureBleFingerprintsIsMutable(); + bleFingerprints_.addAll(other.bleFingerprints_); + } + onChanged(); + } + } else { + if (!other.bleFingerprints_.isEmpty()) { + if (bleFingerprintsBuilder_.isEmpty()) { + bleFingerprintsBuilder_.dispose(); + bleFingerprintsBuilder_ = null; + bleFingerprints_ = other.bleFingerprints_; + bitField0_ = (bitField0_ & ~0x00000400); + bleFingerprintsBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getBleFingerprintsFieldBuilder() : null; + } else { + bleFingerprintsBuilder_.addAllMessages(other.bleFingerprints_); + } + } + } + if (bleDataBuilder_ == null) { + if (!other.bleData_.isEmpty()) { + if (bleData_.isEmpty()) { + bleData_ = other.bleData_; + bitField0_ = (bitField0_ & ~0x00000800); + } else { + ensureBleDataIsMutable(); + bleData_.addAll(other.bleData_); + } + onChanged(); + } + } else { + if (!other.bleData_.isEmpty()) { + if (bleDataBuilder_.isEmpty()) { + bleDataBuilder_.dispose(); + bleDataBuilder_ = null; + bleData_ = other.bleData_; + bitField0_ = (bitField0_ & ~0x00000800); + bleDataBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getBleDataFieldBuilder() : null; + } else { + bleDataBuilder_.addAllMessages(other.bleData_); + } + } + } if (other.getStartTimestamp() != 0L) { setStartTimestamp(other.getStartTimestamp()); } - if (!other.getDataIdentifier().isEmpty()) { - dataIdentifier_ = other.dataIdentifier_; - onChanged(); + if (other.hasInitialPosition()) { + mergeInitialPosition(other.getInitialPosition()); + } + if (correctedPositionsBuilder_ == null) { + if (!other.correctedPositions_.isEmpty()) { + if (correctedPositions_.isEmpty()) { + correctedPositions_ = other.correctedPositions_; + bitField0_ = (bitField0_ & ~0x00001000); + } else { + ensureCorrectedPositionsIsMutable(); + correctedPositions_.addAll(other.correctedPositions_); + } + onChanged(); + } + } else { + if (!other.correctedPositions_.isEmpty()) { + if (correctedPositionsBuilder_.isEmpty()) { + correctedPositionsBuilder_.dispose(); + correctedPositionsBuilder_ = null; + correctedPositions_ = other.correctedPositions_; + bitField0_ = (bitField0_ & ~0x00001000); + correctedPositionsBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getCorrectedPositionsFieldBuilder() : null; + } else { + correctedPositionsBuilder_.addAllMessages(other.correctedPositions_); + } + } } if (other.hasAccelerometerInfo()) { mergeAccelerometerInfo(other.getAccelerometerInfo()); @@ -1980,23 +3117,55 @@ public Builder mergeFrom(Trajectory other) { if (other.hasLightSensorInfo()) { mergeLightSensorInfo(other.getLightSensorInfo()); } + if (other.hasProximityInfo()) { + mergeProximityInfo(other.getProximityInfo()); + } + if (testPointsBuilder_ == null) { + if (!other.testPoints_.isEmpty()) { + if (testPoints_.isEmpty()) { + testPoints_ = other.testPoints_; + bitField0_ = (bitField0_ & ~0x00002000); + } else { + ensureTestPointsIsMutable(); + testPoints_.addAll(other.testPoints_); + } + onChanged(); + } + } else { + if (!other.testPoints_.isEmpty()) { + if (testPointsBuilder_.isEmpty()) { + testPointsBuilder_.dispose(); + testPointsBuilder_ = null; + testPoints_ = other.testPoints_; + bitField0_ = (bitField0_ & ~0x00002000); + testPointsBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getTestPointsFieldBuilder() : null; + } else { + testPointsBuilder_.addAllMessages(other.testPoints_); + } + } + } + this.mergeUnknownFields(other.unknownFields); onChanged(); return this; } + @java.lang.Override public final boolean isInitialized() { return true; } + @java.lang.Override public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - Trajectory parsedMessage = null; + Traj.Trajectory parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (Trajectory) e.getUnfinishedMessage(); + parsedMessage = (Traj.Trajectory) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -2007,32 +3176,34 @@ public Builder mergeFrom( } private int bitField0_; - private Object androidVersion_ = ""; + private java.lang.Object androidVersion_ = ""; /** - * optional string android_version = 1; + * string android_version = 1; + * @return The androidVersion. */ - public String getAndroidVersion() { - Object ref = androidVersion_; - if (!(ref instanceof String)) { + public java.lang.String getAndroidVersion() { + java.lang.Object ref = androidVersion_; + if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); + java.lang.String s = bs.toStringUtf8(); androidVersion_ = s; return s; } else { - return (String) ref; + return (java.lang.String) ref; } } /** - * optional string android_version = 1; + * string android_version = 1; + * @return The bytes for androidVersion. */ public com.google.protobuf.ByteString getAndroidVersionBytes() { - Object ref = androidVersion_; + java.lang.Object ref = androidVersion_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); + (java.lang.String) ref); androidVersion_ = b; return b; } else { @@ -2040,10 +3211,12 @@ public String getAndroidVersion() { } } /** - * optional string android_version = 1; + * string android_version = 1; + * @param value The androidVersion to set. + * @return This builder for chaining. */ public Builder setAndroidVersion( - String value) { + java.lang.String value) { if (value == null) { throw new NullPointerException(); } @@ -2053,7 +3226,8 @@ public Builder setAndroidVersion( return this; } /** - * optional string android_version = 1; + * string android_version = 1; + * @return This builder for chaining. */ public Builder clearAndroidVersion() { @@ -2062,7 +3236,9 @@ public Builder clearAndroidVersion() { return this; } /** - * optional string android_version = 1; + * string android_version = 1; + * @param value The bytes for androidVersion to set. + * @return This builder for chaining. */ public Builder setAndroidVersionBytes( com.google.protobuf.ByteString value) { @@ -2076,22 +3252,161 @@ public Builder setAndroidVersionBytes( return this; } - private java.util.List imuData_ = + private float trajectoryVersion_ ; + /** + *
+       * version 2.0
+       * 
+ * + * float trajectory_version = 2; + * @return The trajectoryVersion. + */ + @java.lang.Override + public float getTrajectoryVersion() { + return trajectoryVersion_; + } + /** + *
+       * version 2.0
+       * 
+ * + * float trajectory_version = 2; + * @param value The trajectoryVersion to set. + * @return This builder for chaining. + */ + public Builder setTrajectoryVersion(float value) { + + trajectoryVersion_ = value; + onChanged(); + return this; + } + /** + *
+       * version 2.0
+       * 
+ * + * float trajectory_version = 2; + * @return This builder for chaining. + */ + public Builder clearTrajectoryVersion() { + + trajectoryVersion_ = 0F; + onChanged(); + return this; + } + + private java.lang.Object trajectoryId_ = ""; + /** + *
+       * trajectory id/name for identification
+       * 
+ * + * string trajectory_id = 3; + * @return The trajectoryId. + */ + public java.lang.String getTrajectoryId() { + java.lang.Object ref = trajectoryId_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + trajectoryId_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + *
+       * trajectory id/name for identification
+       * 
+ * + * string trajectory_id = 3; + * @return The bytes for trajectoryId. + */ + public com.google.protobuf.ByteString + getTrajectoryIdBytes() { + java.lang.Object ref = trajectoryId_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + trajectoryId_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
+       * trajectory id/name for identification
+       * 
+ * + * string trajectory_id = 3; + * @param value The trajectoryId to set. + * @return This builder for chaining. + */ + public Builder setTrajectoryId( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + trajectoryId_ = value; + onChanged(); + return this; + } + /** + *
+       * trajectory id/name for identification
+       * 
+ * + * string trajectory_id = 3; + * @return This builder for chaining. + */ + public Builder clearTrajectoryId() { + + trajectoryId_ = getDefaultInstance().getTrajectoryId(); + onChanged(); + return this; + } + /** + *
+       * trajectory id/name for identification
+       * 
+ * + * string trajectory_id = 3; + * @param value The bytes for trajectoryId to set. + * @return This builder for chaining. + */ + public Builder setTrajectoryIdBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + trajectoryId_ = value; + onChanged(); + return this; + } + + private java.util.List imuData_ = java.util.Collections.emptyList(); private void ensureImuDataIsMutable() { - if (!((bitField0_ & 0x00000002) == 0x00000002)) { - imuData_ = new java.util.ArrayList(imuData_); - bitField0_ |= 0x00000002; + if (!((bitField0_ & 0x00000001) != 0)) { + imuData_ = new java.util.ArrayList(imuData_); + bitField0_ |= 0x00000001; } } private com.google.protobuf.RepeatedFieldBuilderV3< - Motion_Sample, Motion_Sample.Builder, Motion_SampleOrBuilder> imuDataBuilder_; + Traj.IMUReading, Traj.IMUReading.Builder, Traj.IMUReadingOrBuilder> imuDataBuilder_; /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public java.util.List getImuDataList() { + public java.util.List getImuDataList() { if (imuDataBuilder_ == null) { return java.util.Collections.unmodifiableList(imuData_); } else { @@ -2099,7 +3414,7 @@ public java.util.List getImuDataList() { } } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ public int getImuDataCount() { if (imuDataBuilder_ == null) { @@ -2109,9 +3424,9 @@ public int getImuDataCount() { } } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public Motion_Sample getImuData(int index) { + public Traj.IMUReading getImuData(int index) { if (imuDataBuilder_ == null) { return imuData_.get(index); } else { @@ -2119,10 +3434,10 @@ public Motion_Sample getImuData(int index) { } } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ public Builder setImuData( - int index, Motion_Sample value) { + int index, Traj.IMUReading value) { if (imuDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -2136,10 +3451,10 @@ public Builder setImuData( return this; } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ public Builder setImuData( - int index, Motion_Sample.Builder builderForValue) { + int index, Traj.IMUReading.Builder builderForValue) { if (imuDataBuilder_ == null) { ensureImuDataIsMutable(); imuData_.set(index, builderForValue.build()); @@ -2150,9 +3465,9 @@ public Builder setImuData( return this; } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public Builder addImuData(Motion_Sample value) { + public Builder addImuData(Traj.IMUReading value) { if (imuDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -2166,10 +3481,10 @@ public Builder addImuData(Motion_Sample value) { return this; } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ public Builder addImuData( - int index, Motion_Sample value) { + int index, Traj.IMUReading value) { if (imuDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -2183,10 +3498,10 @@ public Builder addImuData( return this; } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ public Builder addImuData( - Motion_Sample.Builder builderForValue) { + Traj.IMUReading.Builder builderForValue) { if (imuDataBuilder_ == null) { ensureImuDataIsMutable(); imuData_.add(builderForValue.build()); @@ -2197,10 +3512,10 @@ public Builder addImuData( return this; } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ public Builder addImuData( - int index, Motion_Sample.Builder builderForValue) { + int index, Traj.IMUReading.Builder builderForValue) { if (imuDataBuilder_ == null) { ensureImuDataIsMutable(); imuData_.add(index, builderForValue.build()); @@ -2211,10 +3526,10 @@ public Builder addImuData( return this; } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ public Builder addAllImuData( - Iterable values) { + java.lang.Iterable values) { if (imuDataBuilder_ == null) { ensureImuDataIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll( @@ -2226,12 +3541,12 @@ public Builder addAllImuData( return this; } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ public Builder clearImuData() { if (imuDataBuilder_ == null) { imuData_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); + bitField0_ = (bitField0_ & ~0x00000001); onChanged(); } else { imuDataBuilder_.clear(); @@ -2239,7 +3554,7 @@ public Builder clearImuData() { return this; } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ public Builder removeImuData(int index) { if (imuDataBuilder_ == null) { @@ -2252,16 +3567,16 @@ public Builder removeImuData(int index) { return this; } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public Motion_Sample.Builder getImuDataBuilder( + public Traj.IMUReading.Builder getImuDataBuilder( int index) { return getImuDataFieldBuilder().getBuilder(index); } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public Motion_SampleOrBuilder getImuDataOrBuilder( + public Traj.IMUReadingOrBuilder getImuDataOrBuilder( int index) { if (imuDataBuilder_ == null) { return imuData_.get(index); } else { @@ -2269,9 +3584,9 @@ public Motion_SampleOrBuilder getImuDataOrBuilder( } } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public java.util.List + public java.util.List getImuDataOrBuilderList() { if (imuDataBuilder_ != null) { return imuDataBuilder_.getMessageOrBuilderList(); @@ -2280,35 +3595,35 @@ public Motion_SampleOrBuilder getImuDataOrBuilder( } } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public Motion_Sample.Builder addImuDataBuilder() { + public Traj.IMUReading.Builder addImuDataBuilder() { return getImuDataFieldBuilder().addBuilder( - Motion_Sample.getDefaultInstance()); + Traj.IMUReading.getDefaultInstance()); } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public Motion_Sample.Builder addImuDataBuilder( + public Traj.IMUReading.Builder addImuDataBuilder( int index) { return getImuDataFieldBuilder().addBuilder( - index, Motion_Sample.getDefaultInstance()); + index, Traj.IMUReading.getDefaultInstance()); } /** - * repeated .Motion_Sample imu_data = 2; + * repeated .IMUReading imu_data = 4; */ - public java.util.List + public java.util.List getImuDataBuilderList() { return getImuDataFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilderV3< - Motion_Sample, Motion_Sample.Builder, Motion_SampleOrBuilder> + Traj.IMUReading, Traj.IMUReading.Builder, Traj.IMUReadingOrBuilder> getImuDataFieldBuilder() { if (imuDataBuilder_ == null) { imuDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - Motion_Sample, Motion_Sample.Builder, Motion_SampleOrBuilder>( + Traj.IMUReading, Traj.IMUReading.Builder, Traj.IMUReadingOrBuilder>( imuData_, - ((bitField0_ & 0x00000002) == 0x00000002), + ((bitField0_ & 0x00000001) != 0), getParentForChildren(), isClean()); imuData_ = null; @@ -2316,22 +3631,22 @@ public Motion_Sample.Builder addImuDataBuilder( return imuDataBuilder_; } - private java.util.List pdrData_ = + private java.util.List pdrData_ = java.util.Collections.emptyList(); private void ensurePdrDataIsMutable() { - if (!((bitField0_ & 0x00000004) == 0x00000004)) { - pdrData_ = new java.util.ArrayList(pdrData_); - bitField0_ |= 0x00000004; + if (!((bitField0_ & 0x00000002) != 0)) { + pdrData_ = new java.util.ArrayList(pdrData_); + bitField0_ |= 0x00000002; } } private com.google.protobuf.RepeatedFieldBuilderV3< - Pdr_Sample, Pdr_Sample.Builder, Pdr_SampleOrBuilder> pdrDataBuilder_; + Traj.RelativePosition, Traj.RelativePosition.Builder, Traj.RelativePositionOrBuilder> pdrDataBuilder_; /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public java.util.List getPdrDataList() { + public java.util.List getPdrDataList() { if (pdrDataBuilder_ == null) { return java.util.Collections.unmodifiableList(pdrData_); } else { @@ -2339,7 +3654,7 @@ public java.util.List getPdrDataList() { } } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ public int getPdrDataCount() { if (pdrDataBuilder_ == null) { @@ -2349,9 +3664,9 @@ public int getPdrDataCount() { } } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public Pdr_Sample getPdrData(int index) { + public Traj.RelativePosition getPdrData(int index) { if (pdrDataBuilder_ == null) { return pdrData_.get(index); } else { @@ -2359,10 +3674,10 @@ public Pdr_Sample getPdrData(int index) { } } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ public Builder setPdrData( - int index, Pdr_Sample value) { + int index, Traj.RelativePosition value) { if (pdrDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -2376,10 +3691,10 @@ public Builder setPdrData( return this; } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ public Builder setPdrData( - int index, Pdr_Sample.Builder builderForValue) { + int index, Traj.RelativePosition.Builder builderForValue) { if (pdrDataBuilder_ == null) { ensurePdrDataIsMutable(); pdrData_.set(index, builderForValue.build()); @@ -2390,9 +3705,9 @@ public Builder setPdrData( return this; } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public Builder addPdrData(Pdr_Sample value) { + public Builder addPdrData(Traj.RelativePosition value) { if (pdrDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -2406,10 +3721,10 @@ public Builder addPdrData(Pdr_Sample value) { return this; } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ public Builder addPdrData( - int index, Pdr_Sample value) { + int index, Traj.RelativePosition value) { if (pdrDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -2423,10 +3738,10 @@ public Builder addPdrData( return this; } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ public Builder addPdrData( - Pdr_Sample.Builder builderForValue) { + Traj.RelativePosition.Builder builderForValue) { if (pdrDataBuilder_ == null) { ensurePdrDataIsMutable(); pdrData_.add(builderForValue.build()); @@ -2437,10 +3752,10 @@ public Builder addPdrData( return this; } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ public Builder addPdrData( - int index, Pdr_Sample.Builder builderForValue) { + int index, Traj.RelativePosition.Builder builderForValue) { if (pdrDataBuilder_ == null) { ensurePdrDataIsMutable(); pdrData_.add(index, builderForValue.build()); @@ -2451,10 +3766,10 @@ public Builder addPdrData( return this; } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ public Builder addAllPdrData( - Iterable values) { + java.lang.Iterable values) { if (pdrDataBuilder_ == null) { ensurePdrDataIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll( @@ -2466,12 +3781,12 @@ public Builder addAllPdrData( return this; } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ public Builder clearPdrData() { if (pdrDataBuilder_ == null) { pdrData_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000004); + bitField0_ = (bitField0_ & ~0x00000002); onChanged(); } else { pdrDataBuilder_.clear(); @@ -2479,7 +3794,7 @@ public Builder clearPdrData() { return this; } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ public Builder removePdrData(int index) { if (pdrDataBuilder_ == null) { @@ -2492,16 +3807,16 @@ public Builder removePdrData(int index) { return this; } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public Pdr_Sample.Builder getPdrDataBuilder( + public Traj.RelativePosition.Builder getPdrDataBuilder( int index) { return getPdrDataFieldBuilder().getBuilder(index); } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public Pdr_SampleOrBuilder getPdrDataOrBuilder( + public Traj.RelativePositionOrBuilder getPdrDataOrBuilder( int index) { if (pdrDataBuilder_ == null) { return pdrData_.get(index); } else { @@ -2509,9 +3824,9 @@ public Pdr_SampleOrBuilder getPdrDataOrBuilder( } } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public java.util.List + public java.util.List getPdrDataOrBuilderList() { if (pdrDataBuilder_ != null) { return pdrDataBuilder_.getMessageOrBuilderList(); @@ -2520,35 +3835,35 @@ public Pdr_SampleOrBuilder getPdrDataOrBuilder( } } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public Pdr_Sample.Builder addPdrDataBuilder() { + public Traj.RelativePosition.Builder addPdrDataBuilder() { return getPdrDataFieldBuilder().addBuilder( - Pdr_Sample.getDefaultInstance()); + Traj.RelativePosition.getDefaultInstance()); } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public Pdr_Sample.Builder addPdrDataBuilder( + public Traj.RelativePosition.Builder addPdrDataBuilder( int index) { return getPdrDataFieldBuilder().addBuilder( - index, Pdr_Sample.getDefaultInstance()); + index, Traj.RelativePosition.getDefaultInstance()); } /** - * repeated .Pdr_Sample pdr_data = 3; + * repeated .RelativePosition pdr_data = 5; */ - public java.util.List + public java.util.List getPdrDataBuilderList() { return getPdrDataFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilderV3< - Pdr_Sample, Pdr_Sample.Builder, Pdr_SampleOrBuilder> + Traj.RelativePosition, Traj.RelativePosition.Builder, Traj.RelativePositionOrBuilder> getPdrDataFieldBuilder() { if (pdrDataBuilder_ == null) { pdrDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - Pdr_Sample, Pdr_Sample.Builder, Pdr_SampleOrBuilder>( + Traj.RelativePosition, Traj.RelativePosition.Builder, Traj.RelativePositionOrBuilder>( pdrData_, - ((bitField0_ & 0x00000004) == 0x00000004), + ((bitField0_ & 0x00000002) != 0), getParentForChildren(), isClean()); pdrData_ = null; @@ -2556,262 +3871,262 @@ public Pdr_Sample.Builder addPdrDataBuilder( return pdrDataBuilder_; } - private java.util.List positionData_ = + private java.util.List magnetometerData_ = java.util.Collections.emptyList(); - private void ensurePositionDataIsMutable() { - if (!((bitField0_ & 0x00000008) == 0x00000008)) { - positionData_ = new java.util.ArrayList(positionData_); - bitField0_ |= 0x00000008; + private void ensureMagnetometerDataIsMutable() { + if (!((bitField0_ & 0x00000004) != 0)) { + magnetometerData_ = new java.util.ArrayList(magnetometerData_); + bitField0_ |= 0x00000004; } } private com.google.protobuf.RepeatedFieldBuilderV3< - Position_Sample, Position_Sample.Builder, Position_SampleOrBuilder> positionDataBuilder_; + Traj.MagnetometerReading, Traj.MagnetometerReading.Builder, Traj.MagnetometerReadingOrBuilder> magnetometerDataBuilder_; /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public java.util.List getPositionDataList() { - if (positionDataBuilder_ == null) { - return java.util.Collections.unmodifiableList(positionData_); + public java.util.List getMagnetometerDataList() { + if (magnetometerDataBuilder_ == null) { + return java.util.Collections.unmodifiableList(magnetometerData_); } else { - return positionDataBuilder_.getMessageList(); + return magnetometerDataBuilder_.getMessageList(); } } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public int getPositionDataCount() { - if (positionDataBuilder_ == null) { - return positionData_.size(); + public int getMagnetometerDataCount() { + if (magnetometerDataBuilder_ == null) { + return magnetometerData_.size(); } else { - return positionDataBuilder_.getCount(); + return magnetometerDataBuilder_.getCount(); } } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Position_Sample getPositionData(int index) { - if (positionDataBuilder_ == null) { - return positionData_.get(index); + public Traj.MagnetometerReading getMagnetometerData(int index) { + if (magnetometerDataBuilder_ == null) { + return magnetometerData_.get(index); } else { - return positionDataBuilder_.getMessage(index); + return magnetometerDataBuilder_.getMessage(index); } } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Builder setPositionData( - int index, Position_Sample value) { - if (positionDataBuilder_ == null) { + public Builder setMagnetometerData( + int index, Traj.MagnetometerReading value) { + if (magnetometerDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensurePositionDataIsMutable(); - positionData_.set(index, value); + ensureMagnetometerDataIsMutable(); + magnetometerData_.set(index, value); onChanged(); } else { - positionDataBuilder_.setMessage(index, value); + magnetometerDataBuilder_.setMessage(index, value); } return this; } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Builder setPositionData( - int index, Position_Sample.Builder builderForValue) { - if (positionDataBuilder_ == null) { - ensurePositionDataIsMutable(); - positionData_.set(index, builderForValue.build()); + public Builder setMagnetometerData( + int index, Traj.MagnetometerReading.Builder builderForValue) { + if (magnetometerDataBuilder_ == null) { + ensureMagnetometerDataIsMutable(); + magnetometerData_.set(index, builderForValue.build()); onChanged(); } else { - positionDataBuilder_.setMessage(index, builderForValue.build()); + magnetometerDataBuilder_.setMessage(index, builderForValue.build()); } return this; } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Builder addPositionData(Position_Sample value) { - if (positionDataBuilder_ == null) { + public Builder addMagnetometerData(Traj.MagnetometerReading value) { + if (magnetometerDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensurePositionDataIsMutable(); - positionData_.add(value); + ensureMagnetometerDataIsMutable(); + magnetometerData_.add(value); onChanged(); } else { - positionDataBuilder_.addMessage(value); + magnetometerDataBuilder_.addMessage(value); } return this; } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Builder addPositionData( - int index, Position_Sample value) { - if (positionDataBuilder_ == null) { + public Builder addMagnetometerData( + int index, Traj.MagnetometerReading value) { + if (magnetometerDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensurePositionDataIsMutable(); - positionData_.add(index, value); + ensureMagnetometerDataIsMutable(); + magnetometerData_.add(index, value); onChanged(); } else { - positionDataBuilder_.addMessage(index, value); + magnetometerDataBuilder_.addMessage(index, value); } return this; } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Builder addPositionData( - Position_Sample.Builder builderForValue) { - if (positionDataBuilder_ == null) { - ensurePositionDataIsMutable(); - positionData_.add(builderForValue.build()); + public Builder addMagnetometerData( + Traj.MagnetometerReading.Builder builderForValue) { + if (magnetometerDataBuilder_ == null) { + ensureMagnetometerDataIsMutable(); + magnetometerData_.add(builderForValue.build()); onChanged(); } else { - positionDataBuilder_.addMessage(builderForValue.build()); + magnetometerDataBuilder_.addMessage(builderForValue.build()); } return this; } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Builder addPositionData( - int index, Position_Sample.Builder builderForValue) { - if (positionDataBuilder_ == null) { - ensurePositionDataIsMutable(); - positionData_.add(index, builderForValue.build()); + public Builder addMagnetometerData( + int index, Traj.MagnetometerReading.Builder builderForValue) { + if (magnetometerDataBuilder_ == null) { + ensureMagnetometerDataIsMutable(); + magnetometerData_.add(index, builderForValue.build()); onChanged(); } else { - positionDataBuilder_.addMessage(index, builderForValue.build()); + magnetometerDataBuilder_.addMessage(index, builderForValue.build()); } return this; } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Builder addAllPositionData( - Iterable values) { - if (positionDataBuilder_ == null) { - ensurePositionDataIsMutable(); + public Builder addAllMagnetometerData( + java.lang.Iterable values) { + if (magnetometerDataBuilder_ == null) { + ensureMagnetometerDataIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, positionData_); + values, magnetometerData_); onChanged(); } else { - positionDataBuilder_.addAllMessages(values); + magnetometerDataBuilder_.addAllMessages(values); } return this; } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Builder clearPositionData() { - if (positionDataBuilder_ == null) { - positionData_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000008); + public Builder clearMagnetometerData() { + if (magnetometerDataBuilder_ == null) { + magnetometerData_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000004); onChanged(); } else { - positionDataBuilder_.clear(); + magnetometerDataBuilder_.clear(); } return this; } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Builder removePositionData(int index) { - if (positionDataBuilder_ == null) { - ensurePositionDataIsMutable(); - positionData_.remove(index); + public Builder removeMagnetometerData(int index) { + if (magnetometerDataBuilder_ == null) { + ensureMagnetometerDataIsMutable(); + magnetometerData_.remove(index); onChanged(); } else { - positionDataBuilder_.remove(index); + magnetometerDataBuilder_.remove(index); } return this; } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Position_Sample.Builder getPositionDataBuilder( + public Traj.MagnetometerReading.Builder getMagnetometerDataBuilder( int index) { - return getPositionDataFieldBuilder().getBuilder(index); + return getMagnetometerDataFieldBuilder().getBuilder(index); } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Position_SampleOrBuilder getPositionDataOrBuilder( + public Traj.MagnetometerReadingOrBuilder getMagnetometerDataOrBuilder( int index) { - if (positionDataBuilder_ == null) { - return positionData_.get(index); } else { - return positionDataBuilder_.getMessageOrBuilder(index); + if (magnetometerDataBuilder_ == null) { + return magnetometerData_.get(index); } else { + return magnetometerDataBuilder_.getMessageOrBuilder(index); } } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public java.util.List - getPositionDataOrBuilderList() { - if (positionDataBuilder_ != null) { - return positionDataBuilder_.getMessageOrBuilderList(); + public java.util.List + getMagnetometerDataOrBuilderList() { + if (magnetometerDataBuilder_ != null) { + return magnetometerDataBuilder_.getMessageOrBuilderList(); } else { - return java.util.Collections.unmodifiableList(positionData_); + return java.util.Collections.unmodifiableList(magnetometerData_); } } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Position_Sample.Builder addPositionDataBuilder() { - return getPositionDataFieldBuilder().addBuilder( - Position_Sample.getDefaultInstance()); + public Traj.MagnetometerReading.Builder addMagnetometerDataBuilder() { + return getMagnetometerDataFieldBuilder().addBuilder( + Traj.MagnetometerReading.getDefaultInstance()); } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public Position_Sample.Builder addPositionDataBuilder( + public Traj.MagnetometerReading.Builder addMagnetometerDataBuilder( int index) { - return getPositionDataFieldBuilder().addBuilder( - index, Position_Sample.getDefaultInstance()); + return getMagnetometerDataFieldBuilder().addBuilder( + index, Traj.MagnetometerReading.getDefaultInstance()); } /** - * repeated .Position_Sample position_data = 4; + * repeated .MagnetometerReading magnetometer_data = 6; */ - public java.util.List - getPositionDataBuilderList() { - return getPositionDataFieldBuilder().getBuilderList(); + public java.util.List + getMagnetometerDataBuilderList() { + return getMagnetometerDataFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilderV3< - Position_Sample, Position_Sample.Builder, Position_SampleOrBuilder> - getPositionDataFieldBuilder() { - if (positionDataBuilder_ == null) { - positionDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - Position_Sample, Position_Sample.Builder, Position_SampleOrBuilder>( - positionData_, - ((bitField0_ & 0x00000008) == 0x00000008), + Traj.MagnetometerReading, Traj.MagnetometerReading.Builder, Traj.MagnetometerReadingOrBuilder> + getMagnetometerDataFieldBuilder() { + if (magnetometerDataBuilder_ == null) { + magnetometerDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + Traj.MagnetometerReading, Traj.MagnetometerReading.Builder, Traj.MagnetometerReadingOrBuilder>( + magnetometerData_, + ((bitField0_ & 0x00000004) != 0), getParentForChildren(), isClean()); - positionData_ = null; + magnetometerData_ = null; } - return positionDataBuilder_; + return magnetometerDataBuilder_; } - private java.util.List pressureData_ = + private java.util.List pressureData_ = java.util.Collections.emptyList(); private void ensurePressureDataIsMutable() { - if (!((bitField0_ & 0x00000010) == 0x00000010)) { - pressureData_ = new java.util.ArrayList(pressureData_); - bitField0_ |= 0x00000010; + if (!((bitField0_ & 0x00000008) != 0)) { + pressureData_ = new java.util.ArrayList(pressureData_); + bitField0_ |= 0x00000008; } } private com.google.protobuf.RepeatedFieldBuilderV3< - Pressure_Sample, Pressure_Sample.Builder, Pressure_SampleOrBuilder> pressureDataBuilder_; + Traj.BarometerReading, Traj.BarometerReading.Builder, Traj.BarometerReadingOrBuilder> pressureDataBuilder_; /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public java.util.List getPressureDataList() { + public java.util.List getPressureDataList() { if (pressureDataBuilder_ == null) { return java.util.Collections.unmodifiableList(pressureData_); } else { @@ -2819,7 +4134,7 @@ public java.util.List getPressureDataList() { } } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ public int getPressureDataCount() { if (pressureDataBuilder_ == null) { @@ -2829,9 +4144,9 @@ public int getPressureDataCount() { } } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public Pressure_Sample getPressureData(int index) { + public Traj.BarometerReading getPressureData(int index) { if (pressureDataBuilder_ == null) { return pressureData_.get(index); } else { @@ -2839,10 +4154,10 @@ public Pressure_Sample getPressureData(int index) { } } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ public Builder setPressureData( - int index, Pressure_Sample value) { + int index, Traj.BarometerReading value) { if (pressureDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -2856,10 +4171,10 @@ public Builder setPressureData( return this; } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ public Builder setPressureData( - int index, Pressure_Sample.Builder builderForValue) { + int index, Traj.BarometerReading.Builder builderForValue) { if (pressureDataBuilder_ == null) { ensurePressureDataIsMutable(); pressureData_.set(index, builderForValue.build()); @@ -2870,9 +4185,9 @@ public Builder setPressureData( return this; } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public Builder addPressureData(Pressure_Sample value) { + public Builder addPressureData(Traj.BarometerReading value) { if (pressureDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -2886,10 +4201,10 @@ public Builder addPressureData(Pressure_Sample value) { return this; } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ public Builder addPressureData( - int index, Pressure_Sample value) { + int index, Traj.BarometerReading value) { if (pressureDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -2903,10 +4218,10 @@ public Builder addPressureData( return this; } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ public Builder addPressureData( - Pressure_Sample.Builder builderForValue) { + Traj.BarometerReading.Builder builderForValue) { if (pressureDataBuilder_ == null) { ensurePressureDataIsMutable(); pressureData_.add(builderForValue.build()); @@ -2917,10 +4232,10 @@ public Builder addPressureData( return this; } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ public Builder addPressureData( - int index, Pressure_Sample.Builder builderForValue) { + int index, Traj.BarometerReading.Builder builderForValue) { if (pressureDataBuilder_ == null) { ensurePressureDataIsMutable(); pressureData_.add(index, builderForValue.build()); @@ -2931,10 +4246,10 @@ public Builder addPressureData( return this; } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ public Builder addAllPressureData( - Iterable values) { + java.lang.Iterable values) { if (pressureDataBuilder_ == null) { ensurePressureDataIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll( @@ -2946,12 +4261,12 @@ public Builder addAllPressureData( return this; } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ public Builder clearPressureData() { if (pressureDataBuilder_ == null) { pressureData_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000010); + bitField0_ = (bitField0_ & ~0x00000008); onChanged(); } else { pressureDataBuilder_.clear(); @@ -2959,7 +4274,7 @@ public Builder clearPressureData() { return this; } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ public Builder removePressureData(int index) { if (pressureDataBuilder_ == null) { @@ -2972,16 +4287,16 @@ public Builder removePressureData(int index) { return this; } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public Pressure_Sample.Builder getPressureDataBuilder( + public Traj.BarometerReading.Builder getPressureDataBuilder( int index) { return getPressureDataFieldBuilder().getBuilder(index); } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public Pressure_SampleOrBuilder getPressureDataOrBuilder( + public Traj.BarometerReadingOrBuilder getPressureDataOrBuilder( int index) { if (pressureDataBuilder_ == null) { return pressureData_.get(index); } else { @@ -2989,9 +4304,9 @@ public Pressure_SampleOrBuilder getPressureDataOrBuilder( } } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public java.util.List + public java.util.List getPressureDataOrBuilderList() { if (pressureDataBuilder_ != null) { return pressureDataBuilder_.getMessageOrBuilderList(); @@ -3000,35 +4315,35 @@ public Pressure_SampleOrBuilder getPressureDataOrBuilder( } } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public Pressure_Sample.Builder addPressureDataBuilder() { + public Traj.BarometerReading.Builder addPressureDataBuilder() { return getPressureDataFieldBuilder().addBuilder( - Pressure_Sample.getDefaultInstance()); + Traj.BarometerReading.getDefaultInstance()); } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public Pressure_Sample.Builder addPressureDataBuilder( + public Traj.BarometerReading.Builder addPressureDataBuilder( int index) { return getPressureDataFieldBuilder().addBuilder( - index, Pressure_Sample.getDefaultInstance()); + index, Traj.BarometerReading.getDefaultInstance()); } /** - * repeated .Pressure_Sample pressure_data = 5; + * repeated .BarometerReading pressure_data = 7; */ - public java.util.List + public java.util.List getPressureDataBuilderList() { return getPressureDataFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilderV3< - Pressure_Sample, Pressure_Sample.Builder, Pressure_SampleOrBuilder> + Traj.BarometerReading, Traj.BarometerReading.Builder, Traj.BarometerReadingOrBuilder> getPressureDataFieldBuilder() { if (pressureDataBuilder_ == null) { pressureDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - Pressure_Sample, Pressure_Sample.Builder, Pressure_SampleOrBuilder>( + Traj.BarometerReading, Traj.BarometerReading.Builder, Traj.BarometerReadingOrBuilder>( pressureData_, - ((bitField0_ & 0x00000010) == 0x00000010), + ((bitField0_ & 0x00000008) != 0), getParentForChildren(), isClean()); pressureData_ = null; @@ -3036,22 +4351,22 @@ public Pressure_Sample.Builder addPressureDataBuilder( return pressureDataBuilder_; } - private java.util.List lightData_ = + private java.util.List lightData_ = java.util.Collections.emptyList(); private void ensureLightDataIsMutable() { - if (!((bitField0_ & 0x00000020) == 0x00000020)) { - lightData_ = new java.util.ArrayList(lightData_); - bitField0_ |= 0x00000020; + if (!((bitField0_ & 0x00000010) != 0)) { + lightData_ = new java.util.ArrayList(lightData_); + bitField0_ |= 0x00000010; } } private com.google.protobuf.RepeatedFieldBuilderV3< - Light_Sample, Light_Sample.Builder, Light_SampleOrBuilder> lightDataBuilder_; + Traj.LightReading, Traj.LightReading.Builder, Traj.LightReadingOrBuilder> lightDataBuilder_; /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public java.util.List getLightDataList() { + public java.util.List getLightDataList() { if (lightDataBuilder_ == null) { return java.util.Collections.unmodifiableList(lightData_); } else { @@ -3059,7 +4374,7 @@ public java.util.List getLightDataList() { } } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ public int getLightDataCount() { if (lightDataBuilder_ == null) { @@ -3069,9 +4384,9 @@ public int getLightDataCount() { } } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public Light_Sample getLightData(int index) { + public Traj.LightReading getLightData(int index) { if (lightDataBuilder_ == null) { return lightData_.get(index); } else { @@ -3079,10 +4394,10 @@ public Light_Sample getLightData(int index) { } } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ public Builder setLightData( - int index, Light_Sample value) { + int index, Traj.LightReading value) { if (lightDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -3096,10 +4411,10 @@ public Builder setLightData( return this; } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ public Builder setLightData( - int index, Light_Sample.Builder builderForValue) { + int index, Traj.LightReading.Builder builderForValue) { if (lightDataBuilder_ == null) { ensureLightDataIsMutable(); lightData_.set(index, builderForValue.build()); @@ -3110,9 +4425,9 @@ public Builder setLightData( return this; } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public Builder addLightData(Light_Sample value) { + public Builder addLightData(Traj.LightReading value) { if (lightDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -3126,10 +4441,10 @@ public Builder addLightData(Light_Sample value) { return this; } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ public Builder addLightData( - int index, Light_Sample value) { + int index, Traj.LightReading value) { if (lightDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -3143,10 +4458,10 @@ public Builder addLightData( return this; } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ public Builder addLightData( - Light_Sample.Builder builderForValue) { + Traj.LightReading.Builder builderForValue) { if (lightDataBuilder_ == null) { ensureLightDataIsMutable(); lightData_.add(builderForValue.build()); @@ -3157,10 +4472,10 @@ public Builder addLightData( return this; } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ public Builder addLightData( - int index, Light_Sample.Builder builderForValue) { + int index, Traj.LightReading.Builder builderForValue) { if (lightDataBuilder_ == null) { ensureLightDataIsMutable(); lightData_.add(index, builderForValue.build()); @@ -3171,10 +4486,10 @@ public Builder addLightData( return this; } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ public Builder addAllLightData( - Iterable values) { + java.lang.Iterable values) { if (lightDataBuilder_ == null) { ensureLightDataIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll( @@ -3186,12 +4501,12 @@ public Builder addAllLightData( return this; } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ public Builder clearLightData() { if (lightDataBuilder_ == null) { lightData_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000020); + bitField0_ = (bitField0_ & ~0x00000010); onChanged(); } else { lightDataBuilder_.clear(); @@ -3199,7 +4514,7 @@ public Builder clearLightData() { return this; } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ public Builder removeLightData(int index) { if (lightDataBuilder_ == null) { @@ -3212,16 +4527,16 @@ public Builder removeLightData(int index) { return this; } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public Light_Sample.Builder getLightDataBuilder( + public Traj.LightReading.Builder getLightDataBuilder( int index) { return getLightDataFieldBuilder().getBuilder(index); } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public Light_SampleOrBuilder getLightDataOrBuilder( + public Traj.LightReadingOrBuilder getLightDataOrBuilder( int index) { if (lightDataBuilder_ == null) { return lightData_.get(index); } else { @@ -3229,9 +4544,9 @@ public Light_SampleOrBuilder getLightDataOrBuilder( } } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public java.util.List + public java.util.List getLightDataOrBuilderList() { if (lightDataBuilder_ != null) { return lightDataBuilder_.getMessageOrBuilderList(); @@ -3240,35 +4555,35 @@ public Light_SampleOrBuilder getLightDataOrBuilder( } } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public Light_Sample.Builder addLightDataBuilder() { + public Traj.LightReading.Builder addLightDataBuilder() { return getLightDataFieldBuilder().addBuilder( - Light_Sample.getDefaultInstance()); + Traj.LightReading.getDefaultInstance()); } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public Light_Sample.Builder addLightDataBuilder( + public Traj.LightReading.Builder addLightDataBuilder( int index) { return getLightDataFieldBuilder().addBuilder( - index, Light_Sample.getDefaultInstance()); + index, Traj.LightReading.getDefaultInstance()); } /** - * repeated .Light_Sample light_data = 6; + * repeated .LightReading light_data = 8; */ - public java.util.List + public java.util.List getLightDataBuilderList() { return getLightDataFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilderV3< - Light_Sample, Light_Sample.Builder, Light_SampleOrBuilder> + Traj.LightReading, Traj.LightReading.Builder, Traj.LightReadingOrBuilder> getLightDataFieldBuilder() { if (lightDataBuilder_ == null) { lightDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - Light_Sample, Light_Sample.Builder, Light_SampleOrBuilder>( + Traj.LightReading, Traj.LightReading.Builder, Traj.LightReadingOrBuilder>( lightData_, - ((bitField0_ & 0x00000020) == 0x00000020), + ((bitField0_ & 0x00000010) != 0), getParentForChildren(), isClean()); lightData_ = null; @@ -3276,502 +4591,742 @@ public Light_Sample.Builder addLightDataBuilder( return lightDataBuilder_; } - private java.util.List gnssData_ = + private java.util.List proximityData_ = java.util.Collections.emptyList(); - private void ensureGnssDataIsMutable() { - if (!((bitField0_ & 0x00000040) == 0x00000040)) { - gnssData_ = new java.util.ArrayList(gnssData_); - bitField0_ |= 0x00000040; + private void ensureProximityDataIsMutable() { + if (!((bitField0_ & 0x00000020) != 0)) { + proximityData_ = new java.util.ArrayList(proximityData_); + bitField0_ |= 0x00000020; } } private com.google.protobuf.RepeatedFieldBuilderV3< - GNSS_Sample, GNSS_Sample.Builder, GNSS_SampleOrBuilder> gnssDataBuilder_; + Traj.ProximityReading, Traj.ProximityReading.Builder, Traj.ProximityReadingOrBuilder> proximityDataBuilder_; /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public java.util.List getGnssDataList() { - if (gnssDataBuilder_ == null) { - return java.util.Collections.unmodifiableList(gnssData_); + public java.util.List getProximityDataList() { + if (proximityDataBuilder_ == null) { + return java.util.Collections.unmodifiableList(proximityData_); } else { - return gnssDataBuilder_.getMessageList(); + return proximityDataBuilder_.getMessageList(); } } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public int getGnssDataCount() { - if (gnssDataBuilder_ == null) { - return gnssData_.size(); + public int getProximityDataCount() { + if (proximityDataBuilder_ == null) { + return proximityData_.size(); } else { - return gnssDataBuilder_.getCount(); + return proximityDataBuilder_.getCount(); } } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public GNSS_Sample getGnssData(int index) { - if (gnssDataBuilder_ == null) { - return gnssData_.get(index); + public Traj.ProximityReading getProximityData(int index) { + if (proximityDataBuilder_ == null) { + return proximityData_.get(index); } else { - return gnssDataBuilder_.getMessage(index); + return proximityDataBuilder_.getMessage(index); } } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public Builder setGnssData( - int index, GNSS_Sample value) { - if (gnssDataBuilder_ == null) { + public Builder setProximityData( + int index, Traj.ProximityReading value) { + if (proximityDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureGnssDataIsMutable(); - gnssData_.set(index, value); + ensureProximityDataIsMutable(); + proximityData_.set(index, value); onChanged(); } else { - gnssDataBuilder_.setMessage(index, value); + proximityDataBuilder_.setMessage(index, value); } return this; } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public Builder setGnssData( - int index, GNSS_Sample.Builder builderForValue) { - if (gnssDataBuilder_ == null) { - ensureGnssDataIsMutable(); - gnssData_.set(index, builderForValue.build()); + public Builder setProximityData( + int index, Traj.ProximityReading.Builder builderForValue) { + if (proximityDataBuilder_ == null) { + ensureProximityDataIsMutable(); + proximityData_.set(index, builderForValue.build()); onChanged(); } else { - gnssDataBuilder_.setMessage(index, builderForValue.build()); + proximityDataBuilder_.setMessage(index, builderForValue.build()); } return this; } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public Builder addGnssData(GNSS_Sample value) { - if (gnssDataBuilder_ == null) { + public Builder addProximityData(Traj.ProximityReading value) { + if (proximityDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureGnssDataIsMutable(); - gnssData_.add(value); + ensureProximityDataIsMutable(); + proximityData_.add(value); onChanged(); } else { - gnssDataBuilder_.addMessage(value); + proximityDataBuilder_.addMessage(value); } return this; } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public Builder addGnssData( - int index, GNSS_Sample value) { - if (gnssDataBuilder_ == null) { + public Builder addProximityData( + int index, Traj.ProximityReading value) { + if (proximityDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureGnssDataIsMutable(); - gnssData_.add(index, value); + ensureProximityDataIsMutable(); + proximityData_.add(index, value); onChanged(); } else { - gnssDataBuilder_.addMessage(index, value); + proximityDataBuilder_.addMessage(index, value); } return this; } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public Builder addGnssData( - GNSS_Sample.Builder builderForValue) { - if (gnssDataBuilder_ == null) { - ensureGnssDataIsMutable(); - gnssData_.add(builderForValue.build()); + public Builder addProximityData( + Traj.ProximityReading.Builder builderForValue) { + if (proximityDataBuilder_ == null) { + ensureProximityDataIsMutable(); + proximityData_.add(builderForValue.build()); onChanged(); } else { - gnssDataBuilder_.addMessage(builderForValue.build()); + proximityDataBuilder_.addMessage(builderForValue.build()); } return this; } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public Builder addGnssData( - int index, GNSS_Sample.Builder builderForValue) { - if (gnssDataBuilder_ == null) { - ensureGnssDataIsMutable(); - gnssData_.add(index, builderForValue.build()); + public Builder addProximityData( + int index, Traj.ProximityReading.Builder builderForValue) { + if (proximityDataBuilder_ == null) { + ensureProximityDataIsMutable(); + proximityData_.add(index, builderForValue.build()); onChanged(); } else { - gnssDataBuilder_.addMessage(index, builderForValue.build()); + proximityDataBuilder_.addMessage(index, builderForValue.build()); } return this; } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public Builder addAllGnssData( - Iterable values) { - if (gnssDataBuilder_ == null) { - ensureGnssDataIsMutable(); + public Builder addAllProximityData( + java.lang.Iterable values) { + if (proximityDataBuilder_ == null) { + ensureProximityDataIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, gnssData_); + values, proximityData_); onChanged(); } else { - gnssDataBuilder_.addAllMessages(values); + proximityDataBuilder_.addAllMessages(values); } return this; } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public Builder clearGnssData() { - if (gnssDataBuilder_ == null) { - gnssData_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000040); + public Builder clearProximityData() { + if (proximityDataBuilder_ == null) { + proximityData_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000020); onChanged(); } else { - gnssDataBuilder_.clear(); + proximityDataBuilder_.clear(); } return this; } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public Builder removeGnssData(int index) { - if (gnssDataBuilder_ == null) { - ensureGnssDataIsMutable(); - gnssData_.remove(index); + public Builder removeProximityData(int index) { + if (proximityDataBuilder_ == null) { + ensureProximityDataIsMutable(); + proximityData_.remove(index); onChanged(); } else { - gnssDataBuilder_.remove(index); + proximityDataBuilder_.remove(index); } return this; } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public GNSS_Sample.Builder getGnssDataBuilder( + public Traj.ProximityReading.Builder getProximityDataBuilder( int index) { - return getGnssDataFieldBuilder().getBuilder(index); + return getProximityDataFieldBuilder().getBuilder(index); } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public GNSS_SampleOrBuilder getGnssDataOrBuilder( + public Traj.ProximityReadingOrBuilder getProximityDataOrBuilder( int index) { - if (gnssDataBuilder_ == null) { - return gnssData_.get(index); } else { - return gnssDataBuilder_.getMessageOrBuilder(index); + if (proximityDataBuilder_ == null) { + return proximityData_.get(index); } else { + return proximityDataBuilder_.getMessageOrBuilder(index); } } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public java.util.List - getGnssDataOrBuilderList() { - if (gnssDataBuilder_ != null) { - return gnssDataBuilder_.getMessageOrBuilderList(); + public java.util.List + getProximityDataOrBuilderList() { + if (proximityDataBuilder_ != null) { + return proximityDataBuilder_.getMessageOrBuilderList(); } else { - return java.util.Collections.unmodifiableList(gnssData_); + return java.util.Collections.unmodifiableList(proximityData_); } } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public GNSS_Sample.Builder addGnssDataBuilder() { - return getGnssDataFieldBuilder().addBuilder( - GNSS_Sample.getDefaultInstance()); + public Traj.ProximityReading.Builder addProximityDataBuilder() { + return getProximityDataFieldBuilder().addBuilder( + Traj.ProximityReading.getDefaultInstance()); } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public GNSS_Sample.Builder addGnssDataBuilder( + public Traj.ProximityReading.Builder addProximityDataBuilder( int index) { - return getGnssDataFieldBuilder().addBuilder( - index, GNSS_Sample.getDefaultInstance()); + return getProximityDataFieldBuilder().addBuilder( + index, Traj.ProximityReading.getDefaultInstance()); } /** - * repeated .GNSS_Sample gnss_data = 7; + * repeated .ProximityReading proximity_data = 9; */ - public java.util.List - getGnssDataBuilderList() { - return getGnssDataFieldBuilder().getBuilderList(); + public java.util.List + getProximityDataBuilderList() { + return getProximityDataFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilderV3< - GNSS_Sample, GNSS_Sample.Builder, GNSS_SampleOrBuilder> - getGnssDataFieldBuilder() { - if (gnssDataBuilder_ == null) { - gnssDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - GNSS_Sample, GNSS_Sample.Builder, GNSS_SampleOrBuilder>( - gnssData_, - ((bitField0_ & 0x00000040) == 0x00000040), + Traj.ProximityReading, Traj.ProximityReading.Builder, Traj.ProximityReadingOrBuilder> + getProximityDataFieldBuilder() { + if (proximityDataBuilder_ == null) { + proximityDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + Traj.ProximityReading, Traj.ProximityReading.Builder, Traj.ProximityReadingOrBuilder>( + proximityData_, + ((bitField0_ & 0x00000020) != 0), getParentForChildren(), isClean()); - gnssData_ = null; + proximityData_ = null; } - return gnssDataBuilder_; + return proximityDataBuilder_; } - private java.util.List wifiData_ = + private java.util.List gnssData_ = java.util.Collections.emptyList(); - private void ensureWifiDataIsMutable() { - if (!((bitField0_ & 0x00000080) == 0x00000080)) { - wifiData_ = new java.util.ArrayList(wifiData_); - bitField0_ |= 0x00000080; + private void ensureGnssDataIsMutable() { + if (!((bitField0_ & 0x00000040) != 0)) { + gnssData_ = new java.util.ArrayList(gnssData_); + bitField0_ |= 0x00000040; } } private com.google.protobuf.RepeatedFieldBuilderV3< - WiFi_Sample, WiFi_Sample.Builder, WiFi_SampleOrBuilder> wifiDataBuilder_; + Traj.GNSSReading, Traj.GNSSReading.Builder, Traj.GNSSReadingOrBuilder> gnssDataBuilder_; /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .GNSSReading gnss_data = 10; */ - public java.util.List getWifiDataList() { - if (wifiDataBuilder_ == null) { - return java.util.Collections.unmodifiableList(wifiData_); + public java.util.List getGnssDataList() { + if (gnssDataBuilder_ == null) { + return java.util.Collections.unmodifiableList(gnssData_); } else { - return wifiDataBuilder_.getMessageList(); + return gnssDataBuilder_.getMessageList(); } } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .GNSSReading gnss_data = 10; */ - public int getWifiDataCount() { - if (wifiDataBuilder_ == null) { - return wifiData_.size(); + public int getGnssDataCount() { + if (gnssDataBuilder_ == null) { + return gnssData_.size(); + } else { + return gnssDataBuilder_.getCount(); + } + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Traj.GNSSReading getGnssData(int index) { + if (gnssDataBuilder_ == null) { + return gnssData_.get(index); + } else { + return gnssDataBuilder_.getMessage(index); + } + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Builder setGnssData( + int index, Traj.GNSSReading value) { + if (gnssDataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureGnssDataIsMutable(); + gnssData_.set(index, value); + onChanged(); + } else { + gnssDataBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Builder setGnssData( + int index, Traj.GNSSReading.Builder builderForValue) { + if (gnssDataBuilder_ == null) { + ensureGnssDataIsMutable(); + gnssData_.set(index, builderForValue.build()); + onChanged(); + } else { + gnssDataBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Builder addGnssData(Traj.GNSSReading value) { + if (gnssDataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureGnssDataIsMutable(); + gnssData_.add(value); + onChanged(); + } else { + gnssDataBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Builder addGnssData( + int index, Traj.GNSSReading value) { + if (gnssDataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureGnssDataIsMutable(); + gnssData_.add(index, value); + onChanged(); + } else { + gnssDataBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Builder addGnssData( + Traj.GNSSReading.Builder builderForValue) { + if (gnssDataBuilder_ == null) { + ensureGnssDataIsMutable(); + gnssData_.add(builderForValue.build()); + onChanged(); + } else { + gnssDataBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Builder addGnssData( + int index, Traj.GNSSReading.Builder builderForValue) { + if (gnssDataBuilder_ == null) { + ensureGnssDataIsMutable(); + gnssData_.add(index, builderForValue.build()); + onChanged(); + } else { + gnssDataBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Builder addAllGnssData( + java.lang.Iterable values) { + if (gnssDataBuilder_ == null) { + ensureGnssDataIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, gnssData_); + onChanged(); + } else { + gnssDataBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Builder clearGnssData() { + if (gnssDataBuilder_ == null) { + gnssData_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000040); + onChanged(); + } else { + gnssDataBuilder_.clear(); + } + return this; + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Builder removeGnssData(int index) { + if (gnssDataBuilder_ == null) { + ensureGnssDataIsMutable(); + gnssData_.remove(index); + onChanged(); + } else { + gnssDataBuilder_.remove(index); + } + return this; + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Traj.GNSSReading.Builder getGnssDataBuilder( + int index) { + return getGnssDataFieldBuilder().getBuilder(index); + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Traj.GNSSReadingOrBuilder getGnssDataOrBuilder( + int index) { + if (gnssDataBuilder_ == null) { + return gnssData_.get(index); } else { + return gnssDataBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public java.util.List + getGnssDataOrBuilderList() { + if (gnssDataBuilder_ != null) { + return gnssDataBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(gnssData_); + } + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Traj.GNSSReading.Builder addGnssDataBuilder() { + return getGnssDataFieldBuilder().addBuilder( + Traj.GNSSReading.getDefaultInstance()); + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public Traj.GNSSReading.Builder addGnssDataBuilder( + int index) { + return getGnssDataFieldBuilder().addBuilder( + index, Traj.GNSSReading.getDefaultInstance()); + } + /** + * repeated .GNSSReading gnss_data = 10; + */ + public java.util.List + getGnssDataBuilderList() { + return getGnssDataFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.GNSSReading, Traj.GNSSReading.Builder, Traj.GNSSReadingOrBuilder> + getGnssDataFieldBuilder() { + if (gnssDataBuilder_ == null) { + gnssDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + Traj.GNSSReading, Traj.GNSSReading.Builder, Traj.GNSSReadingOrBuilder>( + gnssData_, + ((bitField0_ & 0x00000040) != 0), + getParentForChildren(), + isClean()); + gnssData_ = null; + } + return gnssDataBuilder_; + } + + private java.util.List wifiFingerprints_ = + java.util.Collections.emptyList(); + private void ensureWifiFingerprintsIsMutable() { + if (!((bitField0_ & 0x00000080) != 0)) { + wifiFingerprints_ = new java.util.ArrayList(wifiFingerprints_); + bitField0_ |= 0x00000080; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.Fingerprint, Traj.Fingerprint.Builder, Traj.FingerprintOrBuilder> wifiFingerprintsBuilder_; + + /** + * repeated .Fingerprint wifi_fingerprints = 11; + */ + public java.util.List getWifiFingerprintsList() { + if (wifiFingerprintsBuilder_ == null) { + return java.util.Collections.unmodifiableList(wifiFingerprints_); + } else { + return wifiFingerprintsBuilder_.getMessageList(); + } + } + /** + * repeated .Fingerprint wifi_fingerprints = 11; + */ + public int getWifiFingerprintsCount() { + if (wifiFingerprintsBuilder_ == null) { + return wifiFingerprints_.size(); } else { - return wifiDataBuilder_.getCount(); + return wifiFingerprintsBuilder_.getCount(); } } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public WiFi_Sample getWifiData(int index) { - if (wifiDataBuilder_ == null) { - return wifiData_.get(index); + public Traj.Fingerprint getWifiFingerprints(int index) { + if (wifiFingerprintsBuilder_ == null) { + return wifiFingerprints_.get(index); } else { - return wifiDataBuilder_.getMessage(index); + return wifiFingerprintsBuilder_.getMessage(index); } } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public Builder setWifiData( - int index, WiFi_Sample value) { - if (wifiDataBuilder_ == null) { + public Builder setWifiFingerprints( + int index, Traj.Fingerprint value) { + if (wifiFingerprintsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureWifiDataIsMutable(); - wifiData_.set(index, value); + ensureWifiFingerprintsIsMutable(); + wifiFingerprints_.set(index, value); onChanged(); } else { - wifiDataBuilder_.setMessage(index, value); + wifiFingerprintsBuilder_.setMessage(index, value); } return this; } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public Builder setWifiData( - int index, WiFi_Sample.Builder builderForValue) { - if (wifiDataBuilder_ == null) { - ensureWifiDataIsMutable(); - wifiData_.set(index, builderForValue.build()); + public Builder setWifiFingerprints( + int index, Traj.Fingerprint.Builder builderForValue) { + if (wifiFingerprintsBuilder_ == null) { + ensureWifiFingerprintsIsMutable(); + wifiFingerprints_.set(index, builderForValue.build()); onChanged(); } else { - wifiDataBuilder_.setMessage(index, builderForValue.build()); + wifiFingerprintsBuilder_.setMessage(index, builderForValue.build()); } return this; } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public Builder addWifiData(WiFi_Sample value) { - if (wifiDataBuilder_ == null) { + public Builder addWifiFingerprints(Traj.Fingerprint value) { + if (wifiFingerprintsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureWifiDataIsMutable(); - wifiData_.add(value); + ensureWifiFingerprintsIsMutable(); + wifiFingerprints_.add(value); onChanged(); } else { - wifiDataBuilder_.addMessage(value); + wifiFingerprintsBuilder_.addMessage(value); } return this; } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public Builder addWifiData( - int index, WiFi_Sample value) { - if (wifiDataBuilder_ == null) { + public Builder addWifiFingerprints( + int index, Traj.Fingerprint value) { + if (wifiFingerprintsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - ensureWifiDataIsMutable(); - wifiData_.add(index, value); + ensureWifiFingerprintsIsMutable(); + wifiFingerprints_.add(index, value); onChanged(); } else { - wifiDataBuilder_.addMessage(index, value); + wifiFingerprintsBuilder_.addMessage(index, value); } return this; } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public Builder addWifiData( - WiFi_Sample.Builder builderForValue) { - if (wifiDataBuilder_ == null) { - ensureWifiDataIsMutable(); - wifiData_.add(builderForValue.build()); + public Builder addWifiFingerprints( + Traj.Fingerprint.Builder builderForValue) { + if (wifiFingerprintsBuilder_ == null) { + ensureWifiFingerprintsIsMutable(); + wifiFingerprints_.add(builderForValue.build()); onChanged(); } else { - wifiDataBuilder_.addMessage(builderForValue.build()); + wifiFingerprintsBuilder_.addMessage(builderForValue.build()); } return this; } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public Builder addWifiData( - int index, WiFi_Sample.Builder builderForValue) { - if (wifiDataBuilder_ == null) { - ensureWifiDataIsMutable(); - wifiData_.add(index, builderForValue.build()); + public Builder addWifiFingerprints( + int index, Traj.Fingerprint.Builder builderForValue) { + if (wifiFingerprintsBuilder_ == null) { + ensureWifiFingerprintsIsMutable(); + wifiFingerprints_.add(index, builderForValue.build()); onChanged(); } else { - wifiDataBuilder_.addMessage(index, builderForValue.build()); + wifiFingerprintsBuilder_.addMessage(index, builderForValue.build()); } return this; } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public Builder addAllWifiData( - Iterable values) { - if (wifiDataBuilder_ == null) { - ensureWifiDataIsMutable(); + public Builder addAllWifiFingerprints( + java.lang.Iterable values) { + if (wifiFingerprintsBuilder_ == null) { + ensureWifiFingerprintsIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, wifiData_); + values, wifiFingerprints_); onChanged(); } else { - wifiDataBuilder_.addAllMessages(values); + wifiFingerprintsBuilder_.addAllMessages(values); } return this; } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public Builder clearWifiData() { - if (wifiDataBuilder_ == null) { - wifiData_ = java.util.Collections.emptyList(); + public Builder clearWifiFingerprints() { + if (wifiFingerprintsBuilder_ == null) { + wifiFingerprints_ = java.util.Collections.emptyList(); bitField0_ = (bitField0_ & ~0x00000080); onChanged(); } else { - wifiDataBuilder_.clear(); + wifiFingerprintsBuilder_.clear(); } return this; } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public Builder removeWifiData(int index) { - if (wifiDataBuilder_ == null) { - ensureWifiDataIsMutable(); - wifiData_.remove(index); + public Builder removeWifiFingerprints(int index) { + if (wifiFingerprintsBuilder_ == null) { + ensureWifiFingerprintsIsMutable(); + wifiFingerprints_.remove(index); onChanged(); } else { - wifiDataBuilder_.remove(index); + wifiFingerprintsBuilder_.remove(index); } return this; } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public WiFi_Sample.Builder getWifiDataBuilder( + public Traj.Fingerprint.Builder getWifiFingerprintsBuilder( int index) { - return getWifiDataFieldBuilder().getBuilder(index); + return getWifiFingerprintsFieldBuilder().getBuilder(index); } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public WiFi_SampleOrBuilder getWifiDataOrBuilder( + public Traj.FingerprintOrBuilder getWifiFingerprintsOrBuilder( int index) { - if (wifiDataBuilder_ == null) { - return wifiData_.get(index); } else { - return wifiDataBuilder_.getMessageOrBuilder(index); + if (wifiFingerprintsBuilder_ == null) { + return wifiFingerprints_.get(index); } else { + return wifiFingerprintsBuilder_.getMessageOrBuilder(index); } } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public java.util.List - getWifiDataOrBuilderList() { - if (wifiDataBuilder_ != null) { - return wifiDataBuilder_.getMessageOrBuilderList(); + public java.util.List + getWifiFingerprintsOrBuilderList() { + if (wifiFingerprintsBuilder_ != null) { + return wifiFingerprintsBuilder_.getMessageOrBuilderList(); } else { - return java.util.Collections.unmodifiableList(wifiData_); + return java.util.Collections.unmodifiableList(wifiFingerprints_); } } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public WiFi_Sample.Builder addWifiDataBuilder() { - return getWifiDataFieldBuilder().addBuilder( - WiFi_Sample.getDefaultInstance()); + public Traj.Fingerprint.Builder addWifiFingerprintsBuilder() { + return getWifiFingerprintsFieldBuilder().addBuilder( + Traj.Fingerprint.getDefaultInstance()); } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public WiFi_Sample.Builder addWifiDataBuilder( + public Traj.Fingerprint.Builder addWifiFingerprintsBuilder( int index) { - return getWifiDataFieldBuilder().addBuilder( - index, WiFi_Sample.getDefaultInstance()); + return getWifiFingerprintsFieldBuilder().addBuilder( + index, Traj.Fingerprint.getDefaultInstance()); } /** - * repeated .WiFi_Sample wifi_data = 8; + * repeated .Fingerprint wifi_fingerprints = 11; */ - public java.util.List - getWifiDataBuilderList() { - return getWifiDataFieldBuilder().getBuilderList(); + public java.util.List + getWifiFingerprintsBuilderList() { + return getWifiFingerprintsFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilderV3< - WiFi_Sample, WiFi_Sample.Builder, WiFi_SampleOrBuilder> - getWifiDataFieldBuilder() { - if (wifiDataBuilder_ == null) { - wifiDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - WiFi_Sample, WiFi_Sample.Builder, WiFi_SampleOrBuilder>( - wifiData_, - ((bitField0_ & 0x00000080) == 0x00000080), + Traj.Fingerprint, Traj.Fingerprint.Builder, Traj.FingerprintOrBuilder> + getWifiFingerprintsFieldBuilder() { + if (wifiFingerprintsBuilder_ == null) { + wifiFingerprintsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + Traj.Fingerprint, Traj.Fingerprint.Builder, Traj.FingerprintOrBuilder>( + wifiFingerprints_, + ((bitField0_ & 0x00000080) != 0), getParentForChildren(), isClean()); - wifiData_ = null; + wifiFingerprints_ = null; } - return wifiDataBuilder_; + return wifiFingerprintsBuilder_; } - private java.util.List apsData_ = + private java.util.List apsData_ = java.util.Collections.emptyList(); private void ensureApsDataIsMutable() { - if (!((bitField0_ & 0x00000100) == 0x00000100)) { - apsData_ = new java.util.ArrayList(apsData_); + if (!((bitField0_ & 0x00000100) != 0)) { + apsData_ = new java.util.ArrayList(apsData_); bitField0_ |= 0x00000100; } } private com.google.protobuf.RepeatedFieldBuilderV3< - AP_Data, AP_Data.Builder, AP_DataOrBuilder> apsDataBuilder_; + Traj.WiFiAPData, Traj.WiFiAPData.Builder, Traj.WiFiAPDataOrBuilder> apsDataBuilder_; /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public java.util.List getApsDataList() { + public java.util.List getApsDataList() { if (apsDataBuilder_ == null) { return java.util.Collections.unmodifiableList(apsData_); } else { @@ -3779,7 +5334,7 @@ public java.util.List getApsDataList() { } } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ public int getApsDataCount() { if (apsDataBuilder_ == null) { @@ -3789,9 +5344,9 @@ public int getApsDataCount() { } } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public AP_Data getApsData(int index) { + public Traj.WiFiAPData getApsData(int index) { if (apsDataBuilder_ == null) { return apsData_.get(index); } else { @@ -3799,10 +5354,10 @@ public AP_Data getApsData(int index) { } } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ public Builder setApsData( - int index, AP_Data value) { + int index, Traj.WiFiAPData value) { if (apsDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -3816,10 +5371,10 @@ public Builder setApsData( return this; } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ public Builder setApsData( - int index, AP_Data.Builder builderForValue) { + int index, Traj.WiFiAPData.Builder builderForValue) { if (apsDataBuilder_ == null) { ensureApsDataIsMutable(); apsData_.set(index, builderForValue.build()); @@ -3830,9 +5385,9 @@ public Builder setApsData( return this; } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public Builder addApsData(AP_Data value) { + public Builder addApsData(Traj.WiFiAPData value) { if (apsDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -3846,10 +5401,10 @@ public Builder addApsData(AP_Data value) { return this; } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ public Builder addApsData( - int index, AP_Data value) { + int index, Traj.WiFiAPData value) { if (apsDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); @@ -3863,10 +5418,10 @@ public Builder addApsData( return this; } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ public Builder addApsData( - AP_Data.Builder builderForValue) { + Traj.WiFiAPData.Builder builderForValue) { if (apsDataBuilder_ == null) { ensureApsDataIsMutable(); apsData_.add(builderForValue.build()); @@ -3877,10 +5432,10 @@ public Builder addApsData( return this; } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ public Builder addApsData( - int index, AP_Data.Builder builderForValue) { + int index, Traj.WiFiAPData.Builder builderForValue) { if (apsDataBuilder_ == null) { ensureApsDataIsMutable(); apsData_.add(index, builderForValue.build()); @@ -3891,10 +5446,10 @@ public Builder addApsData( return this; } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ public Builder addAllApsData( - Iterable values) { + java.lang.Iterable values) { if (apsDataBuilder_ == null) { ensureApsDataIsMutable(); com.google.protobuf.AbstractMessageLite.Builder.addAll( @@ -3906,7 +5461,7 @@ public Builder addAllApsData( return this; } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ public Builder clearApsData() { if (apsDataBuilder_ == null) { @@ -3919,7 +5474,7 @@ public Builder clearApsData() { return this; } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ public Builder removeApsData(int index) { if (apsDataBuilder_ == null) { @@ -3932,16 +5487,16 @@ public Builder removeApsData(int index) { return this; } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public AP_Data.Builder getApsDataBuilder( + public Traj.WiFiAPData.Builder getApsDataBuilder( int index) { return getApsDataFieldBuilder().getBuilder(index); } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public AP_DataOrBuilder getApsDataOrBuilder( + public Traj.WiFiAPDataOrBuilder getApsDataOrBuilder( int index) { if (apsDataBuilder_ == null) { return apsData_.get(index); } else { @@ -3949,9 +5504,9 @@ public AP_DataOrBuilder getApsDataOrBuilder( } } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public java.util.List + public java.util.List getApsDataOrBuilderList() { if (apsDataBuilder_ != null) { return apsDataBuilder_.getMessageOrBuilderList(); @@ -3960,35 +5515,35 @@ public AP_DataOrBuilder getApsDataOrBuilder( } } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public AP_Data.Builder addApsDataBuilder() { + public Traj.WiFiAPData.Builder addApsDataBuilder() { return getApsDataFieldBuilder().addBuilder( - AP_Data.getDefaultInstance()); + Traj.WiFiAPData.getDefaultInstance()); } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public AP_Data.Builder addApsDataBuilder( + public Traj.WiFiAPData.Builder addApsDataBuilder( int index) { return getApsDataFieldBuilder().addBuilder( - index, AP_Data.getDefaultInstance()); + index, Traj.WiFiAPData.getDefaultInstance()); } /** - * repeated .AP_Data aps_data = 9; + * repeated .WiFiAPData aps_data = 12; */ - public java.util.List + public java.util.List getApsDataBuilderList() { return getApsDataFieldBuilder().getBuilderList(); } private com.google.protobuf.RepeatedFieldBuilderV3< - AP_Data, AP_Data.Builder, AP_DataOrBuilder> + Traj.WiFiAPData, Traj.WiFiAPData.Builder, Traj.WiFiAPDataOrBuilder> getApsDataFieldBuilder() { if (apsDataBuilder_ == null) { apsDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - AP_Data, AP_Data.Builder, AP_DataOrBuilder>( + Traj.WiFiAPData, Traj.WiFiAPData.Builder, Traj.WiFiAPDataOrBuilder>( apsData_, - ((bitField0_ & 0x00000100) == 0x00000100), + ((bitField0_ & 0x00000100) != 0), getParentForChildren(), isClean()); apsData_ = null; @@ -3996,938 +5551,6958 @@ public AP_Data.Builder addApsDataBuilder( return apsDataBuilder_; } - private long startTimestamp_ ; - /** - *
-       * UNIX timestamp (in milliseconds) recorded from the start of this
-       * trajectory data collection event. All future
-       * timestamps in sub classes are to be RELATIVE timestamps
-       * (in milliseconds) to this start time.
-       * E.g.
-       * start_timestamp = 1674819807315 (UTC 27 Jan 2023 in the morning)
-       * relative_timestamp = 3000 (3s)
-       * 
- * - * optional int64 start_timestamp = 10; - */ - public long getStartTimestamp() { - return startTimestamp_; + private java.util.List wifiRttData_ = + java.util.Collections.emptyList(); + private void ensureWifiRttDataIsMutable() { + if (!((bitField0_ & 0x00000200) != 0)) { + wifiRttData_ = new java.util.ArrayList(wifiRttData_); + bitField0_ |= 0x00000200; + } } + + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.WiFiRTTReading, Traj.WiFiRTTReading.Builder, Traj.WiFiRTTReadingOrBuilder> wifiRttDataBuilder_; + /** - *
-       * UNIX timestamp (in milliseconds) recorded from the start of this
-       * trajectory data collection event. All future
-       * timestamps in sub classes are to be RELATIVE timestamps
-       * (in milliseconds) to this start time.
-       * E.g.
-       * start_timestamp = 1674819807315 (UTC 27 Jan 2023 in the morning)
-       * relative_timestamp = 3000 (3s)
-       * 
- * - * optional int64 start_timestamp = 10; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public Builder setStartTimestamp(long value) { - - startTimestamp_ = value; - onChanged(); - return this; + public java.util.List getWifiRttDataList() { + if (wifiRttDataBuilder_ == null) { + return java.util.Collections.unmodifiableList(wifiRttData_); + } else { + return wifiRttDataBuilder_.getMessageList(); + } } /** - *
-       * UNIX timestamp (in milliseconds) recorded from the start of this
-       * trajectory data collection event. All future
-       * timestamps in sub classes are to be RELATIVE timestamps
-       * (in milliseconds) to this start time.
-       * E.g.
-       * start_timestamp = 1674819807315 (UTC 27 Jan 2023 in the morning)
-       * relative_timestamp = 3000 (3s)
-       * 
- * - * optional int64 start_timestamp = 10; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public Builder clearStartTimestamp() { - - startTimestamp_ = 0L; - onChanged(); - return this; + public int getWifiRttDataCount() { + if (wifiRttDataBuilder_ == null) { + return wifiRttData_.size(); + } else { + return wifiRttDataBuilder_.getCount(); + } } - - private Object dataIdentifier_ = ""; /** - * optional string data_identifier = 11; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public String getDataIdentifier() { - Object ref = dataIdentifier_; - if (!(ref instanceof String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - dataIdentifier_ = s; - return s; + public Traj.WiFiRTTReading getWifiRttData(int index) { + if (wifiRttDataBuilder_ == null) { + return wifiRttData_.get(index); } else { - return (String) ref; + return wifiRttDataBuilder_.getMessage(index); } } /** - * optional string data_identifier = 11; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public com.google.protobuf.ByteString - getDataIdentifierBytes() { - Object ref = dataIdentifier_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - dataIdentifier_ = b; - return b; + public Builder setWifiRttData( + int index, Traj.WiFiRTTReading value) { + if (wifiRttDataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureWifiRttDataIsMutable(); + wifiRttData_.set(index, value); + onChanged(); } else { - return (com.google.protobuf.ByteString) ref; + wifiRttDataBuilder_.setMessage(index, value); } - } - /** - * optional string data_identifier = 11; - */ - public Builder setDataIdentifier( - String value) { - if (value == null) { - throw new NullPointerException(); - } - - dataIdentifier_ = value; - onChanged(); return this; } /** - * optional string data_identifier = 11; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public Builder clearDataIdentifier() { - - dataIdentifier_ = getDefaultInstance().getDataIdentifier(); - onChanged(); + public Builder setWifiRttData( + int index, Traj.WiFiRTTReading.Builder builderForValue) { + if (wifiRttDataBuilder_ == null) { + ensureWifiRttDataIsMutable(); + wifiRttData_.set(index, builderForValue.build()); + onChanged(); + } else { + wifiRttDataBuilder_.setMessage(index, builderForValue.build()); + } return this; } /** - * optional string data_identifier = 11; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public Builder setDataIdentifierBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - dataIdentifier_ = value; - onChanged(); + public Builder addWifiRttData(Traj.WiFiRTTReading value) { + if (wifiRttDataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureWifiRttDataIsMutable(); + wifiRttData_.add(value); + onChanged(); + } else { + wifiRttDataBuilder_.addMessage(value); + } return this; } - - private Sensor_Info accelerometerInfo_ = null; - private com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder> accelerometerInfoBuilder_; /** - * optional .Sensor_Info accelerometer_info = 12; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public boolean hasAccelerometerInfo() { - return accelerometerInfoBuilder_ != null || accelerometerInfo_ != null; + public Builder addWifiRttData( + int index, Traj.WiFiRTTReading value) { + if (wifiRttDataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureWifiRttDataIsMutable(); + wifiRttData_.add(index, value); + onChanged(); + } else { + wifiRttDataBuilder_.addMessage(index, value); + } + return this; } /** - * optional .Sensor_Info accelerometer_info = 12; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public Sensor_Info getAccelerometerInfo() { - if (accelerometerInfoBuilder_ == null) { - return accelerometerInfo_ == null ? Sensor_Info.getDefaultInstance() : accelerometerInfo_; + public Builder addWifiRttData( + Traj.WiFiRTTReading.Builder builderForValue) { + if (wifiRttDataBuilder_ == null) { + ensureWifiRttDataIsMutable(); + wifiRttData_.add(builderForValue.build()); + onChanged(); } else { - return accelerometerInfoBuilder_.getMessage(); + wifiRttDataBuilder_.addMessage(builderForValue.build()); } + return this; } /** - * optional .Sensor_Info accelerometer_info = 12; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public Builder setAccelerometerInfo(Sensor_Info value) { - if (accelerometerInfoBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - accelerometerInfo_ = value; + public Builder addWifiRttData( + int index, Traj.WiFiRTTReading.Builder builderForValue) { + if (wifiRttDataBuilder_ == null) { + ensureWifiRttDataIsMutable(); + wifiRttData_.add(index, builderForValue.build()); onChanged(); } else { - accelerometerInfoBuilder_.setMessage(value); + wifiRttDataBuilder_.addMessage(index, builderForValue.build()); } - return this; } /** - * optional .Sensor_Info accelerometer_info = 12; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public Builder setAccelerometerInfo( - Sensor_Info.Builder builderForValue) { - if (accelerometerInfoBuilder_ == null) { - accelerometerInfo_ = builderForValue.build(); + public Builder addAllWifiRttData( + java.lang.Iterable values) { + if (wifiRttDataBuilder_ == null) { + ensureWifiRttDataIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, wifiRttData_); onChanged(); } else { - accelerometerInfoBuilder_.setMessage(builderForValue.build()); + wifiRttDataBuilder_.addAllMessages(values); } - return this; } /** - * optional .Sensor_Info accelerometer_info = 12; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public Builder mergeAccelerometerInfo(Sensor_Info value) { - if (accelerometerInfoBuilder_ == null) { - if (accelerometerInfo_ != null) { - accelerometerInfo_ = - Sensor_Info.newBuilder(accelerometerInfo_).mergeFrom(value).buildPartial(); - } else { - accelerometerInfo_ = value; - } + public Builder clearWifiRttData() { + if (wifiRttDataBuilder_ == null) { + wifiRttData_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000200); onChanged(); } else { - accelerometerInfoBuilder_.mergeFrom(value); + wifiRttDataBuilder_.clear(); } - return this; } /** - * optional .Sensor_Info accelerometer_info = 12; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public Builder clearAccelerometerInfo() { - if (accelerometerInfoBuilder_ == null) { - accelerometerInfo_ = null; + public Builder removeWifiRttData(int index) { + if (wifiRttDataBuilder_ == null) { + ensureWifiRttDataIsMutable(); + wifiRttData_.remove(index); onChanged(); } else { - accelerometerInfo_ = null; - accelerometerInfoBuilder_ = null; + wifiRttDataBuilder_.remove(index); } - return this; } /** - * optional .Sensor_Info accelerometer_info = 12; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public Sensor_Info.Builder getAccelerometerInfoBuilder() { - - onChanged(); - return getAccelerometerInfoFieldBuilder().getBuilder(); + public Traj.WiFiRTTReading.Builder getWifiRttDataBuilder( + int index) { + return getWifiRttDataFieldBuilder().getBuilder(index); } /** - * optional .Sensor_Info accelerometer_info = 12; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - public Sensor_InfoOrBuilder getAccelerometerInfoOrBuilder() { - if (accelerometerInfoBuilder_ != null) { - return accelerometerInfoBuilder_.getMessageOrBuilder(); + public Traj.WiFiRTTReadingOrBuilder getWifiRttDataOrBuilder( + int index) { + if (wifiRttDataBuilder_ == null) { + return wifiRttData_.get(index); } else { + return wifiRttDataBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .WiFiRTTReading wifi_rtt_data = 13; + */ + public java.util.List + getWifiRttDataOrBuilderList() { + if (wifiRttDataBuilder_ != null) { + return wifiRttDataBuilder_.getMessageOrBuilderList(); } else { - return accelerometerInfo_ == null ? - Sensor_Info.getDefaultInstance() : accelerometerInfo_; + return java.util.Collections.unmodifiableList(wifiRttData_); } } /** - * optional .Sensor_Info accelerometer_info = 12; + * repeated .WiFiRTTReading wifi_rtt_data = 13; */ - private com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder> - getAccelerometerInfoFieldBuilder() { - if (accelerometerInfoBuilder_ == null) { - accelerometerInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder>( - getAccelerometerInfo(), + public Traj.WiFiRTTReading.Builder addWifiRttDataBuilder() { + return getWifiRttDataFieldBuilder().addBuilder( + Traj.WiFiRTTReading.getDefaultInstance()); + } + /** + * repeated .WiFiRTTReading wifi_rtt_data = 13; + */ + public Traj.WiFiRTTReading.Builder addWifiRttDataBuilder( + int index) { + return getWifiRttDataFieldBuilder().addBuilder( + index, Traj.WiFiRTTReading.getDefaultInstance()); + } + /** + * repeated .WiFiRTTReading wifi_rtt_data = 13; + */ + public java.util.List + getWifiRttDataBuilderList() { + return getWifiRttDataFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.WiFiRTTReading, Traj.WiFiRTTReading.Builder, Traj.WiFiRTTReadingOrBuilder> + getWifiRttDataFieldBuilder() { + if (wifiRttDataBuilder_ == null) { + wifiRttDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + Traj.WiFiRTTReading, Traj.WiFiRTTReading.Builder, Traj.WiFiRTTReadingOrBuilder>( + wifiRttData_, + ((bitField0_ & 0x00000200) != 0), getParentForChildren(), isClean()); - accelerometerInfo_ = null; + wifiRttData_ = null; } - return accelerometerInfoBuilder_; + return wifiRttDataBuilder_; } - private Sensor_Info gyroscopeInfo_ = null; - private com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder> gyroscopeInfoBuilder_; + private java.util.List bleFingerprints_ = + java.util.Collections.emptyList(); + private void ensureBleFingerprintsIsMutable() { + if (!((bitField0_ & 0x00000400) != 0)) { + bleFingerprints_ = new java.util.ArrayList(bleFingerprints_); + bitField0_ |= 0x00000400; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.Fingerprint, Traj.Fingerprint.Builder, Traj.FingerprintOrBuilder> bleFingerprintsBuilder_; + /** - * optional .Sensor_Info gyroscope_info = 13; + * repeated .Fingerprint ble_fingerprints = 14; */ - public boolean hasGyroscopeInfo() { - return gyroscopeInfoBuilder_ != null || gyroscopeInfo_ != null; + public java.util.List getBleFingerprintsList() { + if (bleFingerprintsBuilder_ == null) { + return java.util.Collections.unmodifiableList(bleFingerprints_); + } else { + return bleFingerprintsBuilder_.getMessageList(); + } } /** - * optional .Sensor_Info gyroscope_info = 13; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Sensor_Info getGyroscopeInfo() { - if (gyroscopeInfoBuilder_ == null) { - return gyroscopeInfo_ == null ? Sensor_Info.getDefaultInstance() : gyroscopeInfo_; + public int getBleFingerprintsCount() { + if (bleFingerprintsBuilder_ == null) { + return bleFingerprints_.size(); } else { - return gyroscopeInfoBuilder_.getMessage(); + return bleFingerprintsBuilder_.getCount(); } } /** - * optional .Sensor_Info gyroscope_info = 13; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Builder setGyroscopeInfo(Sensor_Info value) { - if (gyroscopeInfoBuilder_ == null) { + public Traj.Fingerprint getBleFingerprints(int index) { + if (bleFingerprintsBuilder_ == null) { + return bleFingerprints_.get(index); + } else { + return bleFingerprintsBuilder_.getMessage(index); + } + } + /** + * repeated .Fingerprint ble_fingerprints = 14; + */ + public Builder setBleFingerprints( + int index, Traj.Fingerprint value) { + if (bleFingerprintsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - gyroscopeInfo_ = value; + ensureBleFingerprintsIsMutable(); + bleFingerprints_.set(index, value); onChanged(); } else { - gyroscopeInfoBuilder_.setMessage(value); + bleFingerprintsBuilder_.setMessage(index, value); } - return this; } /** - * optional .Sensor_Info gyroscope_info = 13; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Builder setGyroscopeInfo( - Sensor_Info.Builder builderForValue) { - if (gyroscopeInfoBuilder_ == null) { - gyroscopeInfo_ = builderForValue.build(); + public Builder setBleFingerprints( + int index, Traj.Fingerprint.Builder builderForValue) { + if (bleFingerprintsBuilder_ == null) { + ensureBleFingerprintsIsMutable(); + bleFingerprints_.set(index, builderForValue.build()); onChanged(); } else { - gyroscopeInfoBuilder_.setMessage(builderForValue.build()); + bleFingerprintsBuilder_.setMessage(index, builderForValue.build()); } - return this; } /** - * optional .Sensor_Info gyroscope_info = 13; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Builder mergeGyroscopeInfo(Sensor_Info value) { - if (gyroscopeInfoBuilder_ == null) { - if (gyroscopeInfo_ != null) { - gyroscopeInfo_ = - Sensor_Info.newBuilder(gyroscopeInfo_).mergeFrom(value).buildPartial(); - } else { - gyroscopeInfo_ = value; + public Builder addBleFingerprints(Traj.Fingerprint value) { + if (bleFingerprintsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); } + ensureBleFingerprintsIsMutable(); + bleFingerprints_.add(value); onChanged(); } else { - gyroscopeInfoBuilder_.mergeFrom(value); + bleFingerprintsBuilder_.addMessage(value); } - return this; } /** - * optional .Sensor_Info gyroscope_info = 13; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Builder clearGyroscopeInfo() { - if (gyroscopeInfoBuilder_ == null) { - gyroscopeInfo_ = null; + public Builder addBleFingerprints( + int index, Traj.Fingerprint value) { + if (bleFingerprintsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureBleFingerprintsIsMutable(); + bleFingerprints_.add(index, value); onChanged(); } else { - gyroscopeInfo_ = null; - gyroscopeInfoBuilder_ = null; + bleFingerprintsBuilder_.addMessage(index, value); } - return this; } /** - * optional .Sensor_Info gyroscope_info = 13; - */ - public Sensor_Info.Builder getGyroscopeInfoBuilder() { - - onChanged(); - return getGyroscopeInfoFieldBuilder().getBuilder(); - } - /** - * optional .Sensor_Info gyroscope_info = 13; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Sensor_InfoOrBuilder getGyroscopeInfoOrBuilder() { - if (gyroscopeInfoBuilder_ != null) { - return gyroscopeInfoBuilder_.getMessageOrBuilder(); + public Builder addBleFingerprints( + Traj.Fingerprint.Builder builderForValue) { + if (bleFingerprintsBuilder_ == null) { + ensureBleFingerprintsIsMutable(); + bleFingerprints_.add(builderForValue.build()); + onChanged(); } else { - return gyroscopeInfo_ == null ? - Sensor_Info.getDefaultInstance() : gyroscopeInfo_; + bleFingerprintsBuilder_.addMessage(builderForValue.build()); } + return this; } /** - * optional .Sensor_Info gyroscope_info = 13; + * repeated .Fingerprint ble_fingerprints = 14; */ - private com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder> - getGyroscopeInfoFieldBuilder() { - if (gyroscopeInfoBuilder_ == null) { - gyroscopeInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder>( - getGyroscopeInfo(), - getParentForChildren(), - isClean()); - gyroscopeInfo_ = null; + public Builder addBleFingerprints( + int index, Traj.Fingerprint.Builder builderForValue) { + if (bleFingerprintsBuilder_ == null) { + ensureBleFingerprintsIsMutable(); + bleFingerprints_.add(index, builderForValue.build()); + onChanged(); + } else { + bleFingerprintsBuilder_.addMessage(index, builderForValue.build()); } - return gyroscopeInfoBuilder_; - } - - private Sensor_Info rotationVectorInfo_ = null; - private com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder> rotationVectorInfoBuilder_; - /** - * optional .Sensor_Info rotation_vector_info = 14; - */ - public boolean hasRotationVectorInfo() { - return rotationVectorInfoBuilder_ != null || rotationVectorInfo_ != null; + return this; } /** - * optional .Sensor_Info rotation_vector_info = 14; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Sensor_Info getRotationVectorInfo() { - if (rotationVectorInfoBuilder_ == null) { - return rotationVectorInfo_ == null ? Sensor_Info.getDefaultInstance() : rotationVectorInfo_; + public Builder addAllBleFingerprints( + java.lang.Iterable values) { + if (bleFingerprintsBuilder_ == null) { + ensureBleFingerprintsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, bleFingerprints_); + onChanged(); } else { - return rotationVectorInfoBuilder_.getMessage(); + bleFingerprintsBuilder_.addAllMessages(values); } + return this; } /** - * optional .Sensor_Info rotation_vector_info = 14; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Builder setRotationVectorInfo(Sensor_Info value) { - if (rotationVectorInfoBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - rotationVectorInfo_ = value; + public Builder clearBleFingerprints() { + if (bleFingerprintsBuilder_ == null) { + bleFingerprints_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000400); onChanged(); } else { - rotationVectorInfoBuilder_.setMessage(value); + bleFingerprintsBuilder_.clear(); } - return this; } /** - * optional .Sensor_Info rotation_vector_info = 14; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Builder setRotationVectorInfo( - Sensor_Info.Builder builderForValue) { - if (rotationVectorInfoBuilder_ == null) { - rotationVectorInfo_ = builderForValue.build(); + public Builder removeBleFingerprints(int index) { + if (bleFingerprintsBuilder_ == null) { + ensureBleFingerprintsIsMutable(); + bleFingerprints_.remove(index); onChanged(); } else { - rotationVectorInfoBuilder_.setMessage(builderForValue.build()); + bleFingerprintsBuilder_.remove(index); } - return this; } /** - * optional .Sensor_Info rotation_vector_info = 14; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Builder mergeRotationVectorInfo(Sensor_Info value) { - if (rotationVectorInfoBuilder_ == null) { - if (rotationVectorInfo_ != null) { - rotationVectorInfo_ = - Sensor_Info.newBuilder(rotationVectorInfo_).mergeFrom(value).buildPartial(); - } else { - rotationVectorInfo_ = value; - } - onChanged(); - } else { - rotationVectorInfoBuilder_.mergeFrom(value); + public Traj.Fingerprint.Builder getBleFingerprintsBuilder( + int index) { + return getBleFingerprintsFieldBuilder().getBuilder(index); + } + /** + * repeated .Fingerprint ble_fingerprints = 14; + */ + public Traj.FingerprintOrBuilder getBleFingerprintsOrBuilder( + int index) { + if (bleFingerprintsBuilder_ == null) { + return bleFingerprints_.get(index); } else { + return bleFingerprintsBuilder_.getMessageOrBuilder(index); } - - return this; } /** - * optional .Sensor_Info rotation_vector_info = 14; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Builder clearRotationVectorInfo() { - if (rotationVectorInfoBuilder_ == null) { - rotationVectorInfo_ = null; - onChanged(); + public java.util.List + getBleFingerprintsOrBuilderList() { + if (bleFingerprintsBuilder_ != null) { + return bleFingerprintsBuilder_.getMessageOrBuilderList(); } else { - rotationVectorInfo_ = null; - rotationVectorInfoBuilder_ = null; + return java.util.Collections.unmodifiableList(bleFingerprints_); } - - return this; } /** - * optional .Sensor_Info rotation_vector_info = 14; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Sensor_Info.Builder getRotationVectorInfoBuilder() { - - onChanged(); - return getRotationVectorInfoFieldBuilder().getBuilder(); + public Traj.Fingerprint.Builder addBleFingerprintsBuilder() { + return getBleFingerprintsFieldBuilder().addBuilder( + Traj.Fingerprint.getDefaultInstance()); } /** - * optional .Sensor_Info rotation_vector_info = 14; + * repeated .Fingerprint ble_fingerprints = 14; */ - public Sensor_InfoOrBuilder getRotationVectorInfoOrBuilder() { - if (rotationVectorInfoBuilder_ != null) { - return rotationVectorInfoBuilder_.getMessageOrBuilder(); - } else { - return rotationVectorInfo_ == null ? - Sensor_Info.getDefaultInstance() : rotationVectorInfo_; - } + public Traj.Fingerprint.Builder addBleFingerprintsBuilder( + int index) { + return getBleFingerprintsFieldBuilder().addBuilder( + index, Traj.Fingerprint.getDefaultInstance()); } /** - * optional .Sensor_Info rotation_vector_info = 14; + * repeated .Fingerprint ble_fingerprints = 14; */ - private com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder> - getRotationVectorInfoFieldBuilder() { - if (rotationVectorInfoBuilder_ == null) { - rotationVectorInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder>( - getRotationVectorInfo(), + public java.util.List + getBleFingerprintsBuilderList() { + return getBleFingerprintsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.Fingerprint, Traj.Fingerprint.Builder, Traj.FingerprintOrBuilder> + getBleFingerprintsFieldBuilder() { + if (bleFingerprintsBuilder_ == null) { + bleFingerprintsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + Traj.Fingerprint, Traj.Fingerprint.Builder, Traj.FingerprintOrBuilder>( + bleFingerprints_, + ((bitField0_ & 0x00000400) != 0), getParentForChildren(), isClean()); - rotationVectorInfo_ = null; + bleFingerprints_ = null; } - return rotationVectorInfoBuilder_; + return bleFingerprintsBuilder_; } - private Sensor_Info magnetometerInfo_ = null; - private com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder> magnetometerInfoBuilder_; + private java.util.List bleData_ = + java.util.Collections.emptyList(); + private void ensureBleDataIsMutable() { + if (!((bitField0_ & 0x00000800) != 0)) { + bleData_ = new java.util.ArrayList(bleData_); + bitField0_ |= 0x00000800; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.BleData, Traj.BleData.Builder, Traj.BleDataOrBuilder> bleDataBuilder_; + /** - * optional .Sensor_Info magnetometer_info = 15; + * repeated .BleData ble_data = 15; */ - public boolean hasMagnetometerInfo() { - return magnetometerInfoBuilder_ != null || magnetometerInfo_ != null; + public java.util.List getBleDataList() { + if (bleDataBuilder_ == null) { + return java.util.Collections.unmodifiableList(bleData_); + } else { + return bleDataBuilder_.getMessageList(); + } } /** - * optional .Sensor_Info magnetometer_info = 15; + * repeated .BleData ble_data = 15; */ - public Sensor_Info getMagnetometerInfo() { - if (magnetometerInfoBuilder_ == null) { - return magnetometerInfo_ == null ? Sensor_Info.getDefaultInstance() : magnetometerInfo_; + public int getBleDataCount() { + if (bleDataBuilder_ == null) { + return bleData_.size(); } else { - return magnetometerInfoBuilder_.getMessage(); + return bleDataBuilder_.getCount(); } } /** - * optional .Sensor_Info magnetometer_info = 15; + * repeated .BleData ble_data = 15; */ - public Builder setMagnetometerInfo(Sensor_Info value) { - if (magnetometerInfoBuilder_ == null) { + public Traj.BleData getBleData(int index) { + if (bleDataBuilder_ == null) { + return bleData_.get(index); + } else { + return bleDataBuilder_.getMessage(index); + } + } + /** + * repeated .BleData ble_data = 15; + */ + public Builder setBleData( + int index, Traj.BleData value) { + if (bleDataBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - magnetometerInfo_ = value; + ensureBleDataIsMutable(); + bleData_.set(index, value); onChanged(); } else { - magnetometerInfoBuilder_.setMessage(value); + bleDataBuilder_.setMessage(index, value); } - return this; } /** - * optional .Sensor_Info magnetometer_info = 15; + * repeated .BleData ble_data = 15; */ - public Builder setMagnetometerInfo( - Sensor_Info.Builder builderForValue) { - if (magnetometerInfoBuilder_ == null) { - magnetometerInfo_ = builderForValue.build(); + public Builder setBleData( + int index, Traj.BleData.Builder builderForValue) { + if (bleDataBuilder_ == null) { + ensureBleDataIsMutable(); + bleData_.set(index, builderForValue.build()); onChanged(); } else { - magnetometerInfoBuilder_.setMessage(builderForValue.build()); + bleDataBuilder_.setMessage(index, builderForValue.build()); } - return this; } /** - * optional .Sensor_Info magnetometer_info = 15; + * repeated .BleData ble_data = 15; */ - public Builder mergeMagnetometerInfo(Sensor_Info value) { - if (magnetometerInfoBuilder_ == null) { - if (magnetometerInfo_ != null) { - magnetometerInfo_ = - Sensor_Info.newBuilder(magnetometerInfo_).mergeFrom(value).buildPartial(); - } else { - magnetometerInfo_ = value; + public Builder addBleData(Traj.BleData value) { + if (bleDataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); } + ensureBleDataIsMutable(); + bleData_.add(value); onChanged(); } else { - magnetometerInfoBuilder_.mergeFrom(value); + bleDataBuilder_.addMessage(value); } - return this; } /** - * optional .Sensor_Info magnetometer_info = 15; + * repeated .BleData ble_data = 15; */ - public Builder clearMagnetometerInfo() { - if (magnetometerInfoBuilder_ == null) { - magnetometerInfo_ = null; + public Builder addBleData( + int index, Traj.BleData value) { + if (bleDataBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureBleDataIsMutable(); + bleData_.add(index, value); onChanged(); } else { - magnetometerInfo_ = null; - magnetometerInfoBuilder_ = null; + bleDataBuilder_.addMessage(index, value); } - return this; } /** - * optional .Sensor_Info magnetometer_info = 15; + * repeated .BleData ble_data = 15; */ - public Sensor_Info.Builder getMagnetometerInfoBuilder() { - - onChanged(); - return getMagnetometerInfoFieldBuilder().getBuilder(); + public Builder addBleData( + Traj.BleData.Builder builderForValue) { + if (bleDataBuilder_ == null) { + ensureBleDataIsMutable(); + bleData_.add(builderForValue.build()); + onChanged(); + } else { + bleDataBuilder_.addMessage(builderForValue.build()); + } + return this; } /** - * optional .Sensor_Info magnetometer_info = 15; + * repeated .BleData ble_data = 15; */ - public Sensor_InfoOrBuilder getMagnetometerInfoOrBuilder() { - if (magnetometerInfoBuilder_ != null) { - return magnetometerInfoBuilder_.getMessageOrBuilder(); + public Builder addBleData( + int index, Traj.BleData.Builder builderForValue) { + if (bleDataBuilder_ == null) { + ensureBleDataIsMutable(); + bleData_.add(index, builderForValue.build()); + onChanged(); } else { - return magnetometerInfo_ == null ? - Sensor_Info.getDefaultInstance() : magnetometerInfo_; + bleDataBuilder_.addMessage(index, builderForValue.build()); } + return this; } /** - * optional .Sensor_Info magnetometer_info = 15; + * repeated .BleData ble_data = 15; */ - private com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder> - getMagnetometerInfoFieldBuilder() { - if (magnetometerInfoBuilder_ == null) { - magnetometerInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder>( - getMagnetometerInfo(), + public Builder addAllBleData( + java.lang.Iterable values) { + if (bleDataBuilder_ == null) { + ensureBleDataIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, bleData_); + onChanged(); + } else { + bleDataBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .BleData ble_data = 15; + */ + public Builder clearBleData() { + if (bleDataBuilder_ == null) { + bleData_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000800); + onChanged(); + } else { + bleDataBuilder_.clear(); + } + return this; + } + /** + * repeated .BleData ble_data = 15; + */ + public Builder removeBleData(int index) { + if (bleDataBuilder_ == null) { + ensureBleDataIsMutable(); + bleData_.remove(index); + onChanged(); + } else { + bleDataBuilder_.remove(index); + } + return this; + } + /** + * repeated .BleData ble_data = 15; + */ + public Traj.BleData.Builder getBleDataBuilder( + int index) { + return getBleDataFieldBuilder().getBuilder(index); + } + /** + * repeated .BleData ble_data = 15; + */ + public Traj.BleDataOrBuilder getBleDataOrBuilder( + int index) { + if (bleDataBuilder_ == null) { + return bleData_.get(index); } else { + return bleDataBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .BleData ble_data = 15; + */ + public java.util.List + getBleDataOrBuilderList() { + if (bleDataBuilder_ != null) { + return bleDataBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(bleData_); + } + } + /** + * repeated .BleData ble_data = 15; + */ + public Traj.BleData.Builder addBleDataBuilder() { + return getBleDataFieldBuilder().addBuilder( + Traj.BleData.getDefaultInstance()); + } + /** + * repeated .BleData ble_data = 15; + */ + public Traj.BleData.Builder addBleDataBuilder( + int index) { + return getBleDataFieldBuilder().addBuilder( + index, Traj.BleData.getDefaultInstance()); + } + /** + * repeated .BleData ble_data = 15; + */ + public java.util.List + getBleDataBuilderList() { + return getBleDataFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.BleData, Traj.BleData.Builder, Traj.BleDataOrBuilder> + getBleDataFieldBuilder() { + if (bleDataBuilder_ == null) { + bleDataBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + Traj.BleData, Traj.BleData.Builder, Traj.BleDataOrBuilder>( + bleData_, + ((bitField0_ & 0x00000800) != 0), getParentForChildren(), isClean()); - magnetometerInfo_ = null; + bleData_ = null; } - return magnetometerInfoBuilder_; + return bleDataBuilder_; + } + + private long startTimestamp_ ; + /** + *
+       * UNIX timestamp (in milliseconds) recorded from the start of this
+       * trajectory data collection event. All future
+       * timestamps in sub classes are to be RELATIVE timestamps
+       * (in milliseconds) to this start time.
+       * E.g.
+       * start_timestamp = 1674819807315 (UTC 27 Jan 2023 in the morning)
+       * relative_timestamp = 3000 (3s)
+       * 
+ * + * int64 start_timestamp = 16; + * @return The startTimestamp. + */ + @java.lang.Override + public long getStartTimestamp() { + return startTimestamp_; + } + /** + *
+       * UNIX timestamp (in milliseconds) recorded from the start of this
+       * trajectory data collection event. All future
+       * timestamps in sub classes are to be RELATIVE timestamps
+       * (in milliseconds) to this start time.
+       * E.g.
+       * start_timestamp = 1674819807315 (UTC 27 Jan 2023 in the morning)
+       * relative_timestamp = 3000 (3s)
+       * 
+ * + * int64 start_timestamp = 16; + * @param value The startTimestamp to set. + * @return This builder for chaining. + */ + public Builder setStartTimestamp(long value) { + + startTimestamp_ = value; + onChanged(); + return this; + } + /** + *
+       * UNIX timestamp (in milliseconds) recorded from the start of this
+       * trajectory data collection event. All future
+       * timestamps in sub classes are to be RELATIVE timestamps
+       * (in milliseconds) to this start time.
+       * E.g.
+       * start_timestamp = 1674819807315 (UTC 27 Jan 2023 in the morning)
+       * relative_timestamp = 3000 (3s)
+       * 
+ * + * int64 start_timestamp = 16; + * @return This builder for chaining. + */ + public Builder clearStartTimestamp() { + + startTimestamp_ = 0L; + onChanged(); + return this; } - private Sensor_Info barometerInfo_ = null; + private Traj.GNSSPosition initialPosition_; private com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder> barometerInfoBuilder_; + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder> initialPositionBuilder_; /** - * optional .Sensor_Info barometer_info = 16; + * .GNSSPosition initial_position = 17; + * @return Whether the initialPosition field is set. */ - public boolean hasBarometerInfo() { - return barometerInfoBuilder_ != null || barometerInfo_ != null; + public boolean hasInitialPosition() { + return initialPositionBuilder_ != null || initialPosition_ != null; } /** - * optional .Sensor_Info barometer_info = 16; + * .GNSSPosition initial_position = 17; + * @return The initialPosition. */ - public Sensor_Info getBarometerInfo() { - if (barometerInfoBuilder_ == null) { - return barometerInfo_ == null ? Sensor_Info.getDefaultInstance() : barometerInfo_; + public Traj.GNSSPosition getInitialPosition() { + if (initialPositionBuilder_ == null) { + return initialPosition_ == null ? Traj.GNSSPosition.getDefaultInstance() : initialPosition_; } else { - return barometerInfoBuilder_.getMessage(); + return initialPositionBuilder_.getMessage(); } } /** - * optional .Sensor_Info barometer_info = 16; + * .GNSSPosition initial_position = 17; */ - public Builder setBarometerInfo(Sensor_Info value) { - if (barometerInfoBuilder_ == null) { + public Builder setInitialPosition(Traj.GNSSPosition value) { + if (initialPositionBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - barometerInfo_ = value; + initialPosition_ = value; onChanged(); } else { - barometerInfoBuilder_.setMessage(value); + initialPositionBuilder_.setMessage(value); } return this; } /** - * optional .Sensor_Info barometer_info = 16; + * .GNSSPosition initial_position = 17; */ - public Builder setBarometerInfo( - Sensor_Info.Builder builderForValue) { - if (barometerInfoBuilder_ == null) { - barometerInfo_ = builderForValue.build(); + public Builder setInitialPosition( + Traj.GNSSPosition.Builder builderForValue) { + if (initialPositionBuilder_ == null) { + initialPosition_ = builderForValue.build(); onChanged(); } else { - barometerInfoBuilder_.setMessage(builderForValue.build()); + initialPositionBuilder_.setMessage(builderForValue.build()); } return this; } /** - * optional .Sensor_Info barometer_info = 16; + * .GNSSPosition initial_position = 17; */ - public Builder mergeBarometerInfo(Sensor_Info value) { - if (barometerInfoBuilder_ == null) { - if (barometerInfo_ != null) { - barometerInfo_ = - Sensor_Info.newBuilder(barometerInfo_).mergeFrom(value).buildPartial(); + public Builder mergeInitialPosition(Traj.GNSSPosition value) { + if (initialPositionBuilder_ == null) { + if (initialPosition_ != null) { + initialPosition_ = + Traj.GNSSPosition.newBuilder(initialPosition_).mergeFrom(value).buildPartial(); } else { - barometerInfo_ = value; + initialPosition_ = value; } onChanged(); } else { - barometerInfoBuilder_.mergeFrom(value); + initialPositionBuilder_.mergeFrom(value); } return this; } /** - * optional .Sensor_Info barometer_info = 16; + * .GNSSPosition initial_position = 17; */ - public Builder clearBarometerInfo() { - if (barometerInfoBuilder_ == null) { - barometerInfo_ = null; + public Builder clearInitialPosition() { + if (initialPositionBuilder_ == null) { + initialPosition_ = null; onChanged(); } else { - barometerInfo_ = null; - barometerInfoBuilder_ = null; + initialPosition_ = null; + initialPositionBuilder_ = null; } return this; } /** - * optional .Sensor_Info barometer_info = 16; + * .GNSSPosition initial_position = 17; */ - public Sensor_Info.Builder getBarometerInfoBuilder() { + public Traj.GNSSPosition.Builder getInitialPositionBuilder() { onChanged(); - return getBarometerInfoFieldBuilder().getBuilder(); + return getInitialPositionFieldBuilder().getBuilder(); } /** - * optional .Sensor_Info barometer_info = 16; + * .GNSSPosition initial_position = 17; */ - public Sensor_InfoOrBuilder getBarometerInfoOrBuilder() { - if (barometerInfoBuilder_ != null) { - return barometerInfoBuilder_.getMessageOrBuilder(); + public Traj.GNSSPositionOrBuilder getInitialPositionOrBuilder() { + if (initialPositionBuilder_ != null) { + return initialPositionBuilder_.getMessageOrBuilder(); } else { - return barometerInfo_ == null ? - Sensor_Info.getDefaultInstance() : barometerInfo_; + return initialPosition_ == null ? + Traj.GNSSPosition.getDefaultInstance() : initialPosition_; } } /** - * optional .Sensor_Info barometer_info = 16; + * .GNSSPosition initial_position = 17; */ private com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder> - getBarometerInfoFieldBuilder() { - if (barometerInfoBuilder_ == null) { - barometerInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder>( - getBarometerInfo(), + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder> + getInitialPositionFieldBuilder() { + if (initialPositionBuilder_ == null) { + initialPositionBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder>( + getInitialPosition(), getParentForChildren(), isClean()); - barometerInfo_ = null; + initialPosition_ = null; } - return barometerInfoBuilder_; + return initialPositionBuilder_; } - private Sensor_Info lightSensorInfo_ = null; - private com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder> lightSensorInfoBuilder_; + private java.util.List correctedPositions_ = + java.util.Collections.emptyList(); + private void ensureCorrectedPositionsIsMutable() { + if (!((bitField0_ & 0x00001000) != 0)) { + correctedPositions_ = new java.util.ArrayList(correctedPositions_); + bitField0_ |= 0x00001000; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder> correctedPositionsBuilder_; + /** - * optional .Sensor_Info light_sensor_info = 17; + * repeated .GNSSPosition corrected_positions = 18; */ - public boolean hasLightSensorInfo() { - return lightSensorInfoBuilder_ != null || lightSensorInfo_ != null; + public java.util.List getCorrectedPositionsList() { + if (correctedPositionsBuilder_ == null) { + return java.util.Collections.unmodifiableList(correctedPositions_); + } else { + return correctedPositionsBuilder_.getMessageList(); + } } /** - * optional .Sensor_Info light_sensor_info = 17; + * repeated .GNSSPosition corrected_positions = 18; */ - public Sensor_Info getLightSensorInfo() { - if (lightSensorInfoBuilder_ == null) { - return lightSensorInfo_ == null ? Sensor_Info.getDefaultInstance() : lightSensorInfo_; + public int getCorrectedPositionsCount() { + if (correctedPositionsBuilder_ == null) { + return correctedPositions_.size(); } else { - return lightSensorInfoBuilder_.getMessage(); + return correctedPositionsBuilder_.getCount(); } } /** - * optional .Sensor_Info light_sensor_info = 17; + * repeated .GNSSPosition corrected_positions = 18; */ - public Builder setLightSensorInfo(Sensor_Info value) { - if (lightSensorInfoBuilder_ == null) { + public Traj.GNSSPosition getCorrectedPositions(int index) { + if (correctedPositionsBuilder_ == null) { + return correctedPositions_.get(index); + } else { + return correctedPositionsBuilder_.getMessage(index); + } + } + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + public Builder setCorrectedPositions( + int index, Traj.GNSSPosition value) { + if (correctedPositionsBuilder_ == null) { if (value == null) { throw new NullPointerException(); } - lightSensorInfo_ = value; + ensureCorrectedPositionsIsMutable(); + correctedPositions_.set(index, value); onChanged(); } else { - lightSensorInfoBuilder_.setMessage(value); + correctedPositionsBuilder_.setMessage(index, value); } - return this; } /** - * optional .Sensor_Info light_sensor_info = 17; + * repeated .GNSSPosition corrected_positions = 18; */ - public Builder setLightSensorInfo( - Sensor_Info.Builder builderForValue) { - if (lightSensorInfoBuilder_ == null) { - lightSensorInfo_ = builderForValue.build(); + public Builder setCorrectedPositions( + int index, Traj.GNSSPosition.Builder builderForValue) { + if (correctedPositionsBuilder_ == null) { + ensureCorrectedPositionsIsMutable(); + correctedPositions_.set(index, builderForValue.build()); onChanged(); } else { - lightSensorInfoBuilder_.setMessage(builderForValue.build()); + correctedPositionsBuilder_.setMessage(index, builderForValue.build()); } - return this; } /** - * optional .Sensor_Info light_sensor_info = 17; + * repeated .GNSSPosition corrected_positions = 18; */ - public Builder mergeLightSensorInfo(Sensor_Info value) { - if (lightSensorInfoBuilder_ == null) { - if (lightSensorInfo_ != null) { - lightSensorInfo_ = - Sensor_Info.newBuilder(lightSensorInfo_).mergeFrom(value).buildPartial(); - } else { - lightSensorInfo_ = value; + public Builder addCorrectedPositions(Traj.GNSSPosition value) { + if (correctedPositionsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); } + ensureCorrectedPositionsIsMutable(); + correctedPositions_.add(value); onChanged(); } else { - lightSensorInfoBuilder_.mergeFrom(value); + correctedPositionsBuilder_.addMessage(value); } - return this; } /** - * optional .Sensor_Info light_sensor_info = 17; + * repeated .GNSSPosition corrected_positions = 18; */ - public Builder clearLightSensorInfo() { - if (lightSensorInfoBuilder_ == null) { - lightSensorInfo_ = null; + public Builder addCorrectedPositions( + int index, Traj.GNSSPosition value) { + if (correctedPositionsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureCorrectedPositionsIsMutable(); + correctedPositions_.add(index, value); onChanged(); } else { - lightSensorInfo_ = null; - lightSensorInfoBuilder_ = null; + correctedPositionsBuilder_.addMessage(index, value); } - return this; } /** - * optional .Sensor_Info light_sensor_info = 17; + * repeated .GNSSPosition corrected_positions = 18; */ - public Sensor_Info.Builder getLightSensorInfoBuilder() { - - onChanged(); - return getLightSensorInfoFieldBuilder().getBuilder(); + public Builder addCorrectedPositions( + Traj.GNSSPosition.Builder builderForValue) { + if (correctedPositionsBuilder_ == null) { + ensureCorrectedPositionsIsMutable(); + correctedPositions_.add(builderForValue.build()); + onChanged(); + } else { + correctedPositionsBuilder_.addMessage(builderForValue.build()); + } + return this; } /** - * optional .Sensor_Info light_sensor_info = 17; + * repeated .GNSSPosition corrected_positions = 18; */ - public Sensor_InfoOrBuilder getLightSensorInfoOrBuilder() { - if (lightSensorInfoBuilder_ != null) { - return lightSensorInfoBuilder_.getMessageOrBuilder(); + public Builder addCorrectedPositions( + int index, Traj.GNSSPosition.Builder builderForValue) { + if (correctedPositionsBuilder_ == null) { + ensureCorrectedPositionsIsMutable(); + correctedPositions_.add(index, builderForValue.build()); + onChanged(); } else { - return lightSensorInfo_ == null ? - Sensor_Info.getDefaultInstance() : lightSensorInfo_; + correctedPositionsBuilder_.addMessage(index, builderForValue.build()); } + return this; } /** - * optional .Sensor_Info light_sensor_info = 17; + * repeated .GNSSPosition corrected_positions = 18; */ - private com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder> - getLightSensorInfoFieldBuilder() { - if (lightSensorInfoBuilder_ == null) { - lightSensorInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - Sensor_Info, Sensor_Info.Builder, Sensor_InfoOrBuilder>( - getLightSensorInfo(), - getParentForChildren(), - isClean()); - lightSensorInfo_ = null; + public Builder addAllCorrectedPositions( + java.lang.Iterable values) { + if (correctedPositionsBuilder_ == null) { + ensureCorrectedPositionsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, correctedPositions_); + onChanged(); + } else { + correctedPositionsBuilder_.addAllMessages(values); } - return lightSensorInfoBuilder_; - } - public final Builder setUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { return this; } - - public final Builder mergeUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + public Builder clearCorrectedPositions() { + if (correctedPositionsBuilder_ == null) { + correctedPositions_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00001000); + onChanged(); + } else { + correctedPositionsBuilder_.clear(); + } return this; } - - - // @@protoc_insertion_point(builder_scope:Trajectory) + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + public Builder removeCorrectedPositions(int index) { + if (correctedPositionsBuilder_ == null) { + ensureCorrectedPositionsIsMutable(); + correctedPositions_.remove(index); + onChanged(); + } else { + correctedPositionsBuilder_.remove(index); + } + return this; + } + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + public Traj.GNSSPosition.Builder getCorrectedPositionsBuilder( + int index) { + return getCorrectedPositionsFieldBuilder().getBuilder(index); + } + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + public Traj.GNSSPositionOrBuilder getCorrectedPositionsOrBuilder( + int index) { + if (correctedPositionsBuilder_ == null) { + return correctedPositions_.get(index); } else { + return correctedPositionsBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + public java.util.List + getCorrectedPositionsOrBuilderList() { + if (correctedPositionsBuilder_ != null) { + return correctedPositionsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(correctedPositions_); + } + } + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + public Traj.GNSSPosition.Builder addCorrectedPositionsBuilder() { + return getCorrectedPositionsFieldBuilder().addBuilder( + Traj.GNSSPosition.getDefaultInstance()); + } + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + public Traj.GNSSPosition.Builder addCorrectedPositionsBuilder( + int index) { + return getCorrectedPositionsFieldBuilder().addBuilder( + index, Traj.GNSSPosition.getDefaultInstance()); + } + /** + * repeated .GNSSPosition corrected_positions = 18; + */ + public java.util.List + getCorrectedPositionsBuilderList() { + return getCorrectedPositionsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder> + getCorrectedPositionsFieldBuilder() { + if (correctedPositionsBuilder_ == null) { + correctedPositionsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder>( + correctedPositions_, + ((bitField0_ & 0x00001000) != 0), + getParentForChildren(), + isClean()); + correctedPositions_ = null; + } + return correctedPositionsBuilder_; + } + + private Traj.SensorInfo accelerometerInfo_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> accelerometerInfoBuilder_; + /** + * .SensorInfo accelerometer_info = 19; + * @return Whether the accelerometerInfo field is set. + */ + public boolean hasAccelerometerInfo() { + return accelerometerInfoBuilder_ != null || accelerometerInfo_ != null; + } + /** + * .SensorInfo accelerometer_info = 19; + * @return The accelerometerInfo. + */ + public Traj.SensorInfo getAccelerometerInfo() { + if (accelerometerInfoBuilder_ == null) { + return accelerometerInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : accelerometerInfo_; + } else { + return accelerometerInfoBuilder_.getMessage(); + } + } + /** + * .SensorInfo accelerometer_info = 19; + */ + public Builder setAccelerometerInfo(Traj.SensorInfo value) { + if (accelerometerInfoBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + accelerometerInfo_ = value; + onChanged(); + } else { + accelerometerInfoBuilder_.setMessage(value); + } + + return this; + } + /** + * .SensorInfo accelerometer_info = 19; + */ + public Builder setAccelerometerInfo( + Traj.SensorInfo.Builder builderForValue) { + if (accelerometerInfoBuilder_ == null) { + accelerometerInfo_ = builderForValue.build(); + onChanged(); + } else { + accelerometerInfoBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + * .SensorInfo accelerometer_info = 19; + */ + public Builder mergeAccelerometerInfo(Traj.SensorInfo value) { + if (accelerometerInfoBuilder_ == null) { + if (accelerometerInfo_ != null) { + accelerometerInfo_ = + Traj.SensorInfo.newBuilder(accelerometerInfo_).mergeFrom(value).buildPartial(); + } else { + accelerometerInfo_ = value; + } + onChanged(); + } else { + accelerometerInfoBuilder_.mergeFrom(value); + } + + return this; + } + /** + * .SensorInfo accelerometer_info = 19; + */ + public Builder clearAccelerometerInfo() { + if (accelerometerInfoBuilder_ == null) { + accelerometerInfo_ = null; + onChanged(); + } else { + accelerometerInfo_ = null; + accelerometerInfoBuilder_ = null; + } + + return this; + } + /** + * .SensorInfo accelerometer_info = 19; + */ + public Traj.SensorInfo.Builder getAccelerometerInfoBuilder() { + + onChanged(); + return getAccelerometerInfoFieldBuilder().getBuilder(); + } + /** + * .SensorInfo accelerometer_info = 19; + */ + public Traj.SensorInfoOrBuilder getAccelerometerInfoOrBuilder() { + if (accelerometerInfoBuilder_ != null) { + return accelerometerInfoBuilder_.getMessageOrBuilder(); + } else { + return accelerometerInfo_ == null ? + Traj.SensorInfo.getDefaultInstance() : accelerometerInfo_; + } + } + /** + * .SensorInfo accelerometer_info = 19; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> + getAccelerometerInfoFieldBuilder() { + if (accelerometerInfoBuilder_ == null) { + accelerometerInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder>( + getAccelerometerInfo(), + getParentForChildren(), + isClean()); + accelerometerInfo_ = null; + } + return accelerometerInfoBuilder_; + } + + private Traj.SensorInfo gyroscopeInfo_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> gyroscopeInfoBuilder_; + /** + * .SensorInfo gyroscope_info = 20; + * @return Whether the gyroscopeInfo field is set. + */ + public boolean hasGyroscopeInfo() { + return gyroscopeInfoBuilder_ != null || gyroscopeInfo_ != null; + } + /** + * .SensorInfo gyroscope_info = 20; + * @return The gyroscopeInfo. + */ + public Traj.SensorInfo getGyroscopeInfo() { + if (gyroscopeInfoBuilder_ == null) { + return gyroscopeInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : gyroscopeInfo_; + } else { + return gyroscopeInfoBuilder_.getMessage(); + } + } + /** + * .SensorInfo gyroscope_info = 20; + */ + public Builder setGyroscopeInfo(Traj.SensorInfo value) { + if (gyroscopeInfoBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + gyroscopeInfo_ = value; + onChanged(); + } else { + gyroscopeInfoBuilder_.setMessage(value); + } + + return this; + } + /** + * .SensorInfo gyroscope_info = 20; + */ + public Builder setGyroscopeInfo( + Traj.SensorInfo.Builder builderForValue) { + if (gyroscopeInfoBuilder_ == null) { + gyroscopeInfo_ = builderForValue.build(); + onChanged(); + } else { + gyroscopeInfoBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + * .SensorInfo gyroscope_info = 20; + */ + public Builder mergeGyroscopeInfo(Traj.SensorInfo value) { + if (gyroscopeInfoBuilder_ == null) { + if (gyroscopeInfo_ != null) { + gyroscopeInfo_ = + Traj.SensorInfo.newBuilder(gyroscopeInfo_).mergeFrom(value).buildPartial(); + } else { + gyroscopeInfo_ = value; + } + onChanged(); + } else { + gyroscopeInfoBuilder_.mergeFrom(value); + } + + return this; + } + /** + * .SensorInfo gyroscope_info = 20; + */ + public Builder clearGyroscopeInfo() { + if (gyroscopeInfoBuilder_ == null) { + gyroscopeInfo_ = null; + onChanged(); + } else { + gyroscopeInfo_ = null; + gyroscopeInfoBuilder_ = null; + } + + return this; + } + /** + * .SensorInfo gyroscope_info = 20; + */ + public Traj.SensorInfo.Builder getGyroscopeInfoBuilder() { + + onChanged(); + return getGyroscopeInfoFieldBuilder().getBuilder(); + } + /** + * .SensorInfo gyroscope_info = 20; + */ + public Traj.SensorInfoOrBuilder getGyroscopeInfoOrBuilder() { + if (gyroscopeInfoBuilder_ != null) { + return gyroscopeInfoBuilder_.getMessageOrBuilder(); + } else { + return gyroscopeInfo_ == null ? + Traj.SensorInfo.getDefaultInstance() : gyroscopeInfo_; + } + } + /** + * .SensorInfo gyroscope_info = 20; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> + getGyroscopeInfoFieldBuilder() { + if (gyroscopeInfoBuilder_ == null) { + gyroscopeInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder>( + getGyroscopeInfo(), + getParentForChildren(), + isClean()); + gyroscopeInfo_ = null; + } + return gyroscopeInfoBuilder_; + } + + private Traj.SensorInfo rotationVectorInfo_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> rotationVectorInfoBuilder_; + /** + * .SensorInfo rotation_vector_info = 21; + * @return Whether the rotationVectorInfo field is set. + */ + public boolean hasRotationVectorInfo() { + return rotationVectorInfoBuilder_ != null || rotationVectorInfo_ != null; + } + /** + * .SensorInfo rotation_vector_info = 21; + * @return The rotationVectorInfo. + */ + public Traj.SensorInfo getRotationVectorInfo() { + if (rotationVectorInfoBuilder_ == null) { + return rotationVectorInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : rotationVectorInfo_; + } else { + return rotationVectorInfoBuilder_.getMessage(); + } + } + /** + * .SensorInfo rotation_vector_info = 21; + */ + public Builder setRotationVectorInfo(Traj.SensorInfo value) { + if (rotationVectorInfoBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + rotationVectorInfo_ = value; + onChanged(); + } else { + rotationVectorInfoBuilder_.setMessage(value); + } + + return this; + } + /** + * .SensorInfo rotation_vector_info = 21; + */ + public Builder setRotationVectorInfo( + Traj.SensorInfo.Builder builderForValue) { + if (rotationVectorInfoBuilder_ == null) { + rotationVectorInfo_ = builderForValue.build(); + onChanged(); + } else { + rotationVectorInfoBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + * .SensorInfo rotation_vector_info = 21; + */ + public Builder mergeRotationVectorInfo(Traj.SensorInfo value) { + if (rotationVectorInfoBuilder_ == null) { + if (rotationVectorInfo_ != null) { + rotationVectorInfo_ = + Traj.SensorInfo.newBuilder(rotationVectorInfo_).mergeFrom(value).buildPartial(); + } else { + rotationVectorInfo_ = value; + } + onChanged(); + } else { + rotationVectorInfoBuilder_.mergeFrom(value); + } + + return this; + } + /** + * .SensorInfo rotation_vector_info = 21; + */ + public Builder clearRotationVectorInfo() { + if (rotationVectorInfoBuilder_ == null) { + rotationVectorInfo_ = null; + onChanged(); + } else { + rotationVectorInfo_ = null; + rotationVectorInfoBuilder_ = null; + } + + return this; + } + /** + * .SensorInfo rotation_vector_info = 21; + */ + public Traj.SensorInfo.Builder getRotationVectorInfoBuilder() { + + onChanged(); + return getRotationVectorInfoFieldBuilder().getBuilder(); + } + /** + * .SensorInfo rotation_vector_info = 21; + */ + public Traj.SensorInfoOrBuilder getRotationVectorInfoOrBuilder() { + if (rotationVectorInfoBuilder_ != null) { + return rotationVectorInfoBuilder_.getMessageOrBuilder(); + } else { + return rotationVectorInfo_ == null ? + Traj.SensorInfo.getDefaultInstance() : rotationVectorInfo_; + } + } + /** + * .SensorInfo rotation_vector_info = 21; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> + getRotationVectorInfoFieldBuilder() { + if (rotationVectorInfoBuilder_ == null) { + rotationVectorInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder>( + getRotationVectorInfo(), + getParentForChildren(), + isClean()); + rotationVectorInfo_ = null; + } + return rotationVectorInfoBuilder_; + } + + private Traj.SensorInfo magnetometerInfo_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> magnetometerInfoBuilder_; + /** + * .SensorInfo magnetometer_info = 22; + * @return Whether the magnetometerInfo field is set. + */ + public boolean hasMagnetometerInfo() { + return magnetometerInfoBuilder_ != null || magnetometerInfo_ != null; + } + /** + * .SensorInfo magnetometer_info = 22; + * @return The magnetometerInfo. + */ + public Traj.SensorInfo getMagnetometerInfo() { + if (magnetometerInfoBuilder_ == null) { + return magnetometerInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : magnetometerInfo_; + } else { + return magnetometerInfoBuilder_.getMessage(); + } + } + /** + * .SensorInfo magnetometer_info = 22; + */ + public Builder setMagnetometerInfo(Traj.SensorInfo value) { + if (magnetometerInfoBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + magnetometerInfo_ = value; + onChanged(); + } else { + magnetometerInfoBuilder_.setMessage(value); + } + + return this; + } + /** + * .SensorInfo magnetometer_info = 22; + */ + public Builder setMagnetometerInfo( + Traj.SensorInfo.Builder builderForValue) { + if (magnetometerInfoBuilder_ == null) { + magnetometerInfo_ = builderForValue.build(); + onChanged(); + } else { + magnetometerInfoBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + * .SensorInfo magnetometer_info = 22; + */ + public Builder mergeMagnetometerInfo(Traj.SensorInfo value) { + if (magnetometerInfoBuilder_ == null) { + if (magnetometerInfo_ != null) { + magnetometerInfo_ = + Traj.SensorInfo.newBuilder(magnetometerInfo_).mergeFrom(value).buildPartial(); + } else { + magnetometerInfo_ = value; + } + onChanged(); + } else { + magnetometerInfoBuilder_.mergeFrom(value); + } + + return this; + } + /** + * .SensorInfo magnetometer_info = 22; + */ + public Builder clearMagnetometerInfo() { + if (magnetometerInfoBuilder_ == null) { + magnetometerInfo_ = null; + onChanged(); + } else { + magnetometerInfo_ = null; + magnetometerInfoBuilder_ = null; + } + + return this; + } + /** + * .SensorInfo magnetometer_info = 22; + */ + public Traj.SensorInfo.Builder getMagnetometerInfoBuilder() { + + onChanged(); + return getMagnetometerInfoFieldBuilder().getBuilder(); + } + /** + * .SensorInfo magnetometer_info = 22; + */ + public Traj.SensorInfoOrBuilder getMagnetometerInfoOrBuilder() { + if (magnetometerInfoBuilder_ != null) { + return magnetometerInfoBuilder_.getMessageOrBuilder(); + } else { + return magnetometerInfo_ == null ? + Traj.SensorInfo.getDefaultInstance() : magnetometerInfo_; + } + } + /** + * .SensorInfo magnetometer_info = 22; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> + getMagnetometerInfoFieldBuilder() { + if (magnetometerInfoBuilder_ == null) { + magnetometerInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder>( + getMagnetometerInfo(), + getParentForChildren(), + isClean()); + magnetometerInfo_ = null; + } + return magnetometerInfoBuilder_; + } + + private Traj.SensorInfo barometerInfo_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> barometerInfoBuilder_; + /** + * .SensorInfo barometer_info = 23; + * @return Whether the barometerInfo field is set. + */ + public boolean hasBarometerInfo() { + return barometerInfoBuilder_ != null || barometerInfo_ != null; + } + /** + * .SensorInfo barometer_info = 23; + * @return The barometerInfo. + */ + public Traj.SensorInfo getBarometerInfo() { + if (barometerInfoBuilder_ == null) { + return barometerInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : barometerInfo_; + } else { + return barometerInfoBuilder_.getMessage(); + } + } + /** + * .SensorInfo barometer_info = 23; + */ + public Builder setBarometerInfo(Traj.SensorInfo value) { + if (barometerInfoBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + barometerInfo_ = value; + onChanged(); + } else { + barometerInfoBuilder_.setMessage(value); + } + + return this; + } + /** + * .SensorInfo barometer_info = 23; + */ + public Builder setBarometerInfo( + Traj.SensorInfo.Builder builderForValue) { + if (barometerInfoBuilder_ == null) { + barometerInfo_ = builderForValue.build(); + onChanged(); + } else { + barometerInfoBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + * .SensorInfo barometer_info = 23; + */ + public Builder mergeBarometerInfo(Traj.SensorInfo value) { + if (barometerInfoBuilder_ == null) { + if (barometerInfo_ != null) { + barometerInfo_ = + Traj.SensorInfo.newBuilder(barometerInfo_).mergeFrom(value).buildPartial(); + } else { + barometerInfo_ = value; + } + onChanged(); + } else { + barometerInfoBuilder_.mergeFrom(value); + } + + return this; + } + /** + * .SensorInfo barometer_info = 23; + */ + public Builder clearBarometerInfo() { + if (barometerInfoBuilder_ == null) { + barometerInfo_ = null; + onChanged(); + } else { + barometerInfo_ = null; + barometerInfoBuilder_ = null; + } + + return this; + } + /** + * .SensorInfo barometer_info = 23; + */ + public Traj.SensorInfo.Builder getBarometerInfoBuilder() { + + onChanged(); + return getBarometerInfoFieldBuilder().getBuilder(); + } + /** + * .SensorInfo barometer_info = 23; + */ + public Traj.SensorInfoOrBuilder getBarometerInfoOrBuilder() { + if (barometerInfoBuilder_ != null) { + return barometerInfoBuilder_.getMessageOrBuilder(); + } else { + return barometerInfo_ == null ? + Traj.SensorInfo.getDefaultInstance() : barometerInfo_; + } + } + /** + * .SensorInfo barometer_info = 23; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> + getBarometerInfoFieldBuilder() { + if (barometerInfoBuilder_ == null) { + barometerInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder>( + getBarometerInfo(), + getParentForChildren(), + isClean()); + barometerInfo_ = null; + } + return barometerInfoBuilder_; + } + + private Traj.SensorInfo lightSensorInfo_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> lightSensorInfoBuilder_; + /** + * .SensorInfo light_sensor_info = 24; + * @return Whether the lightSensorInfo field is set. + */ + public boolean hasLightSensorInfo() { + return lightSensorInfoBuilder_ != null || lightSensorInfo_ != null; + } + /** + * .SensorInfo light_sensor_info = 24; + * @return The lightSensorInfo. + */ + public Traj.SensorInfo getLightSensorInfo() { + if (lightSensorInfoBuilder_ == null) { + return lightSensorInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : lightSensorInfo_; + } else { + return lightSensorInfoBuilder_.getMessage(); + } + } + /** + * .SensorInfo light_sensor_info = 24; + */ + public Builder setLightSensorInfo(Traj.SensorInfo value) { + if (lightSensorInfoBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + lightSensorInfo_ = value; + onChanged(); + } else { + lightSensorInfoBuilder_.setMessage(value); + } + + return this; + } + /** + * .SensorInfo light_sensor_info = 24; + */ + public Builder setLightSensorInfo( + Traj.SensorInfo.Builder builderForValue) { + if (lightSensorInfoBuilder_ == null) { + lightSensorInfo_ = builderForValue.build(); + onChanged(); + } else { + lightSensorInfoBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + * .SensorInfo light_sensor_info = 24; + */ + public Builder mergeLightSensorInfo(Traj.SensorInfo value) { + if (lightSensorInfoBuilder_ == null) { + if (lightSensorInfo_ != null) { + lightSensorInfo_ = + Traj.SensorInfo.newBuilder(lightSensorInfo_).mergeFrom(value).buildPartial(); + } else { + lightSensorInfo_ = value; + } + onChanged(); + } else { + lightSensorInfoBuilder_.mergeFrom(value); + } + + return this; + } + /** + * .SensorInfo light_sensor_info = 24; + */ + public Builder clearLightSensorInfo() { + if (lightSensorInfoBuilder_ == null) { + lightSensorInfo_ = null; + onChanged(); + } else { + lightSensorInfo_ = null; + lightSensorInfoBuilder_ = null; + } + + return this; + } + /** + * .SensorInfo light_sensor_info = 24; + */ + public Traj.SensorInfo.Builder getLightSensorInfoBuilder() { + + onChanged(); + return getLightSensorInfoFieldBuilder().getBuilder(); + } + /** + * .SensorInfo light_sensor_info = 24; + */ + public Traj.SensorInfoOrBuilder getLightSensorInfoOrBuilder() { + if (lightSensorInfoBuilder_ != null) { + return lightSensorInfoBuilder_.getMessageOrBuilder(); + } else { + return lightSensorInfo_ == null ? + Traj.SensorInfo.getDefaultInstance() : lightSensorInfo_; + } + } + /** + * .SensorInfo light_sensor_info = 24; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> + getLightSensorInfoFieldBuilder() { + if (lightSensorInfoBuilder_ == null) { + lightSensorInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder>( + getLightSensorInfo(), + getParentForChildren(), + isClean()); + lightSensorInfo_ = null; + } + return lightSensorInfoBuilder_; + } + + private Traj.SensorInfo proximityInfo_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> proximityInfoBuilder_; + /** + * .SensorInfo proximity_info = 25; + * @return Whether the proximityInfo field is set. + */ + public boolean hasProximityInfo() { + return proximityInfoBuilder_ != null || proximityInfo_ != null; + } + /** + * .SensorInfo proximity_info = 25; + * @return The proximityInfo. + */ + public Traj.SensorInfo getProximityInfo() { + if (proximityInfoBuilder_ == null) { + return proximityInfo_ == null ? Traj.SensorInfo.getDefaultInstance() : proximityInfo_; + } else { + return proximityInfoBuilder_.getMessage(); + } + } + /** + * .SensorInfo proximity_info = 25; + */ + public Builder setProximityInfo(Traj.SensorInfo value) { + if (proximityInfoBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + proximityInfo_ = value; + onChanged(); + } else { + proximityInfoBuilder_.setMessage(value); + } + + return this; + } + /** + * .SensorInfo proximity_info = 25; + */ + public Builder setProximityInfo( + Traj.SensorInfo.Builder builderForValue) { + if (proximityInfoBuilder_ == null) { + proximityInfo_ = builderForValue.build(); + onChanged(); + } else { + proximityInfoBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + * .SensorInfo proximity_info = 25; + */ + public Builder mergeProximityInfo(Traj.SensorInfo value) { + if (proximityInfoBuilder_ == null) { + if (proximityInfo_ != null) { + proximityInfo_ = + Traj.SensorInfo.newBuilder(proximityInfo_).mergeFrom(value).buildPartial(); + } else { + proximityInfo_ = value; + } + onChanged(); + } else { + proximityInfoBuilder_.mergeFrom(value); + } + + return this; + } + /** + * .SensorInfo proximity_info = 25; + */ + public Builder clearProximityInfo() { + if (proximityInfoBuilder_ == null) { + proximityInfo_ = null; + onChanged(); + } else { + proximityInfo_ = null; + proximityInfoBuilder_ = null; + } + + return this; + } + /** + * .SensorInfo proximity_info = 25; + */ + public Traj.SensorInfo.Builder getProximityInfoBuilder() { + + onChanged(); + return getProximityInfoFieldBuilder().getBuilder(); + } + /** + * .SensorInfo proximity_info = 25; + */ + public Traj.SensorInfoOrBuilder getProximityInfoOrBuilder() { + if (proximityInfoBuilder_ != null) { + return proximityInfoBuilder_.getMessageOrBuilder(); + } else { + return proximityInfo_ == null ? + Traj.SensorInfo.getDefaultInstance() : proximityInfo_; + } + } + /** + * .SensorInfo proximity_info = 25; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder> + getProximityInfoFieldBuilder() { + if (proximityInfoBuilder_ == null) { + proximityInfoBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.SensorInfo, Traj.SensorInfo.Builder, Traj.SensorInfoOrBuilder>( + getProximityInfo(), + getParentForChildren(), + isClean()); + proximityInfo_ = null; + } + return proximityInfoBuilder_; + } + + private java.util.List testPoints_ = + java.util.Collections.emptyList(); + private void ensureTestPointsIsMutable() { + if (!((bitField0_ & 0x00002000) != 0)) { + testPoints_ = new java.util.ArrayList(testPoints_); + bitField0_ |= 0x00002000; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder> testPointsBuilder_; + + /** + * repeated .GNSSPosition test_points = 26; + */ + public java.util.List getTestPointsList() { + if (testPointsBuilder_ == null) { + return java.util.Collections.unmodifiableList(testPoints_); + } else { + return testPointsBuilder_.getMessageList(); + } + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public int getTestPointsCount() { + if (testPointsBuilder_ == null) { + return testPoints_.size(); + } else { + return testPointsBuilder_.getCount(); + } + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Traj.GNSSPosition getTestPoints(int index) { + if (testPointsBuilder_ == null) { + return testPoints_.get(index); + } else { + return testPointsBuilder_.getMessage(index); + } + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Builder setTestPoints( + int index, Traj.GNSSPosition value) { + if (testPointsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureTestPointsIsMutable(); + testPoints_.set(index, value); + onChanged(); + } else { + testPointsBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Builder setTestPoints( + int index, Traj.GNSSPosition.Builder builderForValue) { + if (testPointsBuilder_ == null) { + ensureTestPointsIsMutable(); + testPoints_.set(index, builderForValue.build()); + onChanged(); + } else { + testPointsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Builder addTestPoints(Traj.GNSSPosition value) { + if (testPointsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureTestPointsIsMutable(); + testPoints_.add(value); + onChanged(); + } else { + testPointsBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Builder addTestPoints( + int index, Traj.GNSSPosition value) { + if (testPointsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureTestPointsIsMutable(); + testPoints_.add(index, value); + onChanged(); + } else { + testPointsBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Builder addTestPoints( + Traj.GNSSPosition.Builder builderForValue) { + if (testPointsBuilder_ == null) { + ensureTestPointsIsMutable(); + testPoints_.add(builderForValue.build()); + onChanged(); + } else { + testPointsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Builder addTestPoints( + int index, Traj.GNSSPosition.Builder builderForValue) { + if (testPointsBuilder_ == null) { + ensureTestPointsIsMutable(); + testPoints_.add(index, builderForValue.build()); + onChanged(); + } else { + testPointsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Builder addAllTestPoints( + java.lang.Iterable values) { + if (testPointsBuilder_ == null) { + ensureTestPointsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, testPoints_); + onChanged(); + } else { + testPointsBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Builder clearTestPoints() { + if (testPointsBuilder_ == null) { + testPoints_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00002000); + onChanged(); + } else { + testPointsBuilder_.clear(); + } + return this; + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Builder removeTestPoints(int index) { + if (testPointsBuilder_ == null) { + ensureTestPointsIsMutable(); + testPoints_.remove(index); + onChanged(); + } else { + testPointsBuilder_.remove(index); + } + return this; + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Traj.GNSSPosition.Builder getTestPointsBuilder( + int index) { + return getTestPointsFieldBuilder().getBuilder(index); + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Traj.GNSSPositionOrBuilder getTestPointsOrBuilder( + int index) { + if (testPointsBuilder_ == null) { + return testPoints_.get(index); } else { + return testPointsBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public java.util.List + getTestPointsOrBuilderList() { + if (testPointsBuilder_ != null) { + return testPointsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(testPoints_); + } + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Traj.GNSSPosition.Builder addTestPointsBuilder() { + return getTestPointsFieldBuilder().addBuilder( + Traj.GNSSPosition.getDefaultInstance()); + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public Traj.GNSSPosition.Builder addTestPointsBuilder( + int index) { + return getTestPointsFieldBuilder().addBuilder( + index, Traj.GNSSPosition.getDefaultInstance()); + } + /** + * repeated .GNSSPosition test_points = 26; + */ + public java.util.List + getTestPointsBuilderList() { + return getTestPointsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder> + getTestPointsFieldBuilder() { + if (testPointsBuilder_ == null) { + testPointsBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder>( + testPoints_, + ((bitField0_ & 0x00002000) != 0), + getParentForChildren(), + isClean()); + testPoints_ = null; + } + return testPointsBuilder_; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:Trajectory) + } + + // @@protoc_insertion_point(class_scope:Trajectory) + private static final Traj.Trajectory DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new Traj.Trajectory(); + } + + public static Traj.Trajectory getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Trajectory parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new Trajectory(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public Traj.Trajectory getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface RelativePositionOrBuilder extends + // @@protoc_insertion_point(interface_extends:RelativePosition) + com.google.protobuf.MessageOrBuilder { + + /** + *
+     * milliseconds from the start_timestamp
+     * 
+ * + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + long getRelativeTimestamp(); + + /** + *
+     * Both in metres. You should implement an algorithm to estimate
+     * these values. The values are always relative to your start point
+     * so the first entry should always be x = 0.0, y = 0.0
+     * 
+ * + * float x = 2; + * @return The x. + */ + float getX(); + + /** + * float y = 3; + * @return The y. + */ + float getY(); + } + /** + * Protobuf type {@code RelativePosition} + */ + public static final class RelativePosition extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:RelativePosition) + RelativePositionOrBuilder { + private static final long serialVersionUID = 0L; + // Use RelativePosition.newBuilder() to construct. + private RelativePosition(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private RelativePosition() { + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new RelativePosition(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private RelativePosition( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + + relativeTimestamp_ = input.readInt64(); + break; + } + case 21: { + + x_ = input.readFloat(); + break; + } + case 29: { + + y_ = input.readFloat(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return Traj.internal_static_RelativePosition_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_RelativePosition_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.RelativePosition.class, Traj.RelativePosition.Builder.class); + } + + public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; + private long relativeTimestamp_; + /** + *
+     * milliseconds from the start_timestamp
+     * 
+ * + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + + public static final int X_FIELD_NUMBER = 2; + private float x_; + /** + *
+     * Both in metres. You should implement an algorithm to estimate
+     * these values. The values are always relative to your start point
+     * so the first entry should always be x = 0.0, y = 0.0
+     * 
+ * + * float x = 2; + * @return The x. + */ + @java.lang.Override + public float getX() { + return x_; + } + + public static final int Y_FIELD_NUMBER = 3; + private float y_; + /** + * float y = 3; + * @return The y. + */ + @java.lang.Override + public float getY() { + return y_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (relativeTimestamp_ != 0L) { + output.writeInt64(1, relativeTimestamp_); + } + if (java.lang.Float.floatToRawIntBits(x_) != 0) { + output.writeFloat(2, x_); + } + if (java.lang.Float.floatToRawIntBits(y_) != 0) { + output.writeFloat(3, y_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (relativeTimestamp_ != 0L) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, relativeTimestamp_); + } + if (java.lang.Float.floatToRawIntBits(x_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeFloatSize(2, x_); + } + if (java.lang.Float.floatToRawIntBits(y_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeFloatSize(3, y_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Traj.RelativePosition)) { + return super.equals(obj); + } + Traj.RelativePosition other = (Traj.RelativePosition) obj; + + if (getRelativeTimestamp() + != other.getRelativeTimestamp()) return false; + if (java.lang.Float.floatToIntBits(getX()) + != java.lang.Float.floatToIntBits( + other.getX())) return false; + if (java.lang.Float.floatToIntBits(getY()) + != java.lang.Float.floatToIntBits( + other.getY())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getRelativeTimestamp()); + hash = (37 * hash) + X_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getX()); + hash = (37 * hash) + Y_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getY()); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static Traj.RelativePosition parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.RelativePosition parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.RelativePosition parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.RelativePosition parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.RelativePosition parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.RelativePosition parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.RelativePosition parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Traj.RelativePosition parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static Traj.RelativePosition parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static Traj.RelativePosition parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static Traj.RelativePosition parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Traj.RelativePosition parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(Traj.RelativePosition prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code RelativePosition} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:RelativePosition) + Traj.RelativePositionOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return Traj.internal_static_RelativePosition_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_RelativePosition_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.RelativePosition.class, Traj.RelativePosition.Builder.class); + } + + // Construct using Traj.RelativePosition.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + relativeTimestamp_ = 0L; + + x_ = 0F; + + y_ = 0F; + + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return Traj.internal_static_RelativePosition_descriptor; + } + + @java.lang.Override + public Traj.RelativePosition getDefaultInstanceForType() { + return Traj.RelativePosition.getDefaultInstance(); + } + + @java.lang.Override + public Traj.RelativePosition build() { + Traj.RelativePosition result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public Traj.RelativePosition buildPartial() { + Traj.RelativePosition result = new Traj.RelativePosition(this); + result.relativeTimestamp_ = relativeTimestamp_; + result.x_ = x_; + result.y_ = y_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof Traj.RelativePosition) { + return mergeFrom((Traj.RelativePosition)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(Traj.RelativePosition other) { + if (other == Traj.RelativePosition.getDefaultInstance()) return this; + if (other.getRelativeTimestamp() != 0L) { + setRelativeTimestamp(other.getRelativeTimestamp()); + } + if (other.getX() != 0F) { + setX(other.getX()); + } + if (other.getY() != 0F) { + setY(other.getY()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Traj.RelativePosition parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (Traj.RelativePosition) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private long relativeTimestamp_ ; + /** + *
+       * milliseconds from the start_timestamp
+       * 
+ * + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + /** + *
+       * milliseconds from the start_timestamp
+       * 
+ * + * int64 relative_timestamp = 1; + * @param value The relativeTimestamp to set. + * @return This builder for chaining. + */ + public Builder setRelativeTimestamp(long value) { + + relativeTimestamp_ = value; + onChanged(); + return this; + } + /** + *
+       * milliseconds from the start_timestamp
+       * 
+ * + * int64 relative_timestamp = 1; + * @return This builder for chaining. + */ + public Builder clearRelativeTimestamp() { + + relativeTimestamp_ = 0L; + onChanged(); + return this; + } + + private float x_ ; + /** + *
+       * Both in metres. You should implement an algorithm to estimate
+       * these values. The values are always relative to your start point
+       * so the first entry should always be x = 0.0, y = 0.0
+       * 
+ * + * float x = 2; + * @return The x. + */ + @java.lang.Override + public float getX() { + return x_; + } + /** + *
+       * Both in metres. You should implement an algorithm to estimate
+       * these values. The values are always relative to your start point
+       * so the first entry should always be x = 0.0, y = 0.0
+       * 
+ * + * float x = 2; + * @param value The x to set. + * @return This builder for chaining. + */ + public Builder setX(float value) { + + x_ = value; + onChanged(); + return this; + } + /** + *
+       * Both in metres. You should implement an algorithm to estimate
+       * these values. The values are always relative to your start point
+       * so the first entry should always be x = 0.0, y = 0.0
+       * 
+ * + * float x = 2; + * @return This builder for chaining. + */ + public Builder clearX() { + + x_ = 0F; + onChanged(); + return this; + } + + private float y_ ; + /** + * float y = 3; + * @return The y. + */ + @java.lang.Override + public float getY() { + return y_; + } + /** + * float y = 3; + * @param value The y to set. + * @return This builder for chaining. + */ + public Builder setY(float value) { + + y_ = value; + onChanged(); + return this; + } + /** + * float y = 3; + * @return This builder for chaining. + */ + public Builder clearY() { + + y_ = 0F; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:RelativePosition) + } + + // @@protoc_insertion_point(class_scope:RelativePosition) + private static final Traj.RelativePosition DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new Traj.RelativePosition(); + } + + public static Traj.RelativePosition getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public RelativePosition parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new RelativePosition(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public Traj.RelativePosition getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface IMUReadingOrBuilder extends + // @@protoc_insertion_point(interface_extends:IMUReading) + com.google.protobuf.MessageOrBuilder { + + /** + *
+     * milliseconds
+     * 
+ * + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + long getRelativeTimestamp(); + + /** + *
+     * Accelerometer [m/s^2]
+     * 
+ * + * .Vector3 acc = 2; + * @return Whether the acc field is set. + */ + boolean hasAcc(); + /** + *
+     * Accelerometer [m/s^2]
+     * 
+ * + * .Vector3 acc = 2; + * @return The acc. + */ + Traj.Vector3 getAcc(); + /** + *
+     * Accelerometer [m/s^2]
+     * 
+ * + * .Vector3 acc = 2; + */ + Traj.Vector3OrBuilder getAccOrBuilder(); + + /** + *
+     * Gyroscope [radians/s]
+     * 
+ * + * .Vector3 gyr = 3; + * @return Whether the gyr field is set. + */ + boolean hasGyr(); + /** + *
+     * Gyroscope [radians/s]
+     * 
+ * + * .Vector3 gyr = 3; + * @return The gyr. + */ + Traj.Vector3 getGyr(); + /** + *
+     * Gyroscope [radians/s]
+     * 
+ * + * .Vector3 gyr = 3; + */ + Traj.Vector3OrBuilder getGyrOrBuilder(); + + /** + *
+     * Orientation [unitless], 4 components should square sum to ~1
+     * 
+ * + * .Quaternion rotation_vector = 4; + * @return Whether the rotationVector field is set. + */ + boolean hasRotationVector(); + /** + *
+     * Orientation [unitless], 4 components should square sum to ~1
+     * 
+ * + * .Quaternion rotation_vector = 4; + * @return The rotationVector. + */ + Traj.Quaternion getRotationVector(); + /** + *
+     * Orientation [unitless], 4 components should square sum to ~1
+     * 
+ * + * .Quaternion rotation_vector = 4; + */ + Traj.QuaternionOrBuilder getRotationVectorOrBuilder(); + + /** + *
+     * Number of steps so far
+     * 
+ * + * int32 step_count = 5; + * @return The stepCount. + */ + int getStepCount(); + } + /** + * Protobuf type {@code IMUReading} + */ + public static final class IMUReading extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:IMUReading) + IMUReadingOrBuilder { + private static final long serialVersionUID = 0L; + // Use IMUReading.newBuilder() to construct. + private IMUReading(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private IMUReading() { + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new IMUReading(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private IMUReading( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + + relativeTimestamp_ = input.readInt64(); + break; + } + case 18: { + Traj.Vector3.Builder subBuilder = null; + if (acc_ != null) { + subBuilder = acc_.toBuilder(); + } + acc_ = input.readMessage(Traj.Vector3.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(acc_); + acc_ = subBuilder.buildPartial(); + } + + break; + } + case 26: { + Traj.Vector3.Builder subBuilder = null; + if (gyr_ != null) { + subBuilder = gyr_.toBuilder(); + } + gyr_ = input.readMessage(Traj.Vector3.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(gyr_); + gyr_ = subBuilder.buildPartial(); + } + + break; + } + case 34: { + Traj.Quaternion.Builder subBuilder = null; + if (rotationVector_ != null) { + subBuilder = rotationVector_.toBuilder(); + } + rotationVector_ = input.readMessage(Traj.Quaternion.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(rotationVector_); + rotationVector_ = subBuilder.buildPartial(); + } + + break; + } + case 40: { + + stepCount_ = input.readInt32(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return Traj.internal_static_IMUReading_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_IMUReading_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.IMUReading.class, Traj.IMUReading.Builder.class); + } + + public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; + private long relativeTimestamp_; + /** + *
+     * milliseconds
+     * 
+ * + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + + public static final int ACC_FIELD_NUMBER = 2; + private Traj.Vector3 acc_; + /** + *
+     * Accelerometer [m/s^2]
+     * 
+ * + * .Vector3 acc = 2; + * @return Whether the acc field is set. + */ + @java.lang.Override + public boolean hasAcc() { + return acc_ != null; + } + /** + *
+     * Accelerometer [m/s^2]
+     * 
+ * + * .Vector3 acc = 2; + * @return The acc. + */ + @java.lang.Override + public Traj.Vector3 getAcc() { + return acc_ == null ? Traj.Vector3.getDefaultInstance() : acc_; + } + /** + *
+     * Accelerometer [m/s^2]
+     * 
+ * + * .Vector3 acc = 2; + */ + @java.lang.Override + public Traj.Vector3OrBuilder getAccOrBuilder() { + return getAcc(); + } + + public static final int GYR_FIELD_NUMBER = 3; + private Traj.Vector3 gyr_; + /** + *
+     * Gyroscope [radians/s]
+     * 
+ * + * .Vector3 gyr = 3; + * @return Whether the gyr field is set. + */ + @java.lang.Override + public boolean hasGyr() { + return gyr_ != null; + } + /** + *
+     * Gyroscope [radians/s]
+     * 
+ * + * .Vector3 gyr = 3; + * @return The gyr. + */ + @java.lang.Override + public Traj.Vector3 getGyr() { + return gyr_ == null ? Traj.Vector3.getDefaultInstance() : gyr_; + } + /** + *
+     * Gyroscope [radians/s]
+     * 
+ * + * .Vector3 gyr = 3; + */ + @java.lang.Override + public Traj.Vector3OrBuilder getGyrOrBuilder() { + return getGyr(); + } + + public static final int ROTATION_VECTOR_FIELD_NUMBER = 4; + private Traj.Quaternion rotationVector_; + /** + *
+     * Orientation [unitless], 4 components should square sum to ~1
+     * 
+ * + * .Quaternion rotation_vector = 4; + * @return Whether the rotationVector field is set. + */ + @java.lang.Override + public boolean hasRotationVector() { + return rotationVector_ != null; + } + /** + *
+     * Orientation [unitless], 4 components should square sum to ~1
+     * 
+ * + * .Quaternion rotation_vector = 4; + * @return The rotationVector. + */ + @java.lang.Override + public Traj.Quaternion getRotationVector() { + return rotationVector_ == null ? Traj.Quaternion.getDefaultInstance() : rotationVector_; + } + /** + *
+     * Orientation [unitless], 4 components should square sum to ~1
+     * 
+ * + * .Quaternion rotation_vector = 4; + */ + @java.lang.Override + public Traj.QuaternionOrBuilder getRotationVectorOrBuilder() { + return getRotationVector(); + } + + public static final int STEP_COUNT_FIELD_NUMBER = 5; + private int stepCount_; + /** + *
+     * Number of steps so far
+     * 
+ * + * int32 step_count = 5; + * @return The stepCount. + */ + @java.lang.Override + public int getStepCount() { + return stepCount_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (relativeTimestamp_ != 0L) { + output.writeInt64(1, relativeTimestamp_); + } + if (acc_ != null) { + output.writeMessage(2, getAcc()); + } + if (gyr_ != null) { + output.writeMessage(3, getGyr()); + } + if (rotationVector_ != null) { + output.writeMessage(4, getRotationVector()); + } + if (stepCount_ != 0) { + output.writeInt32(5, stepCount_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (relativeTimestamp_ != 0L) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, relativeTimestamp_); + } + if (acc_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, getAcc()); + } + if (gyr_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(3, getGyr()); + } + if (rotationVector_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, getRotationVector()); + } + if (stepCount_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(5, stepCount_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Traj.IMUReading)) { + return super.equals(obj); + } + Traj.IMUReading other = (Traj.IMUReading) obj; + + if (getRelativeTimestamp() + != other.getRelativeTimestamp()) return false; + if (hasAcc() != other.hasAcc()) return false; + if (hasAcc()) { + if (!getAcc() + .equals(other.getAcc())) return false; + } + if (hasGyr() != other.hasGyr()) return false; + if (hasGyr()) { + if (!getGyr() + .equals(other.getGyr())) return false; + } + if (hasRotationVector() != other.hasRotationVector()) return false; + if (hasRotationVector()) { + if (!getRotationVector() + .equals(other.getRotationVector())) return false; + } + if (getStepCount() + != other.getStepCount()) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getRelativeTimestamp()); + if (hasAcc()) { + hash = (37 * hash) + ACC_FIELD_NUMBER; + hash = (53 * hash) + getAcc().hashCode(); + } + if (hasGyr()) { + hash = (37 * hash) + GYR_FIELD_NUMBER; + hash = (53 * hash) + getGyr().hashCode(); + } + if (hasRotationVector()) { + hash = (37 * hash) + ROTATION_VECTOR_FIELD_NUMBER; + hash = (53 * hash) + getRotationVector().hashCode(); + } + hash = (37 * hash) + STEP_COUNT_FIELD_NUMBER; + hash = (53 * hash) + getStepCount(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static Traj.IMUReading parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.IMUReading parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.IMUReading parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.IMUReading parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.IMUReading parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.IMUReading parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.IMUReading parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Traj.IMUReading parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static Traj.IMUReading parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static Traj.IMUReading parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static Traj.IMUReading parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Traj.IMUReading parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(Traj.IMUReading prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code IMUReading} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:IMUReading) + Traj.IMUReadingOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return Traj.internal_static_IMUReading_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_IMUReading_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.IMUReading.class, Traj.IMUReading.Builder.class); + } + + // Construct using Traj.IMUReading.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + relativeTimestamp_ = 0L; + + if (accBuilder_ == null) { + acc_ = null; + } else { + acc_ = null; + accBuilder_ = null; + } + if (gyrBuilder_ == null) { + gyr_ = null; + } else { + gyr_ = null; + gyrBuilder_ = null; + } + if (rotationVectorBuilder_ == null) { + rotationVector_ = null; + } else { + rotationVector_ = null; + rotationVectorBuilder_ = null; + } + stepCount_ = 0; + + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return Traj.internal_static_IMUReading_descriptor; + } + + @java.lang.Override + public Traj.IMUReading getDefaultInstanceForType() { + return Traj.IMUReading.getDefaultInstance(); + } + + @java.lang.Override + public Traj.IMUReading build() { + Traj.IMUReading result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public Traj.IMUReading buildPartial() { + Traj.IMUReading result = new Traj.IMUReading(this); + result.relativeTimestamp_ = relativeTimestamp_; + if (accBuilder_ == null) { + result.acc_ = acc_; + } else { + result.acc_ = accBuilder_.build(); + } + if (gyrBuilder_ == null) { + result.gyr_ = gyr_; + } else { + result.gyr_ = gyrBuilder_.build(); + } + if (rotationVectorBuilder_ == null) { + result.rotationVector_ = rotationVector_; + } else { + result.rotationVector_ = rotationVectorBuilder_.build(); + } + result.stepCount_ = stepCount_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof Traj.IMUReading) { + return mergeFrom((Traj.IMUReading)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(Traj.IMUReading other) { + if (other == Traj.IMUReading.getDefaultInstance()) return this; + if (other.getRelativeTimestamp() != 0L) { + setRelativeTimestamp(other.getRelativeTimestamp()); + } + if (other.hasAcc()) { + mergeAcc(other.getAcc()); + } + if (other.hasGyr()) { + mergeGyr(other.getGyr()); + } + if (other.hasRotationVector()) { + mergeRotationVector(other.getRotationVector()); + } + if (other.getStepCount() != 0) { + setStepCount(other.getStepCount()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Traj.IMUReading parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (Traj.IMUReading) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private long relativeTimestamp_ ; + /** + *
+       * milliseconds
+       * 
+ * + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + /** + *
+       * milliseconds
+       * 
+ * + * int64 relative_timestamp = 1; + * @param value The relativeTimestamp to set. + * @return This builder for chaining. + */ + public Builder setRelativeTimestamp(long value) { + + relativeTimestamp_ = value; + onChanged(); + return this; + } + /** + *
+       * milliseconds
+       * 
+ * + * int64 relative_timestamp = 1; + * @return This builder for chaining. + */ + public Builder clearRelativeTimestamp() { + + relativeTimestamp_ = 0L; + onChanged(); + return this; + } + + private Traj.Vector3 acc_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.Vector3, Traj.Vector3.Builder, Traj.Vector3OrBuilder> accBuilder_; + /** + *
+       * Accelerometer [m/s^2]
+       * 
+ * + * .Vector3 acc = 2; + * @return Whether the acc field is set. + */ + public boolean hasAcc() { + return accBuilder_ != null || acc_ != null; + } + /** + *
+       * Accelerometer [m/s^2]
+       * 
+ * + * .Vector3 acc = 2; + * @return The acc. + */ + public Traj.Vector3 getAcc() { + if (accBuilder_ == null) { + return acc_ == null ? Traj.Vector3.getDefaultInstance() : acc_; + } else { + return accBuilder_.getMessage(); + } + } + /** + *
+       * Accelerometer [m/s^2]
+       * 
+ * + * .Vector3 acc = 2; + */ + public Builder setAcc(Traj.Vector3 value) { + if (accBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + acc_ = value; + onChanged(); + } else { + accBuilder_.setMessage(value); + } + + return this; + } + /** + *
+       * Accelerometer [m/s^2]
+       * 
+ * + * .Vector3 acc = 2; + */ + public Builder setAcc( + Traj.Vector3.Builder builderForValue) { + if (accBuilder_ == null) { + acc_ = builderForValue.build(); + onChanged(); + } else { + accBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + *
+       * Accelerometer [m/s^2]
+       * 
+ * + * .Vector3 acc = 2; + */ + public Builder mergeAcc(Traj.Vector3 value) { + if (accBuilder_ == null) { + if (acc_ != null) { + acc_ = + Traj.Vector3.newBuilder(acc_).mergeFrom(value).buildPartial(); + } else { + acc_ = value; + } + onChanged(); + } else { + accBuilder_.mergeFrom(value); + } + + return this; + } + /** + *
+       * Accelerometer [m/s^2]
+       * 
+ * + * .Vector3 acc = 2; + */ + public Builder clearAcc() { + if (accBuilder_ == null) { + acc_ = null; + onChanged(); + } else { + acc_ = null; + accBuilder_ = null; + } + + return this; + } + /** + *
+       * Accelerometer [m/s^2]
+       * 
+ * + * .Vector3 acc = 2; + */ + public Traj.Vector3.Builder getAccBuilder() { + + onChanged(); + return getAccFieldBuilder().getBuilder(); + } + /** + *
+       * Accelerometer [m/s^2]
+       * 
+ * + * .Vector3 acc = 2; + */ + public Traj.Vector3OrBuilder getAccOrBuilder() { + if (accBuilder_ != null) { + return accBuilder_.getMessageOrBuilder(); + } else { + return acc_ == null ? + Traj.Vector3.getDefaultInstance() : acc_; + } + } + /** + *
+       * Accelerometer [m/s^2]
+       * 
+ * + * .Vector3 acc = 2; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Traj.Vector3, Traj.Vector3.Builder, Traj.Vector3OrBuilder> + getAccFieldBuilder() { + if (accBuilder_ == null) { + accBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.Vector3, Traj.Vector3.Builder, Traj.Vector3OrBuilder>( + getAcc(), + getParentForChildren(), + isClean()); + acc_ = null; + } + return accBuilder_; + } + + private Traj.Vector3 gyr_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.Vector3, Traj.Vector3.Builder, Traj.Vector3OrBuilder> gyrBuilder_; + /** + *
+       * Gyroscope [radians/s]
+       * 
+ * + * .Vector3 gyr = 3; + * @return Whether the gyr field is set. + */ + public boolean hasGyr() { + return gyrBuilder_ != null || gyr_ != null; + } + /** + *
+       * Gyroscope [radians/s]
+       * 
+ * + * .Vector3 gyr = 3; + * @return The gyr. + */ + public Traj.Vector3 getGyr() { + if (gyrBuilder_ == null) { + return gyr_ == null ? Traj.Vector3.getDefaultInstance() : gyr_; + } else { + return gyrBuilder_.getMessage(); + } + } + /** + *
+       * Gyroscope [radians/s]
+       * 
+ * + * .Vector3 gyr = 3; + */ + public Builder setGyr(Traj.Vector3 value) { + if (gyrBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + gyr_ = value; + onChanged(); + } else { + gyrBuilder_.setMessage(value); + } + + return this; + } + /** + *
+       * Gyroscope [radians/s]
+       * 
+ * + * .Vector3 gyr = 3; + */ + public Builder setGyr( + Traj.Vector3.Builder builderForValue) { + if (gyrBuilder_ == null) { + gyr_ = builderForValue.build(); + onChanged(); + } else { + gyrBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + *
+       * Gyroscope [radians/s]
+       * 
+ * + * .Vector3 gyr = 3; + */ + public Builder mergeGyr(Traj.Vector3 value) { + if (gyrBuilder_ == null) { + if (gyr_ != null) { + gyr_ = + Traj.Vector3.newBuilder(gyr_).mergeFrom(value).buildPartial(); + } else { + gyr_ = value; + } + onChanged(); + } else { + gyrBuilder_.mergeFrom(value); + } + + return this; + } + /** + *
+       * Gyroscope [radians/s]
+       * 
+ * + * .Vector3 gyr = 3; + */ + public Builder clearGyr() { + if (gyrBuilder_ == null) { + gyr_ = null; + onChanged(); + } else { + gyr_ = null; + gyrBuilder_ = null; + } + + return this; + } + /** + *
+       * Gyroscope [radians/s]
+       * 
+ * + * .Vector3 gyr = 3; + */ + public Traj.Vector3.Builder getGyrBuilder() { + + onChanged(); + return getGyrFieldBuilder().getBuilder(); + } + /** + *
+       * Gyroscope [radians/s]
+       * 
+ * + * .Vector3 gyr = 3; + */ + public Traj.Vector3OrBuilder getGyrOrBuilder() { + if (gyrBuilder_ != null) { + return gyrBuilder_.getMessageOrBuilder(); + } else { + return gyr_ == null ? + Traj.Vector3.getDefaultInstance() : gyr_; + } + } + /** + *
+       * Gyroscope [radians/s]
+       * 
+ * + * .Vector3 gyr = 3; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Traj.Vector3, Traj.Vector3.Builder, Traj.Vector3OrBuilder> + getGyrFieldBuilder() { + if (gyrBuilder_ == null) { + gyrBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.Vector3, Traj.Vector3.Builder, Traj.Vector3OrBuilder>( + getGyr(), + getParentForChildren(), + isClean()); + gyr_ = null; + } + return gyrBuilder_; + } + + private Traj.Quaternion rotationVector_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.Quaternion, Traj.Quaternion.Builder, Traj.QuaternionOrBuilder> rotationVectorBuilder_; + /** + *
+       * Orientation [unitless], 4 components should square sum to ~1
+       * 
+ * + * .Quaternion rotation_vector = 4; + * @return Whether the rotationVector field is set. + */ + public boolean hasRotationVector() { + return rotationVectorBuilder_ != null || rotationVector_ != null; + } + /** + *
+       * Orientation [unitless], 4 components should square sum to ~1
+       * 
+ * + * .Quaternion rotation_vector = 4; + * @return The rotationVector. + */ + public Traj.Quaternion getRotationVector() { + if (rotationVectorBuilder_ == null) { + return rotationVector_ == null ? Traj.Quaternion.getDefaultInstance() : rotationVector_; + } else { + return rotationVectorBuilder_.getMessage(); + } + } + /** + *
+       * Orientation [unitless], 4 components should square sum to ~1
+       * 
+ * + * .Quaternion rotation_vector = 4; + */ + public Builder setRotationVector(Traj.Quaternion value) { + if (rotationVectorBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + rotationVector_ = value; + onChanged(); + } else { + rotationVectorBuilder_.setMessage(value); + } + + return this; + } + /** + *
+       * Orientation [unitless], 4 components should square sum to ~1
+       * 
+ * + * .Quaternion rotation_vector = 4; + */ + public Builder setRotationVector( + Traj.Quaternion.Builder builderForValue) { + if (rotationVectorBuilder_ == null) { + rotationVector_ = builderForValue.build(); + onChanged(); + } else { + rotationVectorBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + *
+       * Orientation [unitless], 4 components should square sum to ~1
+       * 
+ * + * .Quaternion rotation_vector = 4; + */ + public Builder mergeRotationVector(Traj.Quaternion value) { + if (rotationVectorBuilder_ == null) { + if (rotationVector_ != null) { + rotationVector_ = + Traj.Quaternion.newBuilder(rotationVector_).mergeFrom(value).buildPartial(); + } else { + rotationVector_ = value; + } + onChanged(); + } else { + rotationVectorBuilder_.mergeFrom(value); + } + + return this; + } + /** + *
+       * Orientation [unitless], 4 components should square sum to ~1
+       * 
+ * + * .Quaternion rotation_vector = 4; + */ + public Builder clearRotationVector() { + if (rotationVectorBuilder_ == null) { + rotationVector_ = null; + onChanged(); + } else { + rotationVector_ = null; + rotationVectorBuilder_ = null; + } + + return this; + } + /** + *
+       * Orientation [unitless], 4 components should square sum to ~1
+       * 
+ * + * .Quaternion rotation_vector = 4; + */ + public Traj.Quaternion.Builder getRotationVectorBuilder() { + + onChanged(); + return getRotationVectorFieldBuilder().getBuilder(); + } + /** + *
+       * Orientation [unitless], 4 components should square sum to ~1
+       * 
+ * + * .Quaternion rotation_vector = 4; + */ + public Traj.QuaternionOrBuilder getRotationVectorOrBuilder() { + if (rotationVectorBuilder_ != null) { + return rotationVectorBuilder_.getMessageOrBuilder(); + } else { + return rotationVector_ == null ? + Traj.Quaternion.getDefaultInstance() : rotationVector_; + } + } + /** + *
+       * Orientation [unitless], 4 components should square sum to ~1
+       * 
+ * + * .Quaternion rotation_vector = 4; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Traj.Quaternion, Traj.Quaternion.Builder, Traj.QuaternionOrBuilder> + getRotationVectorFieldBuilder() { + if (rotationVectorBuilder_ == null) { + rotationVectorBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.Quaternion, Traj.Quaternion.Builder, Traj.QuaternionOrBuilder>( + getRotationVector(), + getParentForChildren(), + isClean()); + rotationVector_ = null; + } + return rotationVectorBuilder_; + } + + private int stepCount_ ; + /** + *
+       * Number of steps so far
+       * 
+ * + * int32 step_count = 5; + * @return The stepCount. + */ + @java.lang.Override + public int getStepCount() { + return stepCount_; + } + /** + *
+       * Number of steps so far
+       * 
+ * + * int32 step_count = 5; + * @param value The stepCount to set. + * @return This builder for chaining. + */ + public Builder setStepCount(int value) { + + stepCount_ = value; + onChanged(); + return this; + } + /** + *
+       * Number of steps so far
+       * 
+ * + * int32 step_count = 5; + * @return This builder for chaining. + */ + public Builder clearStepCount() { + + stepCount_ = 0; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:IMUReading) + } + + // @@protoc_insertion_point(class_scope:IMUReading) + private static final Traj.IMUReading DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new Traj.IMUReading(); + } + + public static Traj.IMUReading getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public IMUReading parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new IMUReading(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public Traj.IMUReading getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface MagnetometerReadingOrBuilder extends + // @@protoc_insertion_point(interface_extends:MagnetometerReading) + com.google.protobuf.MessageOrBuilder { + + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + long getRelativeTimestamp(); + + /** + *
+     * Magnetometer [uT]
+     * 
+ * + * .Vector3 mag = 2; + * @return Whether the mag field is set. + */ + boolean hasMag(); + /** + *
+     * Magnetometer [uT]
+     * 
+ * + * .Vector3 mag = 2; + * @return The mag. + */ + Traj.Vector3 getMag(); + /** + *
+     * Magnetometer [uT]
+     * 
+ * + * .Vector3 mag = 2; + */ + Traj.Vector3OrBuilder getMagOrBuilder(); + } + /** + * Protobuf type {@code MagnetometerReading} + */ + public static final class MagnetometerReading extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:MagnetometerReading) + MagnetometerReadingOrBuilder { + private static final long serialVersionUID = 0L; + // Use MagnetometerReading.newBuilder() to construct. + private MagnetometerReading(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private MagnetometerReading() { + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new MagnetometerReading(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private MagnetometerReading( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + + relativeTimestamp_ = input.readInt64(); + break; + } + case 18: { + Traj.Vector3.Builder subBuilder = null; + if (mag_ != null) { + subBuilder = mag_.toBuilder(); + } + mag_ = input.readMessage(Traj.Vector3.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(mag_); + mag_ = subBuilder.buildPartial(); + } + + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return Traj.internal_static_MagnetometerReading_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_MagnetometerReading_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.MagnetometerReading.class, Traj.MagnetometerReading.Builder.class); + } + + public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; + private long relativeTimestamp_; + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + + public static final int MAG_FIELD_NUMBER = 2; + private Traj.Vector3 mag_; + /** + *
+     * Magnetometer [uT]
+     * 
+ * + * .Vector3 mag = 2; + * @return Whether the mag field is set. + */ + @java.lang.Override + public boolean hasMag() { + return mag_ != null; + } + /** + *
+     * Magnetometer [uT]
+     * 
+ * + * .Vector3 mag = 2; + * @return The mag. + */ + @java.lang.Override + public Traj.Vector3 getMag() { + return mag_ == null ? Traj.Vector3.getDefaultInstance() : mag_; + } + /** + *
+     * Magnetometer [uT]
+     * 
+ * + * .Vector3 mag = 2; + */ + @java.lang.Override + public Traj.Vector3OrBuilder getMagOrBuilder() { + return getMag(); + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (relativeTimestamp_ != 0L) { + output.writeInt64(1, relativeTimestamp_); + } + if (mag_ != null) { + output.writeMessage(2, getMag()); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (relativeTimestamp_ != 0L) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, relativeTimestamp_); + } + if (mag_ != null) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(2, getMag()); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Traj.MagnetometerReading)) { + return super.equals(obj); + } + Traj.MagnetometerReading other = (Traj.MagnetometerReading) obj; + + if (getRelativeTimestamp() + != other.getRelativeTimestamp()) return false; + if (hasMag() != other.hasMag()) return false; + if (hasMag()) { + if (!getMag() + .equals(other.getMag())) return false; + } + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getRelativeTimestamp()); + if (hasMag()) { + hash = (37 * hash) + MAG_FIELD_NUMBER; + hash = (53 * hash) + getMag().hashCode(); + } + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static Traj.MagnetometerReading parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.MagnetometerReading parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.MagnetometerReading parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.MagnetometerReading parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.MagnetometerReading parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.MagnetometerReading parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.MagnetometerReading parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Traj.MagnetometerReading parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static Traj.MagnetometerReading parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static Traj.MagnetometerReading parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static Traj.MagnetometerReading parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Traj.MagnetometerReading parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(Traj.MagnetometerReading prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code MagnetometerReading} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:MagnetometerReading) + Traj.MagnetometerReadingOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return Traj.internal_static_MagnetometerReading_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_MagnetometerReading_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.MagnetometerReading.class, Traj.MagnetometerReading.Builder.class); + } + + // Construct using Traj.MagnetometerReading.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + relativeTimestamp_ = 0L; + + if (magBuilder_ == null) { + mag_ = null; + } else { + mag_ = null; + magBuilder_ = null; + } + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return Traj.internal_static_MagnetometerReading_descriptor; + } + + @java.lang.Override + public Traj.MagnetometerReading getDefaultInstanceForType() { + return Traj.MagnetometerReading.getDefaultInstance(); + } + + @java.lang.Override + public Traj.MagnetometerReading build() { + Traj.MagnetometerReading result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public Traj.MagnetometerReading buildPartial() { + Traj.MagnetometerReading result = new Traj.MagnetometerReading(this); + result.relativeTimestamp_ = relativeTimestamp_; + if (magBuilder_ == null) { + result.mag_ = mag_; + } else { + result.mag_ = magBuilder_.build(); + } + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof Traj.MagnetometerReading) { + return mergeFrom((Traj.MagnetometerReading)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(Traj.MagnetometerReading other) { + if (other == Traj.MagnetometerReading.getDefaultInstance()) return this; + if (other.getRelativeTimestamp() != 0L) { + setRelativeTimestamp(other.getRelativeTimestamp()); + } + if (other.hasMag()) { + mergeMag(other.getMag()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Traj.MagnetometerReading parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (Traj.MagnetometerReading) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private long relativeTimestamp_ ; + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + /** + * int64 relative_timestamp = 1; + * @param value The relativeTimestamp to set. + * @return This builder for chaining. + */ + public Builder setRelativeTimestamp(long value) { + + relativeTimestamp_ = value; + onChanged(); + return this; + } + /** + * int64 relative_timestamp = 1; + * @return This builder for chaining. + */ + public Builder clearRelativeTimestamp() { + + relativeTimestamp_ = 0L; + onChanged(); + return this; + } + + private Traj.Vector3 mag_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.Vector3, Traj.Vector3.Builder, Traj.Vector3OrBuilder> magBuilder_; + /** + *
+       * Magnetometer [uT]
+       * 
+ * + * .Vector3 mag = 2; + * @return Whether the mag field is set. + */ + public boolean hasMag() { + return magBuilder_ != null || mag_ != null; + } + /** + *
+       * Magnetometer [uT]
+       * 
+ * + * .Vector3 mag = 2; + * @return The mag. + */ + public Traj.Vector3 getMag() { + if (magBuilder_ == null) { + return mag_ == null ? Traj.Vector3.getDefaultInstance() : mag_; + } else { + return magBuilder_.getMessage(); + } + } + /** + *
+       * Magnetometer [uT]
+       * 
+ * + * .Vector3 mag = 2; + */ + public Builder setMag(Traj.Vector3 value) { + if (magBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + mag_ = value; + onChanged(); + } else { + magBuilder_.setMessage(value); + } + + return this; + } + /** + *
+       * Magnetometer [uT]
+       * 
+ * + * .Vector3 mag = 2; + */ + public Builder setMag( + Traj.Vector3.Builder builderForValue) { + if (magBuilder_ == null) { + mag_ = builderForValue.build(); + onChanged(); + } else { + magBuilder_.setMessage(builderForValue.build()); + } + + return this; + } + /** + *
+       * Magnetometer [uT]
+       * 
+ * + * .Vector3 mag = 2; + */ + public Builder mergeMag(Traj.Vector3 value) { + if (magBuilder_ == null) { + if (mag_ != null) { + mag_ = + Traj.Vector3.newBuilder(mag_).mergeFrom(value).buildPartial(); + } else { + mag_ = value; + } + onChanged(); + } else { + magBuilder_.mergeFrom(value); + } + + return this; + } + /** + *
+       * Magnetometer [uT]
+       * 
+ * + * .Vector3 mag = 2; + */ + public Builder clearMag() { + if (magBuilder_ == null) { + mag_ = null; + onChanged(); + } else { + mag_ = null; + magBuilder_ = null; + } + + return this; + } + /** + *
+       * Magnetometer [uT]
+       * 
+ * + * .Vector3 mag = 2; + */ + public Traj.Vector3.Builder getMagBuilder() { + + onChanged(); + return getMagFieldBuilder().getBuilder(); + } + /** + *
+       * Magnetometer [uT]
+       * 
+ * + * .Vector3 mag = 2; + */ + public Traj.Vector3OrBuilder getMagOrBuilder() { + if (magBuilder_ != null) { + return magBuilder_.getMessageOrBuilder(); + } else { + return mag_ == null ? + Traj.Vector3.getDefaultInstance() : mag_; + } + } + /** + *
+       * Magnetometer [uT]
+       * 
+ * + * .Vector3 mag = 2; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Traj.Vector3, Traj.Vector3.Builder, Traj.Vector3OrBuilder> + getMagFieldBuilder() { + if (magBuilder_ == null) { + magBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.Vector3, Traj.Vector3.Builder, Traj.Vector3OrBuilder>( + getMag(), + getParentForChildren(), + isClean()); + mag_ = null; + } + return magBuilder_; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:MagnetometerReading) + } + + // @@protoc_insertion_point(class_scope:MagnetometerReading) + private static final Traj.MagnetometerReading DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new Traj.MagnetometerReading(); + } + + public static Traj.MagnetometerReading getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public MagnetometerReading parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new MagnetometerReading(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public Traj.MagnetometerReading getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface BarometerReadingOrBuilder extends + // @@protoc_insertion_point(interface_extends:BarometerReading) + com.google.protobuf.MessageOrBuilder { + + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + long getRelativeTimestamp(); + + /** + *
+     * mbar
+     * 
+ * + * float pressure = 2; + * @return The pressure. + */ + float getPressure(); + } + /** + * Protobuf type {@code BarometerReading} + */ + public static final class BarometerReading extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:BarometerReading) + BarometerReadingOrBuilder { + private static final long serialVersionUID = 0L; + // Use BarometerReading.newBuilder() to construct. + private BarometerReading(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private BarometerReading() { + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new BarometerReading(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private BarometerReading( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + + relativeTimestamp_ = input.readInt64(); + break; + } + case 21: { + + pressure_ = input.readFloat(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return Traj.internal_static_BarometerReading_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_BarometerReading_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.BarometerReading.class, Traj.BarometerReading.Builder.class); + } + + public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; + private long relativeTimestamp_; + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + + public static final int PRESSURE_FIELD_NUMBER = 2; + private float pressure_; + /** + *
+     * mbar
+     * 
+ * + * float pressure = 2; + * @return The pressure. + */ + @java.lang.Override + public float getPressure() { + return pressure_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (relativeTimestamp_ != 0L) { + output.writeInt64(1, relativeTimestamp_); + } + if (java.lang.Float.floatToRawIntBits(pressure_) != 0) { + output.writeFloat(2, pressure_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (relativeTimestamp_ != 0L) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, relativeTimestamp_); + } + if (java.lang.Float.floatToRawIntBits(pressure_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeFloatSize(2, pressure_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Traj.BarometerReading)) { + return super.equals(obj); + } + Traj.BarometerReading other = (Traj.BarometerReading) obj; + + if (getRelativeTimestamp() + != other.getRelativeTimestamp()) return false; + if (java.lang.Float.floatToIntBits(getPressure()) + != java.lang.Float.floatToIntBits( + other.getPressure())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getRelativeTimestamp()); + hash = (37 * hash) + PRESSURE_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getPressure()); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static Traj.BarometerReading parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.BarometerReading parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.BarometerReading parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.BarometerReading parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.BarometerReading parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.BarometerReading parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.BarometerReading parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Traj.BarometerReading parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static Traj.BarometerReading parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static Traj.BarometerReading parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static Traj.BarometerReading parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Traj.BarometerReading parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(Traj.BarometerReading prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code BarometerReading} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:BarometerReading) + Traj.BarometerReadingOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return Traj.internal_static_BarometerReading_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_BarometerReading_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.BarometerReading.class, Traj.BarometerReading.Builder.class); + } + + // Construct using Traj.BarometerReading.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + relativeTimestamp_ = 0L; + + pressure_ = 0F; + + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return Traj.internal_static_BarometerReading_descriptor; + } + + @java.lang.Override + public Traj.BarometerReading getDefaultInstanceForType() { + return Traj.BarometerReading.getDefaultInstance(); + } + + @java.lang.Override + public Traj.BarometerReading build() { + Traj.BarometerReading result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public Traj.BarometerReading buildPartial() { + Traj.BarometerReading result = new Traj.BarometerReading(this); + result.relativeTimestamp_ = relativeTimestamp_; + result.pressure_ = pressure_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof Traj.BarometerReading) { + return mergeFrom((Traj.BarometerReading)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(Traj.BarometerReading other) { + if (other == Traj.BarometerReading.getDefaultInstance()) return this; + if (other.getRelativeTimestamp() != 0L) { + setRelativeTimestamp(other.getRelativeTimestamp()); + } + if (other.getPressure() != 0F) { + setPressure(other.getPressure()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Traj.BarometerReading parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (Traj.BarometerReading) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private long relativeTimestamp_ ; + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + /** + * int64 relative_timestamp = 1; + * @param value The relativeTimestamp to set. + * @return This builder for chaining. + */ + public Builder setRelativeTimestamp(long value) { + + relativeTimestamp_ = value; + onChanged(); + return this; + } + /** + * int64 relative_timestamp = 1; + * @return This builder for chaining. + */ + public Builder clearRelativeTimestamp() { + + relativeTimestamp_ = 0L; + onChanged(); + return this; + } + + private float pressure_ ; + /** + *
+       * mbar
+       * 
+ * + * float pressure = 2; + * @return The pressure. + */ + @java.lang.Override + public float getPressure() { + return pressure_; + } + /** + *
+       * mbar
+       * 
+ * + * float pressure = 2; + * @param value The pressure to set. + * @return This builder for chaining. + */ + public Builder setPressure(float value) { + + pressure_ = value; + onChanged(); + return this; + } + /** + *
+       * mbar
+       * 
+ * + * float pressure = 2; + * @return This builder for chaining. + */ + public Builder clearPressure() { + + pressure_ = 0F; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:BarometerReading) + } + + // @@protoc_insertion_point(class_scope:BarometerReading) + private static final Traj.BarometerReading DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new Traj.BarometerReading(); + } + + public static Traj.BarometerReading getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public BarometerReading parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new BarometerReading(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public Traj.BarometerReading getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface LightReadingOrBuilder extends + // @@protoc_insertion_point(interface_extends:LightReading) + com.google.protobuf.MessageOrBuilder { + + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + long getRelativeTimestamp(); + + /** + *
+     * lux
+     * 
+ * + * float light = 2; + * @return The light. + */ + float getLight(); + } + /** + * Protobuf type {@code LightReading} + */ + public static final class LightReading extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:LightReading) + LightReadingOrBuilder { + private static final long serialVersionUID = 0L; + // Use LightReading.newBuilder() to construct. + private LightReading(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private LightReading() { + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new LightReading(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private LightReading( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + + relativeTimestamp_ = input.readInt64(); + break; + } + case 21: { + + light_ = input.readFloat(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return Traj.internal_static_LightReading_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_LightReading_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.LightReading.class, Traj.LightReading.Builder.class); + } + + public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; + private long relativeTimestamp_; + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + + public static final int LIGHT_FIELD_NUMBER = 2; + private float light_; + /** + *
+     * lux
+     * 
+ * + * float light = 2; + * @return The light. + */ + @java.lang.Override + public float getLight() { + return light_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (relativeTimestamp_ != 0L) { + output.writeInt64(1, relativeTimestamp_); + } + if (java.lang.Float.floatToRawIntBits(light_) != 0) { + output.writeFloat(2, light_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (relativeTimestamp_ != 0L) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, relativeTimestamp_); + } + if (java.lang.Float.floatToRawIntBits(light_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeFloatSize(2, light_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Traj.LightReading)) { + return super.equals(obj); + } + Traj.LightReading other = (Traj.LightReading) obj; + + if (getRelativeTimestamp() + != other.getRelativeTimestamp()) return false; + if (java.lang.Float.floatToIntBits(getLight()) + != java.lang.Float.floatToIntBits( + other.getLight())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getRelativeTimestamp()); + hash = (37 * hash) + LIGHT_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getLight()); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static Traj.LightReading parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.LightReading parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.LightReading parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.LightReading parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.LightReading parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.LightReading parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.LightReading parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Traj.LightReading parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static Traj.LightReading parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static Traj.LightReading parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static Traj.LightReading parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Traj.LightReading parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(Traj.LightReading prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code LightReading} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:LightReading) + Traj.LightReadingOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return Traj.internal_static_LightReading_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_LightReading_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.LightReading.class, Traj.LightReading.Builder.class); + } + + // Construct using Traj.LightReading.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + relativeTimestamp_ = 0L; + + light_ = 0F; + + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return Traj.internal_static_LightReading_descriptor; + } + + @java.lang.Override + public Traj.LightReading getDefaultInstanceForType() { + return Traj.LightReading.getDefaultInstance(); + } + + @java.lang.Override + public Traj.LightReading build() { + Traj.LightReading result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public Traj.LightReading buildPartial() { + Traj.LightReading result = new Traj.LightReading(this); + result.relativeTimestamp_ = relativeTimestamp_; + result.light_ = light_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof Traj.LightReading) { + return mergeFrom((Traj.LightReading)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(Traj.LightReading other) { + if (other == Traj.LightReading.getDefaultInstance()) return this; + if (other.getRelativeTimestamp() != 0L) { + setRelativeTimestamp(other.getRelativeTimestamp()); + } + if (other.getLight() != 0F) { + setLight(other.getLight()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Traj.LightReading parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (Traj.LightReading) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private long relativeTimestamp_ ; + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + /** + * int64 relative_timestamp = 1; + * @param value The relativeTimestamp to set. + * @return This builder for chaining. + */ + public Builder setRelativeTimestamp(long value) { + + relativeTimestamp_ = value; + onChanged(); + return this; + } + /** + * int64 relative_timestamp = 1; + * @return This builder for chaining. + */ + public Builder clearRelativeTimestamp() { + + relativeTimestamp_ = 0L; + onChanged(); + return this; + } + + private float light_ ; + /** + *
+       * lux
+       * 
+ * + * float light = 2; + * @return The light. + */ + @java.lang.Override + public float getLight() { + return light_; + } + /** + *
+       * lux
+       * 
+ * + * float light = 2; + * @param value The light to set. + * @return This builder for chaining. + */ + public Builder setLight(float value) { + + light_ = value; + onChanged(); + return this; + } + /** + *
+       * lux
+       * 
+ * + * float light = 2; + * @return This builder for chaining. + */ + public Builder clearLight() { + + light_ = 0F; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:LightReading) + } + + // @@protoc_insertion_point(class_scope:LightReading) + private static final Traj.LightReading DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new Traj.LightReading(); + } + + public static Traj.LightReading getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public LightReading parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new LightReading(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public Traj.LightReading getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface ProximityReadingOrBuilder extends + // @@protoc_insertion_point(interface_extends:ProximityReading) + com.google.protobuf.MessageOrBuilder { + + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + long getRelativeTimestamp(); + + /** + *
+     * cm
+     * 
+ * + * float distance = 2; + * @return The distance. + */ + float getDistance(); + } + /** + * Protobuf type {@code ProximityReading} + */ + public static final class ProximityReading extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:ProximityReading) + ProximityReadingOrBuilder { + private static final long serialVersionUID = 0L; + // Use ProximityReading.newBuilder() to construct. + private ProximityReading(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private ProximityReading() { + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new ProximityReading(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private ProximityReading( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + + relativeTimestamp_ = input.readInt64(); + break; + } + case 21: { + + distance_ = input.readFloat(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return Traj.internal_static_ProximityReading_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_ProximityReading_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.ProximityReading.class, Traj.ProximityReading.Builder.class); + } + + public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; + private long relativeTimestamp_; + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + + public static final int DISTANCE_FIELD_NUMBER = 2; + private float distance_; + /** + *
+     * cm
+     * 
+ * + * float distance = 2; + * @return The distance. + */ + @java.lang.Override + public float getDistance() { + return distance_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (relativeTimestamp_ != 0L) { + output.writeInt64(1, relativeTimestamp_); + } + if (java.lang.Float.floatToRawIntBits(distance_) != 0) { + output.writeFloat(2, distance_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (relativeTimestamp_ != 0L) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(1, relativeTimestamp_); + } + if (java.lang.Float.floatToRawIntBits(distance_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeFloatSize(2, distance_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Traj.ProximityReading)) { + return super.equals(obj); + } + Traj.ProximityReading other = (Traj.ProximityReading) obj; + + if (getRelativeTimestamp() + != other.getRelativeTimestamp()) return false; + if (java.lang.Float.floatToIntBits(getDistance()) + != java.lang.Float.floatToIntBits( + other.getDistance())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getRelativeTimestamp()); + hash = (37 * hash) + DISTANCE_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getDistance()); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static Traj.ProximityReading parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.ProximityReading parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.ProximityReading parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.ProximityReading parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.ProximityReading parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.ProximityReading parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.ProximityReading parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Traj.ProximityReading parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static Traj.ProximityReading parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static Traj.ProximityReading parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static Traj.ProximityReading parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static Traj.ProximityReading parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(Traj.ProximityReading prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code ProximityReading} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:ProximityReading) + Traj.ProximityReadingOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return Traj.internal_static_ProximityReading_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_ProximityReading_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.ProximityReading.class, Traj.ProximityReading.Builder.class); + } + + // Construct using Traj.ProximityReading.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + relativeTimestamp_ = 0L; + + distance_ = 0F; + + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return Traj.internal_static_ProximityReading_descriptor; + } + + @java.lang.Override + public Traj.ProximityReading getDefaultInstanceForType() { + return Traj.ProximityReading.getDefaultInstance(); + } + + @java.lang.Override + public Traj.ProximityReading build() { + Traj.ProximityReading result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public Traj.ProximityReading buildPartial() { + Traj.ProximityReading result = new Traj.ProximityReading(this); + result.relativeTimestamp_ = relativeTimestamp_; + result.distance_ = distance_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof Traj.ProximityReading) { + return mergeFrom((Traj.ProximityReading)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(Traj.ProximityReading other) { + if (other == Traj.ProximityReading.getDefaultInstance()) return this; + if (other.getRelativeTimestamp() != 0L) { + setRelativeTimestamp(other.getRelativeTimestamp()); + } + if (other.getDistance() != 0F) { + setDistance(other.getDistance()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Traj.ProximityReading parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (Traj.ProximityReading) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private long relativeTimestamp_ ; + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + /** + * int64 relative_timestamp = 1; + * @param value The relativeTimestamp to set. + * @return This builder for chaining. + */ + public Builder setRelativeTimestamp(long value) { + + relativeTimestamp_ = value; + onChanged(); + return this; + } + /** + * int64 relative_timestamp = 1; + * @return This builder for chaining. + */ + public Builder clearRelativeTimestamp() { + + relativeTimestamp_ = 0L; + onChanged(); + return this; + } + + private float distance_ ; + /** + *
+       * cm
+       * 
+ * + * float distance = 2; + * @return The distance. + */ + @java.lang.Override + public float getDistance() { + return distance_; + } + /** + *
+       * cm
+       * 
+ * + * float distance = 2; + * @param value The distance to set. + * @return This builder for chaining. + */ + public Builder setDistance(float value) { + + distance_ = value; + onChanged(); + return this; + } + /** + *
+       * cm
+       * 
+ * + * float distance = 2; + * @return This builder for chaining. + */ + public Builder clearDistance() { + + distance_ = 0F; + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:ProximityReading) } - // @@protoc_insertion_point(class_scope:Trajectory) - private static final Trajectory DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:ProximityReading) + private static final Traj.ProximityReading DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new Trajectory(); + DEFAULT_INSTANCE = new Traj.ProximityReading(); } - public static Trajectory getDefaultInstance() { + public static Traj.ProximityReading getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - public Trajectory parsePartialFrom( + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ProximityReading parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { - return new Trajectory(input, extensionRegistry); + return new ProximityReading(input, extensionRegistry); } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } - @Override - public com.google.protobuf.Parser getParserForType() { + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { return PARSER; } - public Trajectory getDefaultInstanceForType() { + @java.lang.Override + public Traj.ProximityReading getDefaultInstanceForType() { return DEFAULT_INSTANCE; } } - public interface Pdr_SampleOrBuilder extends - // @@protoc_insertion_point(interface_extends:Pdr_Sample) + public interface GNSSPositionOrBuilder extends + // @@protoc_insertion_point(interface_extends:GNSSPosition) com.google.protobuf.MessageOrBuilder { + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + long getRelativeTimestamp(); + /** *
-     * milliseconds from the start_timestamp
+     * degrees (minimum 6 significant figures)
+     * latitude between -90 and 90
      * 
* - * optional int64 relative_timestamp = 1; + * double latitude = 2; + * @return The latitude. */ - long getRelativeTimestamp(); + double getLatitude(); /** *
-     * Both in metres. You should implement an algorithm to estimate
-     * these values. The values are always relative to your start point
-     * so the first entry should always be x = 0.0, y = 0.0
+     * longitude between -180 and 180
      * 
* - * optional float x = 2; + * double longitude = 3; + * @return The longitude. */ - float getX(); + double getLongitude(); /** - * optional float y = 3; + *
+     *metres
+     * 
+ * + * double altitude = 4; + * @return The altitude. */ - float getY(); + double getAltitude(); + + /** + *
+     * floor name
+     * 
+ * + * optional string floor = 5; + * @return Whether the floor field is set. + */ + boolean hasFloor(); + /** + *
+     * floor name
+     * 
+ * + * optional string floor = 5; + * @return The floor. + */ + java.lang.String getFloor(); + /** + *
+     * floor name
+     * 
+ * + * optional string floor = 5; + * @return The bytes for floor. + */ + com.google.protobuf.ByteString + getFloorBytes(); } /** - * Protobuf type {@code Pdr_Sample} + * Protobuf type {@code GNSSPosition} */ - public static final class Pdr_Sample extends + public static final class GNSSPosition extends com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:Pdr_Sample) - Pdr_SampleOrBuilder { - // Use Pdr_Sample.newBuilder() to construct. - private Pdr_Sample(com.google.protobuf.GeneratedMessageV3.Builder builder) { + // @@protoc_insertion_point(message_implements:GNSSPosition) + GNSSPositionOrBuilder { + private static final long serialVersionUID = 0L; + // Use GNSSPosition.newBuilder() to construct. + private GNSSPosition(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } - private Pdr_Sample() { - relativeTimestamp_ = 0L; - x_ = 0F; - y_ = 0F; + private GNSSPosition() { + floor_ = ""; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new GNSSPosition(); } - @Override + @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + return this.unknownFields; } - private Pdr_Sample( + private GNSSPosition( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { @@ -4936,88 +12511,184 @@ private Pdr_Sample( case 0: done = true; break; - default: { - if (!input.skipField(tag)) { - done = true; - } - break; - } case 8: { relativeTimestamp_ = input.readInt64(); break; } - case 21: { + case 17: { - x_ = input.readFloat(); + latitude_ = input.readDouble(); break; } - case 29: { + case 25: { - y_ = input.readFloat(); + longitude_ = input.readDouble(); + break; + } + case 33: { + + altitude_ = input.readDouble(); + break; + } + case 42: { + java.lang.String s = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + floor_ = s; + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { + this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Pdr_Sample_descriptor; + return Traj.internal_static_GNSSPosition_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Pdr_Sample_fieldAccessorTable + return Traj.internal_static_GNSSPosition_fieldAccessorTable .ensureFieldAccessorsInitialized( - Pdr_Sample.class, Builder.class); + Traj.GNSSPosition.class, Traj.GNSSPosition.Builder.class); } + private int bitField0_; public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; private long relativeTimestamp_; + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + + public static final int LATITUDE_FIELD_NUMBER = 2; + private double latitude_; /** *
-     * milliseconds from the start_timestamp
+     * degrees (minimum 6 significant figures)
+     * latitude between -90 and 90
      * 
* - * optional int64 relative_timestamp = 1; + * double latitude = 2; + * @return The latitude. */ - public long getRelativeTimestamp() { - return relativeTimestamp_; + @java.lang.Override + public double getLatitude() { + return latitude_; } - public static final int X_FIELD_NUMBER = 2; - private float x_; + public static final int LONGITUDE_FIELD_NUMBER = 3; + private double longitude_; /** *
-     * Both in metres. You should implement an algorithm to estimate
-     * these values. The values are always relative to your start point
-     * so the first entry should always be x = 0.0, y = 0.0
+     * longitude between -180 and 180
      * 
* - * optional float x = 2; + * double longitude = 3; + * @return The longitude. */ - public float getX() { - return x_; + @java.lang.Override + public double getLongitude() { + return longitude_; } - public static final int Y_FIELD_NUMBER = 3; - private float y_; + public static final int ALTITUDE_FIELD_NUMBER = 4; + private double altitude_; /** - * optional float y = 3; + *
+     *metres
+     * 
+ * + * double altitude = 4; + * @return The altitude. */ - public float getY() { - return y_; + @java.lang.Override + public double getAltitude() { + return altitude_; + } + + public static final int FLOOR_FIELD_NUMBER = 5; + private volatile java.lang.Object floor_; + /** + *
+     * floor name
+     * 
+ * + * optional string floor = 5; + * @return Whether the floor field is set. + */ + @java.lang.Override + public boolean hasFloor() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
+     * floor name
+     * 
+ * + * optional string floor = 5; + * @return The floor. + */ + @java.lang.Override + public java.lang.String getFloor() { + java.lang.Object ref = floor_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + floor_ = s; + return s; + } + } + /** + *
+     * floor name
+     * 
+ * + * optional string floor = 5; + * @return The bytes for floor. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getFloorBytes() { + java.lang.Object ref = floor_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + floor_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; @@ -5027,19 +12698,28 @@ public final boolean isInitialized() { return true; } + @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (relativeTimestamp_ != 0L) { output.writeInt64(1, relativeTimestamp_); } - if (x_ != 0F) { - output.writeFloat(2, x_); + if (java.lang.Double.doubleToRawLongBits(latitude_) != 0) { + output.writeDouble(2, latitude_); } - if (y_ != 0F) { - output.writeFloat(3, y_); + if (java.lang.Double.doubleToRawLongBits(longitude_) != 0) { + output.writeDouble(3, longitude_); + } + if (java.lang.Double.doubleToRawLongBits(altitude_) != 0) { + output.writeDouble(4, altitude_); } + if (((bitField0_ & 0x00000001) != 0)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 5, floor_); + } + unknownFields.writeTo(output); } + @java.lang.Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; @@ -5049,116 +12729,147 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeInt64Size(1, relativeTimestamp_); } - if (x_ != 0F) { + if (java.lang.Double.doubleToRawLongBits(latitude_) != 0) { size += com.google.protobuf.CodedOutputStream - .computeFloatSize(2, x_); + .computeDoubleSize(2, latitude_); } - if (y_ != 0F) { + if (java.lang.Double.doubleToRawLongBits(longitude_) != 0) { size += com.google.protobuf.CodedOutputStream - .computeFloatSize(3, y_); + .computeDoubleSize(3, longitude_); + } + if (java.lang.Double.doubleToRawLongBits(altitude_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeDoubleSize(4, altitude_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(5, floor_); } + size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } - private static final long serialVersionUID = 0L; - @Override - public boolean equals(final Object obj) { + @java.lang.Override + public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof Pdr_Sample)) { + if (!(obj instanceof Traj.GNSSPosition)) { return super.equals(obj); } - Pdr_Sample other = (Pdr_Sample) obj; - - boolean result = true; - result = result && (getRelativeTimestamp() - == other.getRelativeTimestamp()); - result = result && ( - Float.floatToIntBits(getX()) - == Float.floatToIntBits( - other.getX())); - result = result && ( - Float.floatToIntBits(getY()) - == Float.floatToIntBits( - other.getY())); - return result; + Traj.GNSSPosition other = (Traj.GNSSPosition) obj; + + if (getRelativeTimestamp() + != other.getRelativeTimestamp()) return false; + if (java.lang.Double.doubleToLongBits(getLatitude()) + != java.lang.Double.doubleToLongBits( + other.getLatitude())) return false; + if (java.lang.Double.doubleToLongBits(getLongitude()) + != java.lang.Double.doubleToLongBits( + other.getLongitude())) return false; + if (java.lang.Double.doubleToLongBits(getAltitude()) + != java.lang.Double.doubleToLongBits( + other.getAltitude())) return false; + if (hasFloor() != other.hasFloor()) return false; + if (hasFloor()) { + if (!getFloor() + .equals(other.getFloor())) return false; + } + if (!unknownFields.equals(other.unknownFields)) return false; + return true; } - @Override + @java.lang.Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; - hash = (19 * hash) + getDescriptorForType().hashCode(); + hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; hash = (53 * hash) + com.google.protobuf.Internal.hashLong( getRelativeTimestamp()); - hash = (37 * hash) + X_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getX()); - hash = (37 * hash) + Y_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getY()); + hash = (37 * hash) + LATITUDE_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + java.lang.Double.doubleToLongBits(getLatitude())); + hash = (37 * hash) + LONGITUDE_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + java.lang.Double.doubleToLongBits(getLongitude())); + hash = (37 * hash) + ALTITUDE_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + java.lang.Double.doubleToLongBits(getAltitude())); + if (hasFloor()) { + hash = (37 * hash) + FLOOR_FIELD_NUMBER; + hash = (53 * hash) + getFloor().hashCode(); + } hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } - public static Pdr_Sample parseFrom( + public static Traj.GNSSPosition parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.GNSSPosition parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.GNSSPosition parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Pdr_Sample parseFrom( + public static Traj.GNSSPosition parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Pdr_Sample parseFrom(byte[] data) + public static Traj.GNSSPosition parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Pdr_Sample parseFrom( + public static Traj.GNSSPosition parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Pdr_Sample parseFrom(java.io.InputStream input) + public static Traj.GNSSPosition parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Pdr_Sample parseFrom( + public static Traj.GNSSPosition parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static Pdr_Sample parseDelimitedFrom(java.io.InputStream input) + public static Traj.GNSSPosition parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static Pdr_Sample parseDelimitedFrom( + public static Traj.GNSSPosition parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static Pdr_Sample parseFrom( + public static Traj.GNSSPosition parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Pdr_Sample parseFrom( + public static Traj.GNSSPosition parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -5166,44 +12877,47 @@ public static Pdr_Sample parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } + @java.lang.Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(Pdr_Sample prototype) { + public static Builder newBuilder(Traj.GNSSPosition prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } - @Override + @java.lang.Override protected Builder newBuilderForType( com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** - * Protobuf type {@code Pdr_Sample} + * Protobuf type {@code GNSSPosition} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:Pdr_Sample) - Pdr_SampleOrBuilder { + // @@protoc_insertion_point(builder_implements:GNSSPosition) + Traj.GNSSPositionOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Pdr_Sample_descriptor; + return Traj.internal_static_GNSSPosition_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Pdr_Sample_fieldAccessorTable + return Traj.internal_static_GNSSPosition_fieldAccessorTable .ensureFieldAccessorsInitialized( - Pdr_Sample.class, Builder.class); + Traj.GNSSPosition.class, Traj.GNSSPosition.Builder.class); } - // Construct using Traj.Pdr_Sample.newBuilder() + // Construct using Traj.GNSSPosition.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -5218,106 +12932,141 @@ private void maybeForceBuilderInitialization() { .alwaysUseFieldBuilders) { } } + @java.lang.Override public Builder clear() { super.clear(); relativeTimestamp_ = 0L; - x_ = 0F; + latitude_ = 0D; - y_ = 0F; + longitude_ = 0D; + altitude_ = 0D; + + floor_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); return this; } + @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return Traj.internal_static_Pdr_Sample_descriptor; + return Traj.internal_static_GNSSPosition_descriptor; } - public Pdr_Sample getDefaultInstanceForType() { - return Pdr_Sample.getDefaultInstance(); + @java.lang.Override + public Traj.GNSSPosition getDefaultInstanceForType() { + return Traj.GNSSPosition.getDefaultInstance(); } - public Pdr_Sample build() { - Pdr_Sample result = buildPartial(); + @java.lang.Override + public Traj.GNSSPosition build() { + Traj.GNSSPosition result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } - public Pdr_Sample buildPartial() { - Pdr_Sample result = new Pdr_Sample(this); + @java.lang.Override + public Traj.GNSSPosition buildPartial() { + Traj.GNSSPosition result = new Traj.GNSSPosition(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; result.relativeTimestamp_ = relativeTimestamp_; - result.x_ = x_; - result.y_ = y_; + result.latitude_ = latitude_; + result.longitude_ = longitude_; + result.altitude_ = altitude_; + if (((from_bitField0_ & 0x00000001) != 0)) { + to_bitField0_ |= 0x00000001; + } + result.floor_ = floor_; + result.bitField0_ = to_bitField0_; onBuilt(); return result; } + @java.lang.Override public Builder clone() { - return (Builder) super.clone(); + return super.clone(); } + @java.lang.Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); + java.lang.Object value) { + return super.setField(field, value); } + @java.lang.Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); + return super.clearField(field); } + @java.lang.Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); + return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); + java.lang.Object value) { + return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof Pdr_Sample) { - return mergeFrom((Pdr_Sample)other); + if (other instanceof Traj.GNSSPosition) { + return mergeFrom((Traj.GNSSPosition)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(Pdr_Sample other) { - if (other == Pdr_Sample.getDefaultInstance()) return this; + public Builder mergeFrom(Traj.GNSSPosition other) { + if (other == Traj.GNSSPosition.getDefaultInstance()) return this; if (other.getRelativeTimestamp() != 0L) { setRelativeTimestamp(other.getRelativeTimestamp()); } - if (other.getX() != 0F) { - setX(other.getX()); + if (other.getLatitude() != 0D) { + setLatitude(other.getLatitude()); } - if (other.getY() != 0F) { - setY(other.getY()); + if (other.getLongitude() != 0D) { + setLongitude(other.getLongitude()); } + if (other.getAltitude() != 0D) { + setAltitude(other.getAltitude()); + } + if (other.hasFloor()) { + bitField0_ |= 0x00000001; + floor_ = other.floor_; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); onChanged(); return this; } + @java.lang.Override public final boolean isInitialized() { return true; } + @java.lang.Override public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - Pdr_Sample parsedMessage = null; + Traj.GNSSPosition parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (Pdr_Sample) e.getUnfinishedMessage(); + parsedMessage = (Traj.GNSSPosition) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -5326,284 +13075,437 @@ public Builder mergeFrom( } return this; } + private int bitField0_; + + private long relativeTimestamp_ ; + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + /** + * int64 relative_timestamp = 1; + * @param value The relativeTimestamp to set. + * @return This builder for chaining. + */ + public Builder setRelativeTimestamp(long value) { + + relativeTimestamp_ = value; + onChanged(); + return this; + } + /** + * int64 relative_timestamp = 1; + * @return This builder for chaining. + */ + public Builder clearRelativeTimestamp() { + + relativeTimestamp_ = 0L; + onChanged(); + return this; + } + + private double latitude_ ; + /** + *
+       * degrees (minimum 6 significant figures)
+       * latitude between -90 and 90
+       * 
+ * + * double latitude = 2; + * @return The latitude. + */ + @java.lang.Override + public double getLatitude() { + return latitude_; + } + /** + *
+       * degrees (minimum 6 significant figures)
+       * latitude between -90 and 90
+       * 
+ * + * double latitude = 2; + * @param value The latitude to set. + * @return This builder for chaining. + */ + public Builder setLatitude(double value) { + + latitude_ = value; + onChanged(); + return this; + } + /** + *
+       * degrees (minimum 6 significant figures)
+       * latitude between -90 and 90
+       * 
+ * + * double latitude = 2; + * @return This builder for chaining. + */ + public Builder clearLatitude() { + + latitude_ = 0D; + onChanged(); + return this; + } + + private double longitude_ ; + /** + *
+       * longitude between -180 and 180
+       * 
+ * + * double longitude = 3; + * @return The longitude. + */ + @java.lang.Override + public double getLongitude() { + return longitude_; + } + /** + *
+       * longitude between -180 and 180
+       * 
+ * + * double longitude = 3; + * @param value The longitude to set. + * @return This builder for chaining. + */ + public Builder setLongitude(double value) { + + longitude_ = value; + onChanged(); + return this; + } + /** + *
+       * longitude between -180 and 180
+       * 
+ * + * double longitude = 3; + * @return This builder for chaining. + */ + public Builder clearLongitude() { + + longitude_ = 0D; + onChanged(); + return this; + } - private long relativeTimestamp_ ; + private double altitude_ ; /** *
-       * milliseconds from the start_timestamp
+       *metres
        * 
* - * optional int64 relative_timestamp = 1; + * double altitude = 4; + * @return The altitude. */ - public long getRelativeTimestamp() { - return relativeTimestamp_; + @java.lang.Override + public double getAltitude() { + return altitude_; } /** *
-       * milliseconds from the start_timestamp
+       *metres
        * 
* - * optional int64 relative_timestamp = 1; + * double altitude = 4; + * @param value The altitude to set. + * @return This builder for chaining. */ - public Builder setRelativeTimestamp(long value) { + public Builder setAltitude(double value) { - relativeTimestamp_ = value; + altitude_ = value; onChanged(); return this; } /** *
-       * milliseconds from the start_timestamp
+       *metres
        * 
* - * optional int64 relative_timestamp = 1; + * double altitude = 4; + * @return This builder for chaining. */ - public Builder clearRelativeTimestamp() { + public Builder clearAltitude() { - relativeTimestamp_ = 0L; + altitude_ = 0D; onChanged(); return this; } - private float x_ ; + private java.lang.Object floor_ = ""; /** *
-       * Both in metres. You should implement an algorithm to estimate
-       * these values. The values are always relative to your start point
-       * so the first entry should always be x = 0.0, y = 0.0
+       * floor name
        * 
* - * optional float x = 2; + * optional string floor = 5; + * @return Whether the floor field is set. */ - public float getX() { - return x_; + public boolean hasFloor() { + return ((bitField0_ & 0x00000001) != 0); } /** *
-       * Both in metres. You should implement an algorithm to estimate
-       * these values. The values are always relative to your start point
-       * so the first entry should always be x = 0.0, y = 0.0
+       * floor name
        * 
* - * optional float x = 2; + * optional string floor = 5; + * @return The floor. */ - public Builder setX(float value) { - - x_ = value; - onChanged(); - return this; + public java.lang.String getFloor() { + java.lang.Object ref = floor_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + floor_ = s; + return s; + } else { + return (java.lang.String) ref; + } } /** *
-       * Both in metres. You should implement an algorithm to estimate
-       * these values. The values are always relative to your start point
-       * so the first entry should always be x = 0.0, y = 0.0
+       * floor name
        * 
* - * optional float x = 2; + * optional string floor = 5; + * @return The bytes for floor. */ - public Builder clearX() { - - x_ = 0F; - onChanged(); - return this; + public com.google.protobuf.ByteString + getFloorBytes() { + java.lang.Object ref = floor_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + floor_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } } - - private float y_ ; /** - * optional float y = 3; + *
+       * floor name
+       * 
+ * + * optional string floor = 5; + * @param value The floor to set. + * @return This builder for chaining. */ - public float getY() { - return y_; + public Builder setFloor( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + floor_ = value; + onChanged(); + return this; } /** - * optional float y = 3; + *
+       * floor name
+       * 
+ * + * optional string floor = 5; + * @return This builder for chaining. */ - public Builder setY(float value) { - - y_ = value; + public Builder clearFloor() { + bitField0_ = (bitField0_ & ~0x00000001); + floor_ = getDefaultInstance().getFloor(); onChanged(); return this; } /** - * optional float y = 3; + *
+       * floor name
+       * 
+ * + * optional string floor = 5; + * @param value The bytes for floor to set. + * @return This builder for chaining. */ - public Builder clearY() { - - y_ = 0F; + public Builder setFloorBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + bitField0_ |= 0x00000001; + floor_ = value; onChanged(); return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.setUnknownFields(unknownFields); } + @java.lang.Override public final Builder mergeUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:Pdr_Sample) + // @@protoc_insertion_point(builder_scope:GNSSPosition) } - // @@protoc_insertion_point(class_scope:Pdr_Sample) - private static final Pdr_Sample DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:GNSSPosition) + private static final Traj.GNSSPosition DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new Pdr_Sample(); + DEFAULT_INSTANCE = new Traj.GNSSPosition(); } - public static Pdr_Sample getDefaultInstance() { + public static Traj.GNSSPosition getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - public Pdr_Sample parsePartialFrom( + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public GNSSPosition parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { - return new Pdr_Sample(input, extensionRegistry); + return new GNSSPosition(input, extensionRegistry); } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } - @Override - public com.google.protobuf.Parser getParserForType() { + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { return PARSER; } - public Pdr_Sample getDefaultInstanceForType() { + @java.lang.Override + public Traj.GNSSPosition getDefaultInstanceForType() { return DEFAULT_INSTANCE; } } - public interface Motion_SampleOrBuilder extends - // @@protoc_insertion_point(interface_extends:Motion_Sample) + public interface GNSSReadingOrBuilder extends + // @@protoc_insertion_point(interface_extends:GNSSReading) com.google.protobuf.MessageOrBuilder { /** - *
-     * milliseconds
-     * 
- * - * optional int64 relative_timestamp = 1; - */ - long getRelativeTimestamp(); - - /** - *
-     * m/s^2
-     * 
- * - * optional float acc_x = 2; + * .GNSSPosition position = 1; + * @return Whether the position field is set. */ - float getAccX(); - + boolean hasPosition(); /** - * optional float acc_y = 3; + * .GNSSPosition position = 1; + * @return The position. */ - float getAccY(); - + Traj.GNSSPosition getPosition(); /** - * optional float acc_z = 4; + * .GNSSPosition position = 1; */ - float getAccZ(); + Traj.GNSSPositionOrBuilder getPositionOrBuilder(); /** *
-     * radians/s
+     * metres
      * 
* - * optional float gyr_x = 5; - */ - float getGyrX(); - - /** - * optional float gyr_y = 6; + * float accuracy = 2; + * @return The accuracy. */ - float getGyrY(); - - /** - * optional float gyr_z = 7; - */ - float getGyrZ(); + float getAccuracy(); /** *
-     * unitless, 4 components should sum to ~1
+     * m/s
      * 
* - * optional float rotation_vector_x = 8; - */ - float getRotationVectorX(); - - /** - * optional float rotation_vector_y = 9; + * float speed = 3; + * @return The speed. */ - float getRotationVectorY(); + float getSpeed(); /** - * optional float rotation_vector_z = 10; + *
+     * degrees
+     * 
+ * + * float bearing = 4; + * @return The bearing. */ - float getRotationVectorZ(); + float getBearing(); /** - * optional float rotation_vector_w = 11; + *
+     * e.g 'gps' or 'network'
+     * 
+ * + * string provider = 5; + * @return The provider. */ - float getRotationVectorW(); - + java.lang.String getProvider(); /** *
-     * Integer
+     * e.g 'gps' or 'network'
      * 
* - * optional int32 step_count = 12; + * string provider = 5; + * @return The bytes for provider. */ - int getStepCount(); + com.google.protobuf.ByteString + getProviderBytes(); } /** - * Protobuf type {@code Motion_Sample} + * Protobuf type {@code GNSSReading} */ - public static final class Motion_Sample extends + public static final class GNSSReading extends com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:Motion_Sample) - Motion_SampleOrBuilder { - // Use Motion_Sample.newBuilder() to construct. - private Motion_Sample(com.google.protobuf.GeneratedMessageV3.Builder builder) { + // @@protoc_insertion_point(message_implements:GNSSReading) + GNSSReadingOrBuilder { + private static final long serialVersionUID = 0L; + // Use GNSSReading.newBuilder() to construct. + private GNSSReading(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } - private Motion_Sample() { - relativeTimestamp_ = 0L; - accX_ = 0F; - accY_ = 0F; - accZ_ = 0F; - gyrX_ = 0F; - gyrY_ = 0F; - gyrZ_ = 0F; - rotationVectorX_ = 0F; - rotationVectorY_ = 0F; - rotationVectorZ_ = 0F; - rotationVectorW_ = 0F; - stepCount_ = 0; - } - - @Override + private GNSSReading() { + provider_ = ""; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new GNSSReading(); + } + + @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + return this.unknownFields; } - private Motion_Sample( + private GNSSReading( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); - int mutable_bitField0_ = 0; + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { @@ -5612,488 +13514,373 @@ private Motion_Sample( case 0: done = true; break; - default: { - if (!input.skipField(tag)) { - done = true; + case 10: { + Traj.GNSSPosition.Builder subBuilder = null; + if (position_ != null) { + subBuilder = position_.toBuilder(); + } + position_ = input.readMessage(Traj.GNSSPosition.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(position_); + position_ = subBuilder.buildPartial(); } - break; - } - case 8: { - relativeTimestamp_ = input.readInt64(); break; } case 21: { - accX_ = input.readFloat(); + accuracy_ = input.readFloat(); break; } case 29: { - accY_ = input.readFloat(); + speed_ = input.readFloat(); break; } case 37: { - accZ_ = input.readFloat(); - break; - } - case 45: { - - gyrX_ = input.readFloat(); - break; - } - case 53: { - - gyrY_ = input.readFloat(); - break; - } - case 61: { - - gyrZ_ = input.readFloat(); - break; - } - case 69: { - - rotationVectorX_ = input.readFloat(); - break; - } - case 77: { - - rotationVectorY_ = input.readFloat(); + bearing_ = input.readFloat(); break; } - case 85: { - - rotationVectorZ_ = input.readFloat(); - break; - } - case 93: { + case 42: { + java.lang.String s = input.readStringRequireUtf8(); - rotationVectorW_ = input.readFloat(); + provider_ = s; break; } - case 96: { - - stepCount_ = input.readInt32(); + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { + this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Motion_Sample_descriptor; + return Traj.internal_static_GNSSReading_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Motion_Sample_fieldAccessorTable + return Traj.internal_static_GNSSReading_fieldAccessorTable .ensureFieldAccessorsInitialized( - Motion_Sample.class, Builder.class); - } - - public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; - private long relativeTimestamp_; - /** - *
-     * milliseconds
-     * 
- * - * optional int64 relative_timestamp = 1; - */ - public long getRelativeTimestamp() { - return relativeTimestamp_; + Traj.GNSSReading.class, Traj.GNSSReading.Builder.class); } - public static final int ACC_X_FIELD_NUMBER = 2; - private float accX_; + public static final int POSITION_FIELD_NUMBER = 1; + private Traj.GNSSPosition position_; /** - *
-     * m/s^2
-     * 
- * - * optional float acc_x = 2; + * .GNSSPosition position = 1; + * @return Whether the position field is set. */ - public float getAccX() { - return accX_; + @java.lang.Override + public boolean hasPosition() { + return position_ != null; } - - public static final int ACC_Y_FIELD_NUMBER = 3; - private float accY_; /** - * optional float acc_y = 3; + * .GNSSPosition position = 1; + * @return The position. */ - public float getAccY() { - return accY_; + @java.lang.Override + public Traj.GNSSPosition getPosition() { + return position_ == null ? Traj.GNSSPosition.getDefaultInstance() : position_; } - - public static final int ACC_Z_FIELD_NUMBER = 4; - private float accZ_; /** - * optional float acc_z = 4; + * .GNSSPosition position = 1; */ - public float getAccZ() { - return accZ_; + @java.lang.Override + public Traj.GNSSPositionOrBuilder getPositionOrBuilder() { + return getPosition(); } - public static final int GYR_X_FIELD_NUMBER = 5; - private float gyrX_; + public static final int ACCURACY_FIELD_NUMBER = 2; + private float accuracy_; /** *
-     * radians/s
+     * metres
      * 
* - * optional float gyr_x = 5; - */ - public float getGyrX() { - return gyrX_; - } - - public static final int GYR_Y_FIELD_NUMBER = 6; - private float gyrY_; - /** - * optional float gyr_y = 6; - */ - public float getGyrY() { - return gyrY_; - } - - public static final int GYR_Z_FIELD_NUMBER = 7; - private float gyrZ_; - /** - * optional float gyr_z = 7; + * float accuracy = 2; + * @return The accuracy. */ - public float getGyrZ() { - return gyrZ_; + @java.lang.Override + public float getAccuracy() { + return accuracy_; } - public static final int ROTATION_VECTOR_X_FIELD_NUMBER = 8; - private float rotationVectorX_; + public static final int SPEED_FIELD_NUMBER = 3; + private float speed_; /** *
-     * unitless, 4 components should sum to ~1
+     * m/s
      * 
* - * optional float rotation_vector_x = 8; - */ - public float getRotationVectorX() { - return rotationVectorX_; - } - - public static final int ROTATION_VECTOR_Y_FIELD_NUMBER = 9; - private float rotationVectorY_; - /** - * optional float rotation_vector_y = 9; + * float speed = 3; + * @return The speed. */ - public float getRotationVectorY() { - return rotationVectorY_; + @java.lang.Override + public float getSpeed() { + return speed_; } - public static final int ROTATION_VECTOR_Z_FIELD_NUMBER = 10; - private float rotationVectorZ_; + public static final int BEARING_FIELD_NUMBER = 4; + private float bearing_; /** - * optional float rotation_vector_z = 10; + *
+     * degrees
+     * 
+ * + * float bearing = 4; + * @return The bearing. */ - public float getRotationVectorZ() { - return rotationVectorZ_; + @java.lang.Override + public float getBearing() { + return bearing_; } - public static final int ROTATION_VECTOR_W_FIELD_NUMBER = 11; - private float rotationVectorW_; + public static final int PROVIDER_FIELD_NUMBER = 5; + private volatile java.lang.Object provider_; /** - * optional float rotation_vector_w = 11; + *
+     * e.g 'gps' or 'network'
+     * 
+ * + * string provider = 5; + * @return The provider. */ - public float getRotationVectorW() { - return rotationVectorW_; + @java.lang.Override + public java.lang.String getProvider() { + java.lang.Object ref = provider_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + provider_ = s; + return s; + } } - - public static final int STEP_COUNT_FIELD_NUMBER = 12; - private int stepCount_; /** *
-     * Integer
+     * e.g 'gps' or 'network'
      * 
* - * optional int32 step_count = 12; + * string provider = 5; + * @return The bytes for provider. */ - public int getStepCount() { - return stepCount_; + @java.lang.Override + public com.google.protobuf.ByteString + getProviderBytes() { + java.lang.Object ref = provider_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + provider_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; if (isInitialized == 0) return false; memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (relativeTimestamp_ != 0L) { - output.writeInt64(1, relativeTimestamp_); - } - if (accX_ != 0F) { - output.writeFloat(2, accX_); - } - if (accY_ != 0F) { - output.writeFloat(3, accY_); - } - if (accZ_ != 0F) { - output.writeFloat(4, accZ_); - } - if (gyrX_ != 0F) { - output.writeFloat(5, gyrX_); - } - if (gyrY_ != 0F) { - output.writeFloat(6, gyrY_); - } - if (gyrZ_ != 0F) { - output.writeFloat(7, gyrZ_); - } - if (rotationVectorX_ != 0F) { - output.writeFloat(8, rotationVectorX_); + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (position_ != null) { + output.writeMessage(1, getPosition()); } - if (rotationVectorY_ != 0F) { - output.writeFloat(9, rotationVectorY_); + if (java.lang.Float.floatToRawIntBits(accuracy_) != 0) { + output.writeFloat(2, accuracy_); } - if (rotationVectorZ_ != 0F) { - output.writeFloat(10, rotationVectorZ_); + if (java.lang.Float.floatToRawIntBits(speed_) != 0) { + output.writeFloat(3, speed_); } - if (rotationVectorW_ != 0F) { - output.writeFloat(11, rotationVectorW_); + if (java.lang.Float.floatToRawIntBits(bearing_) != 0) { + output.writeFloat(4, bearing_); } - if (stepCount_ != 0) { - output.writeInt32(12, stepCount_); + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(provider_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 5, provider_); } + unknownFields.writeTo(output); } + @java.lang.Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; size = 0; - if (relativeTimestamp_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(1, relativeTimestamp_); - } - if (accX_ != 0F) { - size += com.google.protobuf.CodedOutputStream - .computeFloatSize(2, accX_); - } - if (accY_ != 0F) { - size += com.google.protobuf.CodedOutputStream - .computeFloatSize(3, accY_); - } - if (accZ_ != 0F) { - size += com.google.protobuf.CodedOutputStream - .computeFloatSize(4, accZ_); - } - if (gyrX_ != 0F) { + if (position_ != null) { size += com.google.protobuf.CodedOutputStream - .computeFloatSize(5, gyrX_); + .computeMessageSize(1, getPosition()); } - if (gyrY_ != 0F) { + if (java.lang.Float.floatToRawIntBits(accuracy_) != 0) { size += com.google.protobuf.CodedOutputStream - .computeFloatSize(6, gyrY_); + .computeFloatSize(2, accuracy_); } - if (gyrZ_ != 0F) { + if (java.lang.Float.floatToRawIntBits(speed_) != 0) { size += com.google.protobuf.CodedOutputStream - .computeFloatSize(7, gyrZ_); + .computeFloatSize(3, speed_); } - if (rotationVectorX_ != 0F) { + if (java.lang.Float.floatToRawIntBits(bearing_) != 0) { size += com.google.protobuf.CodedOutputStream - .computeFloatSize(8, rotationVectorX_); + .computeFloatSize(4, bearing_); } - if (rotationVectorY_ != 0F) { - size += com.google.protobuf.CodedOutputStream - .computeFloatSize(9, rotationVectorY_); - } - if (rotationVectorZ_ != 0F) { - size += com.google.protobuf.CodedOutputStream - .computeFloatSize(10, rotationVectorZ_); - } - if (rotationVectorW_ != 0F) { - size += com.google.protobuf.CodedOutputStream - .computeFloatSize(11, rotationVectorW_); - } - if (stepCount_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(12, stepCount_); + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(provider_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(5, provider_); } + size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } - private static final long serialVersionUID = 0L; - @Override - public boolean equals(final Object obj) { + @java.lang.Override + public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof Motion_Sample)) { + if (!(obj instanceof Traj.GNSSReading)) { return super.equals(obj); } - Motion_Sample other = (Motion_Sample) obj; - - boolean result = true; - result = result && (getRelativeTimestamp() - == other.getRelativeTimestamp()); - result = result && ( - Float.floatToIntBits(getAccX()) - == Float.floatToIntBits( - other.getAccX())); - result = result && ( - Float.floatToIntBits(getAccY()) - == Float.floatToIntBits( - other.getAccY())); - result = result && ( - Float.floatToIntBits(getAccZ()) - == Float.floatToIntBits( - other.getAccZ())); - result = result && ( - Float.floatToIntBits(getGyrX()) - == Float.floatToIntBits( - other.getGyrX())); - result = result && ( - Float.floatToIntBits(getGyrY()) - == Float.floatToIntBits( - other.getGyrY())); - result = result && ( - Float.floatToIntBits(getGyrZ()) - == Float.floatToIntBits( - other.getGyrZ())); - result = result && ( - Float.floatToIntBits(getRotationVectorX()) - == Float.floatToIntBits( - other.getRotationVectorX())); - result = result && ( - Float.floatToIntBits(getRotationVectorY()) - == Float.floatToIntBits( - other.getRotationVectorY())); - result = result && ( - Float.floatToIntBits(getRotationVectorZ()) - == Float.floatToIntBits( - other.getRotationVectorZ())); - result = result && ( - Float.floatToIntBits(getRotationVectorW()) - == Float.floatToIntBits( - other.getRotationVectorW())); - result = result && (getStepCount() - == other.getStepCount()); - return result; - } - - @Override + Traj.GNSSReading other = (Traj.GNSSReading) obj; + + if (hasPosition() != other.hasPosition()) return false; + if (hasPosition()) { + if (!getPosition() + .equals(other.getPosition())) return false; + } + if (java.lang.Float.floatToIntBits(getAccuracy()) + != java.lang.Float.floatToIntBits( + other.getAccuracy())) return false; + if (java.lang.Float.floatToIntBits(getSpeed()) + != java.lang.Float.floatToIntBits( + other.getSpeed())) return false; + if (java.lang.Float.floatToIntBits(getBearing()) + != java.lang.Float.floatToIntBits( + other.getBearing())) return false; + if (!getProvider() + .equals(other.getProvider())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; - hash = (19 * hash) + getDescriptorForType().hashCode(); - hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getRelativeTimestamp()); - hash = (37 * hash) + ACC_X_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getAccX()); - hash = (37 * hash) + ACC_Y_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getAccY()); - hash = (37 * hash) + ACC_Z_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getAccZ()); - hash = (37 * hash) + GYR_X_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getGyrX()); - hash = (37 * hash) + GYR_Y_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getGyrY()); - hash = (37 * hash) + GYR_Z_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getGyrZ()); - hash = (37 * hash) + ROTATION_VECTOR_X_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getRotationVectorX()); - hash = (37 * hash) + ROTATION_VECTOR_Y_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getRotationVectorY()); - hash = (37 * hash) + ROTATION_VECTOR_Z_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getRotationVectorZ()); - hash = (37 * hash) + ROTATION_VECTOR_W_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getRotationVectorW()); - hash = (37 * hash) + STEP_COUNT_FIELD_NUMBER; - hash = (53 * hash) + getStepCount(); + hash = (19 * hash) + getDescriptor().hashCode(); + if (hasPosition()) { + hash = (37 * hash) + POSITION_FIELD_NUMBER; + hash = (53 * hash) + getPosition().hashCode(); + } + hash = (37 * hash) + ACCURACY_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getAccuracy()); + hash = (37 * hash) + SPEED_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getSpeed()); + hash = (37 * hash) + BEARING_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getBearing()); + hash = (37 * hash) + PROVIDER_FIELD_NUMBER; + hash = (53 * hash) + getProvider().hashCode(); hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } - public static Motion_Sample parseFrom( + public static Traj.GNSSReading parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.GNSSReading parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.GNSSReading parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Motion_Sample parseFrom( + public static Traj.GNSSReading parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Motion_Sample parseFrom(byte[] data) + public static Traj.GNSSReading parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Motion_Sample parseFrom( + public static Traj.GNSSReading parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Motion_Sample parseFrom(java.io.InputStream input) + public static Traj.GNSSReading parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Motion_Sample parseFrom( + public static Traj.GNSSReading parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static Motion_Sample parseDelimitedFrom(java.io.InputStream input) + public static Traj.GNSSReading parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static Motion_Sample parseDelimitedFrom( + public static Traj.GNSSReading parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static Motion_Sample parseFrom( + public static Traj.GNSSReading parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Motion_Sample parseFrom( + public static Traj.GNSSReading parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -6101,44 +13888,47 @@ public static Motion_Sample parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } + @java.lang.Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(Motion_Sample prototype) { + public static Builder newBuilder(Traj.GNSSReading prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } - @Override + @java.lang.Override protected Builder newBuilderForType( com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** - * Protobuf type {@code Motion_Sample} + * Protobuf type {@code GNSSReading} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:Motion_Sample) - Motion_SampleOrBuilder { + // @@protoc_insertion_point(builder_implements:GNSSReading) + Traj.GNSSReadingOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Motion_Sample_descriptor; + return Traj.internal_static_GNSSReading_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Motion_Sample_fieldAccessorTable + return Traj.internal_static_GNSSReading_fieldAccessorTable .ensureFieldAccessorsInitialized( - Motion_Sample.class, Builder.class); + Traj.GNSSReading.class, Traj.GNSSReading.Builder.class); } - // Construct using Traj.Motion_Sample.newBuilder() + // Construct using Traj.GNSSReading.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -6153,160 +13943,142 @@ private void maybeForceBuilderInitialization() { .alwaysUseFieldBuilders) { } } + @java.lang.Override public Builder clear() { super.clear(); - relativeTimestamp_ = 0L; - - accX_ = 0F; - - accY_ = 0F; - - accZ_ = 0F; - - gyrX_ = 0F; - - gyrY_ = 0F; - - gyrZ_ = 0F; - - rotationVectorX_ = 0F; - - rotationVectorY_ = 0F; + if (positionBuilder_ == null) { + position_ = null; + } else { + position_ = null; + positionBuilder_ = null; + } + accuracy_ = 0F; - rotationVectorZ_ = 0F; + speed_ = 0F; - rotationVectorW_ = 0F; + bearing_ = 0F; - stepCount_ = 0; + provider_ = ""; return this; } + @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return Traj.internal_static_Motion_Sample_descriptor; + return Traj.internal_static_GNSSReading_descriptor; } - public Motion_Sample getDefaultInstanceForType() { - return Motion_Sample.getDefaultInstance(); + @java.lang.Override + public Traj.GNSSReading getDefaultInstanceForType() { + return Traj.GNSSReading.getDefaultInstance(); } - public Motion_Sample build() { - Motion_Sample result = buildPartial(); + @java.lang.Override + public Traj.GNSSReading build() { + Traj.GNSSReading result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } - public Motion_Sample buildPartial() { - Motion_Sample result = new Motion_Sample(this); - result.relativeTimestamp_ = relativeTimestamp_; - result.accX_ = accX_; - result.accY_ = accY_; - result.accZ_ = accZ_; - result.gyrX_ = gyrX_; - result.gyrY_ = gyrY_; - result.gyrZ_ = gyrZ_; - result.rotationVectorX_ = rotationVectorX_; - result.rotationVectorY_ = rotationVectorY_; - result.rotationVectorZ_ = rotationVectorZ_; - result.rotationVectorW_ = rotationVectorW_; - result.stepCount_ = stepCount_; + @java.lang.Override + public Traj.GNSSReading buildPartial() { + Traj.GNSSReading result = new Traj.GNSSReading(this); + if (positionBuilder_ == null) { + result.position_ = position_; + } else { + result.position_ = positionBuilder_.build(); + } + result.accuracy_ = accuracy_; + result.speed_ = speed_; + result.bearing_ = bearing_; + result.provider_ = provider_; onBuilt(); return result; } + @java.lang.Override public Builder clone() { - return (Builder) super.clone(); + return super.clone(); } + @java.lang.Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); + java.lang.Object value) { + return super.setField(field, value); } + @java.lang.Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); + return super.clearField(field); } + @java.lang.Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); + return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); + java.lang.Object value) { + return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof Motion_Sample) { - return mergeFrom((Motion_Sample)other); + if (other instanceof Traj.GNSSReading) { + return mergeFrom((Traj.GNSSReading)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(Motion_Sample other) { - if (other == Motion_Sample.getDefaultInstance()) return this; - if (other.getRelativeTimestamp() != 0L) { - setRelativeTimestamp(other.getRelativeTimestamp()); - } - if (other.getAccX() != 0F) { - setAccX(other.getAccX()); - } - if (other.getAccY() != 0F) { - setAccY(other.getAccY()); + public Builder mergeFrom(Traj.GNSSReading other) { + if (other == Traj.GNSSReading.getDefaultInstance()) return this; + if (other.hasPosition()) { + mergePosition(other.getPosition()); } - if (other.getAccZ() != 0F) { - setAccZ(other.getAccZ()); - } - if (other.getGyrX() != 0F) { - setGyrX(other.getGyrX()); - } - if (other.getGyrY() != 0F) { - setGyrY(other.getGyrY()); - } - if (other.getGyrZ() != 0F) { - setGyrZ(other.getGyrZ()); - } - if (other.getRotationVectorX() != 0F) { - setRotationVectorX(other.getRotationVectorX()); - } - if (other.getRotationVectorY() != 0F) { - setRotationVectorY(other.getRotationVectorY()); + if (other.getAccuracy() != 0F) { + setAccuracy(other.getAccuracy()); } - if (other.getRotationVectorZ() != 0F) { - setRotationVectorZ(other.getRotationVectorZ()); + if (other.getSpeed() != 0F) { + setSpeed(other.getSpeed()); } - if (other.getRotationVectorW() != 0F) { - setRotationVectorW(other.getRotationVectorW()); + if (other.getBearing() != 0F) { + setBearing(other.getBearing()); } - if (other.getStepCount() != 0) { - setStepCount(other.getStepCount()); + if (!other.getProvider().isEmpty()) { + provider_ = other.provider_; + onChanged(); } + this.mergeUnknownFields(other.unknownFields); onChanged(); return this; } + @java.lang.Override public final boolean isInitialized() { return true; } + @java.lang.Override public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - Motion_Sample parsedMessage = null; + Traj.GNSSReading parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (Motion_Sample) e.getUnfinishedMessage(); + parsedMessage = (Traj.GNSSReading) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -6316,483 +14088,475 @@ public Builder mergeFrom( return this; } - private long relativeTimestamp_ ; + private Traj.GNSSPosition position_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder> positionBuilder_; /** - *
-       * milliseconds
-       * 
- * - * optional int64 relative_timestamp = 1; + * .GNSSPosition position = 1; + * @return Whether the position field is set. */ - public long getRelativeTimestamp() { - return relativeTimestamp_; + public boolean hasPosition() { + return positionBuilder_ != null || position_ != null; } /** - *
-       * milliseconds
-       * 
- * - * optional int64 relative_timestamp = 1; + * .GNSSPosition position = 1; + * @return The position. */ - public Builder setRelativeTimestamp(long value) { - - relativeTimestamp_ = value; - onChanged(); - return this; + public Traj.GNSSPosition getPosition() { + if (positionBuilder_ == null) { + return position_ == null ? Traj.GNSSPosition.getDefaultInstance() : position_; + } else { + return positionBuilder_.getMessage(); + } } /** - *
-       * milliseconds
-       * 
- * - * optional int64 relative_timestamp = 1; + * .GNSSPosition position = 1; */ - public Builder clearRelativeTimestamp() { - - relativeTimestamp_ = 0L; - onChanged(); - return this; - } + public Builder setPosition(Traj.GNSSPosition value) { + if (positionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + position_ = value; + onChanged(); + } else { + positionBuilder_.setMessage(value); + } - private float accX_ ; - /** - *
-       * m/s^2
-       * 
- * - * optional float acc_x = 2; - */ - public float getAccX() { - return accX_; - } - /** - *
-       * m/s^2
-       * 
- * - * optional float acc_x = 2; - */ - public Builder setAccX(float value) { - - accX_ = value; - onChanged(); return this; } /** - *
-       * m/s^2
-       * 
- * - * optional float acc_x = 2; + * .GNSSPosition position = 1; */ - public Builder clearAccX() { - - accX_ = 0F; - onChanged(); + public Builder setPosition( + Traj.GNSSPosition.Builder builderForValue) { + if (positionBuilder_ == null) { + position_ = builderForValue.build(); + onChanged(); + } else { + positionBuilder_.setMessage(builderForValue.build()); + } + return this; } - - private float accY_ ; /** - * optional float acc_y = 3; + * .GNSSPosition position = 1; */ - public float getAccY() { - return accY_; + public Builder mergePosition(Traj.GNSSPosition value) { + if (positionBuilder_ == null) { + if (position_ != null) { + position_ = + Traj.GNSSPosition.newBuilder(position_).mergeFrom(value).buildPartial(); + } else { + position_ = value; + } + onChanged(); + } else { + positionBuilder_.mergeFrom(value); + } + + return this; } /** - * optional float acc_y = 3; + * .GNSSPosition position = 1; */ - public Builder setAccY(float value) { - - accY_ = value; - onChanged(); + public Builder clearPosition() { + if (positionBuilder_ == null) { + position_ = null; + onChanged(); + } else { + position_ = null; + positionBuilder_ = null; + } + return this; } /** - * optional float acc_y = 3; + * .GNSSPosition position = 1; */ - public Builder clearAccY() { + public Traj.GNSSPosition.Builder getPositionBuilder() { - accY_ = 0F; onChanged(); - return this; - } - - private float accZ_ ; - /** - * optional float acc_z = 4; - */ - public float getAccZ() { - return accZ_; + return getPositionFieldBuilder().getBuilder(); } /** - * optional float acc_z = 4; + * .GNSSPosition position = 1; */ - public Builder setAccZ(float value) { - - accZ_ = value; - onChanged(); - return this; + public Traj.GNSSPositionOrBuilder getPositionOrBuilder() { + if (positionBuilder_ != null) { + return positionBuilder_.getMessageOrBuilder(); + } else { + return position_ == null ? + Traj.GNSSPosition.getDefaultInstance() : position_; + } } /** - * optional float acc_z = 4; + * .GNSSPosition position = 1; */ - public Builder clearAccZ() { - - accZ_ = 0F; - onChanged(); - return this; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder> + getPositionFieldBuilder() { + if (positionBuilder_ == null) { + positionBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder>( + getPosition(), + getParentForChildren(), + isClean()); + position_ = null; + } + return positionBuilder_; } - private float gyrX_ ; + private float accuracy_ ; /** *
-       * radians/s
+       * metres
        * 
* - * optional float gyr_x = 5; + * float accuracy = 2; + * @return The accuracy. */ - public float getGyrX() { - return gyrX_; + @java.lang.Override + public float getAccuracy() { + return accuracy_; } /** *
-       * radians/s
+       * metres
        * 
* - * optional float gyr_x = 5; + * float accuracy = 2; + * @param value The accuracy to set. + * @return This builder for chaining. */ - public Builder setGyrX(float value) { + public Builder setAccuracy(float value) { - gyrX_ = value; + accuracy_ = value; onChanged(); return this; } /** *
-       * radians/s
+       * metres
        * 
* - * optional float gyr_x = 5; - */ - public Builder clearGyrX() { - - gyrX_ = 0F; - onChanged(); - return this; - } - - private float gyrY_ ; - /** - * optional float gyr_y = 6; - */ - public float getGyrY() { - return gyrY_; - } - /** - * optional float gyr_y = 6; + * float accuracy = 2; + * @return This builder for chaining. */ - public Builder setGyrY(float value) { - - gyrY_ = value; - onChanged(); - return this; - } - /** - * optional float gyr_y = 6; - */ - public Builder clearGyrY() { - - gyrY_ = 0F; - onChanged(); - return this; - } - - private float gyrZ_ ; - /** - * optional float gyr_z = 7; - */ - public float getGyrZ() { - return gyrZ_; - } - /** - * optional float gyr_z = 7; - */ - public Builder setGyrZ(float value) { - - gyrZ_ = value; - onChanged(); - return this; - } - /** - * optional float gyr_z = 7; - */ - public Builder clearGyrZ() { + public Builder clearAccuracy() { - gyrZ_ = 0F; + accuracy_ = 0F; onChanged(); return this; } - private float rotationVectorX_ ; + private float speed_ ; /** *
-       * unitless, 4 components should sum to ~1
+       * m/s
        * 
* - * optional float rotation_vector_x = 8; + * float speed = 3; + * @return The speed. */ - public float getRotationVectorX() { - return rotationVectorX_; + @java.lang.Override + public float getSpeed() { + return speed_; } /** *
-       * unitless, 4 components should sum to ~1
+       * m/s
        * 
* - * optional float rotation_vector_x = 8; + * float speed = 3; + * @param value The speed to set. + * @return This builder for chaining. */ - public Builder setRotationVectorX(float value) { + public Builder setSpeed(float value) { - rotationVectorX_ = value; + speed_ = value; onChanged(); return this; } /** *
-       * unitless, 4 components should sum to ~1
+       * m/s
        * 
* - * optional float rotation_vector_x = 8; - */ - public Builder clearRotationVectorX() { - - rotationVectorX_ = 0F; - onChanged(); - return this; - } - - private float rotationVectorY_ ; - /** - * optional float rotation_vector_y = 9; - */ - public float getRotationVectorY() { - return rotationVectorY_; - } - /** - * optional float rotation_vector_y = 9; - */ - public Builder setRotationVectorY(float value) { - - rotationVectorY_ = value; - onChanged(); - return this; - } - /** - * optional float rotation_vector_y = 9; - */ - public Builder clearRotationVectorY() { - - rotationVectorY_ = 0F; - onChanged(); - return this; - } - - private float rotationVectorZ_ ; - /** - * optional float rotation_vector_z = 10; - */ - public float getRotationVectorZ() { - return rotationVectorZ_; - } - /** - * optional float rotation_vector_z = 10; - */ - public Builder setRotationVectorZ(float value) { - - rotationVectorZ_ = value; - onChanged(); - return this; - } - /** - * optional float rotation_vector_z = 10; + * float speed = 3; + * @return This builder for chaining. */ - public Builder clearRotationVectorZ() { + public Builder clearSpeed() { - rotationVectorZ_ = 0F; + speed_ = 0F; onChanged(); return this; } - private float rotationVectorW_ ; + private float bearing_ ; /** - * optional float rotation_vector_w = 11; + *
+       * degrees
+       * 
+ * + * float bearing = 4; + * @return The bearing. */ - public float getRotationVectorW() { - return rotationVectorW_; + @java.lang.Override + public float getBearing() { + return bearing_; } /** - * optional float rotation_vector_w = 11; + *
+       * degrees
+       * 
+ * + * float bearing = 4; + * @param value The bearing to set. + * @return This builder for chaining. */ - public Builder setRotationVectorW(float value) { + public Builder setBearing(float value) { - rotationVectorW_ = value; + bearing_ = value; onChanged(); return this; } /** - * optional float rotation_vector_w = 11; + *
+       * degrees
+       * 
+ * + * float bearing = 4; + * @return This builder for chaining. */ - public Builder clearRotationVectorW() { + public Builder clearBearing() { - rotationVectorW_ = 0F; + bearing_ = 0F; onChanged(); return this; } - private int stepCount_ ; + private java.lang.Object provider_ = ""; /** *
-       * Integer
+       * e.g 'gps' or 'network'
        * 
* - * optional int32 step_count = 12; + * string provider = 5; + * @return The provider. */ - public int getStepCount() { - return stepCount_; + public java.lang.String getProvider() { + java.lang.Object ref = provider_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + provider_ = s; + return s; + } else { + return (java.lang.String) ref; + } } /** *
-       * Integer
+       * e.g 'gps' or 'network'
        * 
* - * optional int32 step_count = 12; + * string provider = 5; + * @return The bytes for provider. */ - public Builder setStepCount(int value) { + public com.google.protobuf.ByteString + getProviderBytes() { + java.lang.Object ref = provider_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + provider_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + *
+       * e.g 'gps' or 'network'
+       * 
+ * + * string provider = 5; + * @param value The provider to set. + * @return This builder for chaining. + */ + public Builder setProvider( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + provider_ = value; + onChanged(); + return this; + } + /** + *
+       * e.g 'gps' or 'network'
+       * 
+ * + * string provider = 5; + * @return This builder for chaining. + */ + public Builder clearProvider() { - stepCount_ = value; + provider_ = getDefaultInstance().getProvider(); onChanged(); return this; } /** *
-       * Integer
+       * e.g 'gps' or 'network'
        * 
* - * optional int32 step_count = 12; + * string provider = 5; + * @param value The bytes for provider to set. + * @return This builder for chaining. */ - public Builder clearStepCount() { + public Builder setProviderBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); - stepCount_ = 0; + provider_ = value; onChanged(); return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.setUnknownFields(unknownFields); } + @java.lang.Override public final Builder mergeUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:Motion_Sample) + // @@protoc_insertion_point(builder_scope:GNSSReading) } - // @@protoc_insertion_point(class_scope:Motion_Sample) - private static final Motion_Sample DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:GNSSReading) + private static final Traj.GNSSReading DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new Motion_Sample(); + DEFAULT_INSTANCE = new Traj.GNSSReading(); } - public static Motion_Sample getDefaultInstance() { + public static Traj.GNSSReading getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - public Motion_Sample parsePartialFrom( + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public GNSSReading parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { - return new Motion_Sample(input, extensionRegistry); + return new GNSSReading(input, extensionRegistry); } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } - @Override - public com.google.protobuf.Parser getParserForType() { + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { return PARSER; } - public Motion_Sample getDefaultInstanceForType() { + @java.lang.Override + public Traj.GNSSReading getDefaultInstanceForType() { return DEFAULT_INSTANCE; } } - public interface Position_SampleOrBuilder extends - // @@protoc_insertion_point(interface_extends:Position_Sample) + public interface FingerprintOrBuilder extends + // @@protoc_insertion_point(interface_extends:Fingerprint) com.google.protobuf.MessageOrBuilder { /** - * optional int64 relative_timestamp = 1; + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. */ long getRelativeTimestamp(); /** - *
-     * uT
-     * 
- * - * optional float mag_x = 2; + * repeated .RFScan rf_scans = 2; */ - float getMagX(); - + java.util.List + getRfScansList(); /** - * optional float mag_y = 3; + * repeated .RFScan rf_scans = 2; */ - float getMagY(); - + Traj.RFScan getRfScans(int index); + /** + * repeated .RFScan rf_scans = 2; + */ + int getRfScansCount(); + /** + * repeated .RFScan rf_scans = 2; + */ + java.util.List + getRfScansOrBuilderList(); /** - * optional float mag_z = 4; + * repeated .RFScan rf_scans = 2; */ - float getMagZ(); + Traj.RFScanOrBuilder getRfScansOrBuilder( + int index); } /** - * Protobuf type {@code Position_Sample} + * Protobuf type {@code Fingerprint} */ - public static final class Position_Sample extends + public static final class Fingerprint extends com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:Position_Sample) - Position_SampleOrBuilder { - // Use Position_Sample.newBuilder() to construct. - private Position_Sample(com.google.protobuf.GeneratedMessageV3.Builder builder) { + // @@protoc_insertion_point(message_implements:Fingerprint) + FingerprintOrBuilder { + private static final long serialVersionUID = 0L; + // Use Fingerprint.newBuilder() to construct. + private Fingerprint(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } - private Position_Sample() { - relativeTimestamp_ = 0L; - magX_ = 0F; - magY_ = 0F; - magZ_ = 0F; + private Fingerprint() { + rfScans_ = java.util.Collections.emptyList(); } - @Override + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new Fingerprint(); + } + + @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + return this.unknownFields; } - private Position_Sample( + private Fingerprint( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { @@ -6801,96 +14565,110 @@ private Position_Sample( case 0: done = true; break; - default: { - if (!input.skipField(tag)) { - done = true; - } - break; - } case 8: { relativeTimestamp_ = input.readInt64(); break; } - case 21: { - - magX_ = input.readFloat(); - break; - } - case 29: { - - magY_ = input.readFloat(); + case 18: { + if (!((mutable_bitField0_ & 0x00000001) != 0)) { + rfScans_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000001; + } + rfScans_.add( + input.readMessage(Traj.RFScan.parser(), extensionRegistry)); break; } - case 37: { - - magZ_ = input.readFloat(); + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { + if (((mutable_bitField0_ & 0x00000001) != 0)) { + rfScans_ = java.util.Collections.unmodifiableList(rfScans_); + } + this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Position_Sample_descriptor; + return Traj.internal_static_Fingerprint_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Position_Sample_fieldAccessorTable + return Traj.internal_static_Fingerprint_fieldAccessorTable .ensureFieldAccessorsInitialized( - Position_Sample.class, Builder.class); + Traj.Fingerprint.class, Traj.Fingerprint.Builder.class); } public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; private long relativeTimestamp_; /** - * optional int64 relative_timestamp = 1; + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. */ + @java.lang.Override public long getRelativeTimestamp() { return relativeTimestamp_; } - public static final int MAG_X_FIELD_NUMBER = 2; - private float magX_; + public static final int RF_SCANS_FIELD_NUMBER = 2; + private java.util.List rfScans_; /** - *
-     * uT
-     * 
- * - * optional float mag_x = 2; + * repeated .RFScan rf_scans = 2; */ - public float getMagX() { - return magX_; + @java.lang.Override + public java.util.List getRfScansList() { + return rfScans_; } - - public static final int MAG_Y_FIELD_NUMBER = 3; - private float magY_; /** - * optional float mag_y = 3; + * repeated .RFScan rf_scans = 2; */ - public float getMagY() { - return magY_; + @java.lang.Override + public java.util.List + getRfScansOrBuilderList() { + return rfScans_; + } + /** + * repeated .RFScan rf_scans = 2; + */ + @java.lang.Override + public int getRfScansCount() { + return rfScans_.size(); + } + /** + * repeated .RFScan rf_scans = 2; + */ + @java.lang.Override + public Traj.RFScan getRfScans(int index) { + return rfScans_.get(index); } - - public static final int MAG_Z_FIELD_NUMBER = 4; - private float magZ_; /** - * optional float mag_z = 4; + * repeated .RFScan rf_scans = 2; */ - public float getMagZ() { - return magZ_; + @java.lang.Override + public Traj.RFScanOrBuilder getRfScansOrBuilder( + int index) { + return rfScans_.get(index); } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; @@ -6900,22 +14678,19 @@ public final boolean isInitialized() { return true; } + @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (relativeTimestamp_ != 0L) { output.writeInt64(1, relativeTimestamp_); } - if (magX_ != 0F) { - output.writeFloat(2, magX_); - } - if (magY_ != 0F) { - output.writeFloat(3, magY_); - } - if (magZ_ != 0F) { - output.writeFloat(4, magZ_); + for (int i = 0; i < rfScans_.size(); i++) { + output.writeMessage(2, rfScans_.get(i)); } + unknownFields.writeTo(output); } + @java.lang.Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; @@ -6925,127 +14700,115 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeInt64Size(1, relativeTimestamp_); } - if (magX_ != 0F) { - size += com.google.protobuf.CodedOutputStream - .computeFloatSize(2, magX_); - } - if (magY_ != 0F) { - size += com.google.protobuf.CodedOutputStream - .computeFloatSize(3, magY_); - } - if (magZ_ != 0F) { + for (int i = 0; i < rfScans_.size(); i++) { size += com.google.protobuf.CodedOutputStream - .computeFloatSize(4, magZ_); + .computeMessageSize(2, rfScans_.get(i)); } + size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } - private static final long serialVersionUID = 0L; - @Override - public boolean equals(final Object obj) { + @java.lang.Override + public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof Position_Sample)) { + if (!(obj instanceof Traj.Fingerprint)) { return super.equals(obj); } - Position_Sample other = (Position_Sample) obj; - - boolean result = true; - result = result && (getRelativeTimestamp() - == other.getRelativeTimestamp()); - result = result && ( - Float.floatToIntBits(getMagX()) - == Float.floatToIntBits( - other.getMagX())); - result = result && ( - Float.floatToIntBits(getMagY()) - == Float.floatToIntBits( - other.getMagY())); - result = result && ( - Float.floatToIntBits(getMagZ()) - == Float.floatToIntBits( - other.getMagZ())); - return result; - } - - @Override + Traj.Fingerprint other = (Traj.Fingerprint) obj; + + if (getRelativeTimestamp() + != other.getRelativeTimestamp()) return false; + if (!getRfScansList() + .equals(other.getRfScansList())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; - hash = (19 * hash) + getDescriptorForType().hashCode(); + hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; hash = (53 * hash) + com.google.protobuf.Internal.hashLong( getRelativeTimestamp()); - hash = (37 * hash) + MAG_X_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getMagX()); - hash = (37 * hash) + MAG_Y_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getMagY()); - hash = (37 * hash) + MAG_Z_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getMagZ()); + if (getRfScansCount() > 0) { + hash = (37 * hash) + RF_SCANS_FIELD_NUMBER; + hash = (53 * hash) + getRfScansList().hashCode(); + } hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } - public static Position_Sample parseFrom( + public static Traj.Fingerprint parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.Fingerprint parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.Fingerprint parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Position_Sample parseFrom( + public static Traj.Fingerprint parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Position_Sample parseFrom(byte[] data) + public static Traj.Fingerprint parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Position_Sample parseFrom( + public static Traj.Fingerprint parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Position_Sample parseFrom(java.io.InputStream input) + public static Traj.Fingerprint parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Position_Sample parseFrom( + public static Traj.Fingerprint parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static Position_Sample parseDelimitedFrom(java.io.InputStream input) + public static Traj.Fingerprint parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static Position_Sample parseDelimitedFrom( + public static Traj.Fingerprint parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static Position_Sample parseFrom( + public static Traj.Fingerprint parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Position_Sample parseFrom( + public static Traj.Fingerprint parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -7053,44 +14816,47 @@ public static Position_Sample parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } + @java.lang.Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(Position_Sample prototype) { + public static Builder newBuilder(Traj.Fingerprint prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } - @Override + @java.lang.Override protected Builder newBuilderForType( com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** - * Protobuf type {@code Position_Sample} + * Protobuf type {@code Fingerprint} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:Position_Sample) - Position_SampleOrBuilder { + // @@protoc_insertion_point(builder_implements:Fingerprint) + Traj.FingerprintOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Position_Sample_descriptor; + return Traj.internal_static_Fingerprint_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Position_Sample_fieldAccessorTable + return Traj.internal_static_Fingerprint_fieldAccessorTable .ensureFieldAccessorsInitialized( - Position_Sample.class, Builder.class); + Traj.Fingerprint.class, Traj.Fingerprint.Builder.class); } - // Construct using Traj.Position_Sample.newBuilder() + // Construct using Traj.Fingerprint.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -7103,114 +14869,154 @@ private Builder( private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessageV3 .alwaysUseFieldBuilders) { + getRfScansFieldBuilder(); } } + @java.lang.Override public Builder clear() { super.clear(); relativeTimestamp_ = 0L; - magX_ = 0F; - - magY_ = 0F; - - magZ_ = 0F; - + if (rfScansBuilder_ == null) { + rfScans_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + } else { + rfScansBuilder_.clear(); + } return this; } + @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return Traj.internal_static_Position_Sample_descriptor; + return Traj.internal_static_Fingerprint_descriptor; } - public Position_Sample getDefaultInstanceForType() { - return Position_Sample.getDefaultInstance(); + @java.lang.Override + public Traj.Fingerprint getDefaultInstanceForType() { + return Traj.Fingerprint.getDefaultInstance(); } - public Position_Sample build() { - Position_Sample result = buildPartial(); + @java.lang.Override + public Traj.Fingerprint build() { + Traj.Fingerprint result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } - public Position_Sample buildPartial() { - Position_Sample result = new Position_Sample(this); + @java.lang.Override + public Traj.Fingerprint buildPartial() { + Traj.Fingerprint result = new Traj.Fingerprint(this); + int from_bitField0_ = bitField0_; result.relativeTimestamp_ = relativeTimestamp_; - result.magX_ = magX_; - result.magY_ = magY_; - result.magZ_ = magZ_; + if (rfScansBuilder_ == null) { + if (((bitField0_ & 0x00000001) != 0)) { + rfScans_ = java.util.Collections.unmodifiableList(rfScans_); + bitField0_ = (bitField0_ & ~0x00000001); + } + result.rfScans_ = rfScans_; + } else { + result.rfScans_ = rfScansBuilder_.build(); + } onBuilt(); return result; } + @java.lang.Override public Builder clone() { - return (Builder) super.clone(); + return super.clone(); } + @java.lang.Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); + java.lang.Object value) { + return super.setField(field, value); } + @java.lang.Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); + return super.clearField(field); } + @java.lang.Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); + return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); + java.lang.Object value) { + return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof Position_Sample) { - return mergeFrom((Position_Sample)other); + if (other instanceof Traj.Fingerprint) { + return mergeFrom((Traj.Fingerprint)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(Position_Sample other) { - if (other == Position_Sample.getDefaultInstance()) return this; + public Builder mergeFrom(Traj.Fingerprint other) { + if (other == Traj.Fingerprint.getDefaultInstance()) return this; if (other.getRelativeTimestamp() != 0L) { setRelativeTimestamp(other.getRelativeTimestamp()); } - if (other.getMagX() != 0F) { - setMagX(other.getMagX()); - } - if (other.getMagY() != 0F) { - setMagY(other.getMagY()); - } - if (other.getMagZ() != 0F) { - setMagZ(other.getMagZ()); + if (rfScansBuilder_ == null) { + if (!other.rfScans_.isEmpty()) { + if (rfScans_.isEmpty()) { + rfScans_ = other.rfScans_; + bitField0_ = (bitField0_ & ~0x00000001); + } else { + ensureRfScansIsMutable(); + rfScans_.addAll(other.rfScans_); + } + onChanged(); + } + } else { + if (!other.rfScans_.isEmpty()) { + if (rfScansBuilder_.isEmpty()) { + rfScansBuilder_.dispose(); + rfScansBuilder_ = null; + rfScans_ = other.rfScans_; + bitField0_ = (bitField0_ & ~0x00000001); + rfScansBuilder_ = + com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? + getRfScansFieldBuilder() : null; + } else { + rfScansBuilder_.addAllMessages(other.rfScans_); + } + } } + this.mergeUnknownFields(other.unknownFields); onChanged(); return this; } + @java.lang.Override public final boolean isInitialized() { return true; } + @java.lang.Override public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - Position_Sample parsedMessage = null; + Traj.Fingerprint parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (Position_Sample) e.getUnfinishedMessage(); + parsedMessage = (Traj.Fingerprint) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -7219,16 +15025,21 @@ public Builder mergeFrom( } return this; } + private int bitField0_; private long relativeTimestamp_ ; /** - * optional int64 relative_timestamp = 1; + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. */ + @java.lang.Override public long getRelativeTimestamp() { return relativeTimestamp_; } /** - * optional int64 relative_timestamp = 1; + * int64 relative_timestamp = 1; + * @param value The relativeTimestamp to set. + * @return This builder for chaining. */ public Builder setRelativeTimestamp(long value) { @@ -7237,7 +15048,8 @@ public Builder setRelativeTimestamp(long value) { return this; } /** - * optional int64 relative_timestamp = 1; + * int64 relative_timestamp = 1; + * @return This builder for chaining. */ public Builder clearRelativeTimestamp() { @@ -7246,189 +15058,395 @@ public Builder clearRelativeTimestamp() { return this; } - private float magX_ ; + private java.util.List rfScans_ = + java.util.Collections.emptyList(); + private void ensureRfScansIsMutable() { + if (!((bitField0_ & 0x00000001) != 0)) { + rfScans_ = new java.util.ArrayList(rfScans_); + bitField0_ |= 0x00000001; + } + } + + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.RFScan, Traj.RFScan.Builder, Traj.RFScanOrBuilder> rfScansBuilder_; + /** - *
-       * uT
-       * 
- * - * optional float mag_x = 2; + * repeated .RFScan rf_scans = 2; */ - public float getMagX() { - return magX_; + public java.util.List getRfScansList() { + if (rfScansBuilder_ == null) { + return java.util.Collections.unmodifiableList(rfScans_); + } else { + return rfScansBuilder_.getMessageList(); + } } /** - *
-       * uT
-       * 
- * - * optional float mag_x = 2; + * repeated .RFScan rf_scans = 2; */ - public Builder setMagX(float value) { - - magX_ = value; - onChanged(); + public int getRfScansCount() { + if (rfScansBuilder_ == null) { + return rfScans_.size(); + } else { + return rfScansBuilder_.getCount(); + } + } + /** + * repeated .RFScan rf_scans = 2; + */ + public Traj.RFScan getRfScans(int index) { + if (rfScansBuilder_ == null) { + return rfScans_.get(index); + } else { + return rfScansBuilder_.getMessage(index); + } + } + /** + * repeated .RFScan rf_scans = 2; + */ + public Builder setRfScans( + int index, Traj.RFScan value) { + if (rfScansBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureRfScansIsMutable(); + rfScans_.set(index, value); + onChanged(); + } else { + rfScansBuilder_.setMessage(index, value); + } return this; } /** - *
-       * uT
-       * 
- * - * optional float mag_x = 2; + * repeated .RFScan rf_scans = 2; */ - public Builder clearMagX() { - - magX_ = 0F; - onChanged(); + public Builder setRfScans( + int index, Traj.RFScan.Builder builderForValue) { + if (rfScansBuilder_ == null) { + ensureRfScansIsMutable(); + rfScans_.set(index, builderForValue.build()); + onChanged(); + } else { + rfScansBuilder_.setMessage(index, builderForValue.build()); + } return this; } - - private float magY_ ; /** - * optional float mag_y = 3; + * repeated .RFScan rf_scans = 2; + */ + public Builder addRfScans(Traj.RFScan value) { + if (rfScansBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureRfScansIsMutable(); + rfScans_.add(value); + onChanged(); + } else { + rfScansBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .RFScan rf_scans = 2; + */ + public Builder addRfScans( + int index, Traj.RFScan value) { + if (rfScansBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureRfScansIsMutable(); + rfScans_.add(index, value); + onChanged(); + } else { + rfScansBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .RFScan rf_scans = 2; + */ + public Builder addRfScans( + Traj.RFScan.Builder builderForValue) { + if (rfScansBuilder_ == null) { + ensureRfScansIsMutable(); + rfScans_.add(builderForValue.build()); + onChanged(); + } else { + rfScansBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .RFScan rf_scans = 2; + */ + public Builder addRfScans( + int index, Traj.RFScan.Builder builderForValue) { + if (rfScansBuilder_ == null) { + ensureRfScansIsMutable(); + rfScans_.add(index, builderForValue.build()); + onChanged(); + } else { + rfScansBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .RFScan rf_scans = 2; + */ + public Builder addAllRfScans( + java.lang.Iterable values) { + if (rfScansBuilder_ == null) { + ensureRfScansIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, rfScans_); + onChanged(); + } else { + rfScansBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .RFScan rf_scans = 2; + */ + public Builder clearRfScans() { + if (rfScansBuilder_ == null) { + rfScans_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + } else { + rfScansBuilder_.clear(); + } + return this; + } + /** + * repeated .RFScan rf_scans = 2; + */ + public Builder removeRfScans(int index) { + if (rfScansBuilder_ == null) { + ensureRfScansIsMutable(); + rfScans_.remove(index); + onChanged(); + } else { + rfScansBuilder_.remove(index); + } + return this; + } + /** + * repeated .RFScan rf_scans = 2; + */ + public Traj.RFScan.Builder getRfScansBuilder( + int index) { + return getRfScansFieldBuilder().getBuilder(index); + } + /** + * repeated .RFScan rf_scans = 2; */ - public float getMagY() { - return magY_; + public Traj.RFScanOrBuilder getRfScansOrBuilder( + int index) { + if (rfScansBuilder_ == null) { + return rfScans_.get(index); } else { + return rfScansBuilder_.getMessageOrBuilder(index); + } } /** - * optional float mag_y = 3; + * repeated .RFScan rf_scans = 2; */ - public Builder setMagY(float value) { - - magY_ = value; - onChanged(); - return this; + public java.util.List + getRfScansOrBuilderList() { + if (rfScansBuilder_ != null) { + return rfScansBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(rfScans_); + } } /** - * optional float mag_y = 3; + * repeated .RFScan rf_scans = 2; */ - public Builder clearMagY() { - - magY_ = 0F; - onChanged(); - return this; + public Traj.RFScan.Builder addRfScansBuilder() { + return getRfScansFieldBuilder().addBuilder( + Traj.RFScan.getDefaultInstance()); } - - private float magZ_ ; /** - * optional float mag_z = 4; + * repeated .RFScan rf_scans = 2; */ - public float getMagZ() { - return magZ_; + public Traj.RFScan.Builder addRfScansBuilder( + int index) { + return getRfScansFieldBuilder().addBuilder( + index, Traj.RFScan.getDefaultInstance()); } /** - * optional float mag_z = 4; + * repeated .RFScan rf_scans = 2; */ - public Builder setMagZ(float value) { - - magZ_ = value; - onChanged(); - return this; + public java.util.List + getRfScansBuilderList() { + return getRfScansFieldBuilder().getBuilderList(); } - /** - * optional float mag_z = 4; - */ - public Builder clearMagZ() { - - magZ_ = 0F; - onChanged(); - return this; + private com.google.protobuf.RepeatedFieldBuilderV3< + Traj.RFScan, Traj.RFScan.Builder, Traj.RFScanOrBuilder> + getRfScansFieldBuilder() { + if (rfScansBuilder_ == null) { + rfScansBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< + Traj.RFScan, Traj.RFScan.Builder, Traj.RFScanOrBuilder>( + rfScans_, + ((bitField0_ & 0x00000001) != 0), + getParentForChildren(), + isClean()); + rfScans_ = null; + } + return rfScansBuilder_; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.setUnknownFields(unknownFields); } + @java.lang.Override public final Builder mergeUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:Position_Sample) + // @@protoc_insertion_point(builder_scope:Fingerprint) } - // @@protoc_insertion_point(class_scope:Position_Sample) - private static final Position_Sample DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:Fingerprint) + private static final Traj.Fingerprint DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new Position_Sample(); + DEFAULT_INSTANCE = new Traj.Fingerprint(); } - public static Position_Sample getDefaultInstance() { + public static Traj.Fingerprint getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - public Position_Sample parsePartialFrom( + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Fingerprint parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { - return new Position_Sample(input, extensionRegistry); + return new Fingerprint(input, extensionRegistry); } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } - @Override - public com.google.protobuf.Parser getParserForType() { + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { return PARSER; } - public Position_Sample getDefaultInstanceForType() { + @java.lang.Override + public Traj.Fingerprint getDefaultInstanceForType() { return DEFAULT_INSTANCE; } } - public interface Pressure_SampleOrBuilder extends - // @@protoc_insertion_point(interface_extends:Pressure_Sample) + public interface RFScanOrBuilder extends + // @@protoc_insertion_point(interface_extends:RFScan) com.google.protobuf.MessageOrBuilder { /** - * optional int64 relative_timestamp = 1; + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. */ long getRelativeTimestamp(); /** *
-     * mbar
+     * Integer encoding of the hex mac address (BSSID)
+     * e.g. 207394925843984
      * 
* - * optional float pressure = 2; + * int64 mac = 2; + * @return The mac. */ - float getPressure(); + long getMac(); + + /** + *
+     * rssi integer in dBm.
+     * typically between -120 and -10
+     * 
+ * + * int32 rssi = 3; + * @return The rssi. + */ + int getRssi(); + + /** + *
+     * returned position
+     * 
+ * + * optional .GNSSPosition position = 4; + * @return Whether the position field is set. + */ + boolean hasPosition(); + /** + *
+     * returned position
+     * 
+ * + * optional .GNSSPosition position = 4; + * @return The position. + */ + Traj.GNSSPosition getPosition(); + /** + *
+     * returned position
+     * 
+ * + * optional .GNSSPosition position = 4; + */ + Traj.GNSSPositionOrBuilder getPositionOrBuilder(); } /** - * Protobuf type {@code Pressure_Sample} + * Protobuf type {@code RFScan} */ - public static final class Pressure_Sample extends + public static final class RFScan extends com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:Pressure_Sample) - Pressure_SampleOrBuilder { - // Use Pressure_Sample.newBuilder() to construct. - private Pressure_Sample(com.google.protobuf.GeneratedMessageV3.Builder builder) { + // @@protoc_insertion_point(message_implements:RFScan) + RFScanOrBuilder { + private static final long serialVersionUID = 0L; + // Use RFScan.newBuilder() to construct. + private RFScan(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } - private Pressure_Sample() { - relativeTimestamp_ = 0L; - pressure_ = 0F; + private RFScan() { + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new RFScan(); } - @Override + @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + return this.unknownFields; } - private Pressure_Sample( + private RFScan( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { @@ -7437,68 +15455,152 @@ private Pressure_Sample( case 0: done = true; break; - default: { - if (!input.skipField(tag)) { - done = true; - } - break; - } case 8: { relativeTimestamp_ = input.readInt64(); break; } - case 21: { + case 16: { - pressure_ = input.readFloat(); + mac_ = input.readInt64(); + break; + } + case 24: { + + rssi_ = input.readInt32(); + break; + } + case 34: { + Traj.GNSSPosition.Builder subBuilder = null; + if (((bitField0_ & 0x00000001) != 0)) { + subBuilder = position_.toBuilder(); + } + position_ = input.readMessage(Traj.GNSSPosition.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(position_); + position_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000001; + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { + this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Pressure_Sample_descriptor; + return Traj.internal_static_RFScan_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Pressure_Sample_fieldAccessorTable + return Traj.internal_static_RFScan_fieldAccessorTable .ensureFieldAccessorsInitialized( - Pressure_Sample.class, Builder.class); + Traj.RFScan.class, Traj.RFScan.Builder.class); } + private int bitField0_; public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; private long relativeTimestamp_; /** - * optional int64 relative_timestamp = 1; + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. */ + @java.lang.Override public long getRelativeTimestamp() { return relativeTimestamp_; } - public static final int PRESSURE_FIELD_NUMBER = 2; - private float pressure_; + public static final int MAC_FIELD_NUMBER = 2; + private long mac_; /** *
-     * mbar
+     * Integer encoding of the hex mac address (BSSID)
+     * e.g. 207394925843984
      * 
* - * optional float pressure = 2; + * int64 mac = 2; + * @return The mac. */ - public float getPressure() { - return pressure_; + @java.lang.Override + public long getMac() { + return mac_; + } + + public static final int RSSI_FIELD_NUMBER = 3; + private int rssi_; + /** + *
+     * rssi integer in dBm.
+     * typically between -120 and -10
+     * 
+ * + * int32 rssi = 3; + * @return The rssi. + */ + @java.lang.Override + public int getRssi() { + return rssi_; + } + + public static final int POSITION_FIELD_NUMBER = 4; + private Traj.GNSSPosition position_; + /** + *
+     * returned position
+     * 
+ * + * optional .GNSSPosition position = 4; + * @return Whether the position field is set. + */ + @java.lang.Override + public boolean hasPosition() { + return ((bitField0_ & 0x00000001) != 0); + } + /** + *
+     * returned position
+     * 
+ * + * optional .GNSSPosition position = 4; + * @return The position. + */ + @java.lang.Override + public Traj.GNSSPosition getPosition() { + return position_ == null ? Traj.GNSSPosition.getDefaultInstance() : position_; + } + /** + *
+     * returned position
+     * 
+ * + * optional .GNSSPosition position = 4; + */ + @java.lang.Override + public Traj.GNSSPositionOrBuilder getPositionOrBuilder() { + return position_ == null ? Traj.GNSSPosition.getDefaultInstance() : position_; } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; @@ -7508,16 +15610,25 @@ public final boolean isInitialized() { return true; } + @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (relativeTimestamp_ != 0L) { output.writeInt64(1, relativeTimestamp_); } - if (pressure_ != 0F) { - output.writeFloat(2, pressure_); + if (mac_ != 0L) { + output.writeInt64(2, mac_); + } + if (rssi_ != 0) { + output.writeInt32(3, rssi_); } + if (((bitField0_ & 0x00000001) != 0)) { + output.writeMessage(4, getPosition()); + } + unknownFields.writeTo(output); } + @java.lang.Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; @@ -7527,105 +15638,135 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeInt64Size(1, relativeTimestamp_); } - if (pressure_ != 0F) { + if (mac_ != 0L) { size += com.google.protobuf.CodedOutputStream - .computeFloatSize(2, pressure_); + .computeInt64Size(2, mac_); + } + if (rssi_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(3, rssi_); + } + if (((bitField0_ & 0x00000001) != 0)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(4, getPosition()); } + size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } - private static final long serialVersionUID = 0L; - @Override - public boolean equals(final Object obj) { + @java.lang.Override + public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof Pressure_Sample)) { + if (!(obj instanceof Traj.RFScan)) { return super.equals(obj); } - Pressure_Sample other = (Pressure_Sample) obj; + Traj.RFScan other = (Traj.RFScan) obj; - boolean result = true; - result = result && (getRelativeTimestamp() - == other.getRelativeTimestamp()); - result = result && ( - Float.floatToIntBits(getPressure()) - == Float.floatToIntBits( - other.getPressure())); - return result; + if (getRelativeTimestamp() + != other.getRelativeTimestamp()) return false; + if (getMac() + != other.getMac()) return false; + if (getRssi() + != other.getRssi()) return false; + if (hasPosition() != other.hasPosition()) return false; + if (hasPosition()) { + if (!getPosition() + .equals(other.getPosition())) return false; + } + if (!unknownFields.equals(other.unknownFields)) return false; + return true; } - @Override + @java.lang.Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; - hash = (19 * hash) + getDescriptorForType().hashCode(); + hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; hash = (53 * hash) + com.google.protobuf.Internal.hashLong( getRelativeTimestamp()); - hash = (37 * hash) + PRESSURE_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getPressure()); + hash = (37 * hash) + MAC_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getMac()); + hash = (37 * hash) + RSSI_FIELD_NUMBER; + hash = (53 * hash) + getRssi(); + if (hasPosition()) { + hash = (37 * hash) + POSITION_FIELD_NUMBER; + hash = (53 * hash) + getPosition().hashCode(); + } hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } - public static Pressure_Sample parseFrom( + public static Traj.RFScan parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.RFScan parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.RFScan parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Pressure_Sample parseFrom( + public static Traj.RFScan parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Pressure_Sample parseFrom(byte[] data) + public static Traj.RFScan parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Pressure_Sample parseFrom( + public static Traj.RFScan parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Pressure_Sample parseFrom(java.io.InputStream input) + public static Traj.RFScan parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Pressure_Sample parseFrom( + public static Traj.RFScan parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static Pressure_Sample parseDelimitedFrom(java.io.InputStream input) + public static Traj.RFScan parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static Pressure_Sample parseDelimitedFrom( + public static Traj.RFScan parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static Pressure_Sample parseFrom( + public static Traj.RFScan parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Pressure_Sample parseFrom( + public static Traj.RFScan parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -7633,44 +15774,47 @@ public static Pressure_Sample parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } + @java.lang.Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(Pressure_Sample prototype) { + public static Builder newBuilder(Traj.RFScan prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } - @Override + @java.lang.Override protected Builder newBuilderForType( com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** - * Protobuf type {@code Pressure_Sample} + * Protobuf type {@code RFScan} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:Pressure_Sample) - Pressure_SampleOrBuilder { + // @@protoc_insertion_point(builder_implements:RFScan) + Traj.RFScanOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Pressure_Sample_descriptor; + return Traj.internal_static_RFScan_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Pressure_Sample_fieldAccessorTable + return Traj.internal_static_RFScan_fieldAccessorTable .ensureFieldAccessorsInitialized( - Pressure_Sample.class, Builder.class); + Traj.RFScan.class, Traj.RFScan.Builder.class); } - // Construct using Traj.Pressure_Sample.newBuilder() + // Construct using Traj.RFScan.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -7683,268 +15827,575 @@ private Builder( private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessageV3 .alwaysUseFieldBuilders) { + getPositionFieldBuilder(); } } + @java.lang.Override public Builder clear() { super.clear(); relativeTimestamp_ = 0L; - pressure_ = 0F; + mac_ = 0L; + + rssi_ = 0; + if (positionBuilder_ == null) { + position_ = null; + } else { + positionBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); return this; } + @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return Traj.internal_static_Pressure_Sample_descriptor; + return Traj.internal_static_RFScan_descriptor; } - public Pressure_Sample getDefaultInstanceForType() { - return Pressure_Sample.getDefaultInstance(); + @java.lang.Override + public Traj.RFScan getDefaultInstanceForType() { + return Traj.RFScan.getDefaultInstance(); } - public Pressure_Sample build() { - Pressure_Sample result = buildPartial(); + @java.lang.Override + public Traj.RFScan build() { + Traj.RFScan result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } - public Pressure_Sample buildPartial() { - Pressure_Sample result = new Pressure_Sample(this); + @java.lang.Override + public Traj.RFScan buildPartial() { + Traj.RFScan result = new Traj.RFScan(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; result.relativeTimestamp_ = relativeTimestamp_; - result.pressure_ = pressure_; + result.mac_ = mac_; + result.rssi_ = rssi_; + if (((from_bitField0_ & 0x00000001) != 0)) { + if (positionBuilder_ == null) { + result.position_ = position_; + } else { + result.position_ = positionBuilder_.build(); + } + to_bitField0_ |= 0x00000001; + } + result.bitField0_ = to_bitField0_; onBuilt(); return result; } + @java.lang.Override public Builder clone() { - return (Builder) super.clone(); + return super.clone(); } + @java.lang.Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); + java.lang.Object value) { + return super.setField(field, value); } + @java.lang.Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); + return super.clearField(field); } + @java.lang.Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); + return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); + java.lang.Object value) { + return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof Pressure_Sample) { - return mergeFrom((Pressure_Sample)other); + if (other instanceof Traj.RFScan) { + return mergeFrom((Traj.RFScan)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(Pressure_Sample other) { - if (other == Pressure_Sample.getDefaultInstance()) return this; + public Builder mergeFrom(Traj.RFScan other) { + if (other == Traj.RFScan.getDefaultInstance()) return this; if (other.getRelativeTimestamp() != 0L) { setRelativeTimestamp(other.getRelativeTimestamp()); } - if (other.getPressure() != 0F) { - setPressure(other.getPressure()); + if (other.getMac() != 0L) { + setMac(other.getMac()); + } + if (other.getRssi() != 0) { + setRssi(other.getRssi()); + } + if (other.hasPosition()) { + mergePosition(other.getPosition()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + Traj.RFScan parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (Traj.RFScan) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } } + return this; + } + private int bitField0_; + + private long relativeTimestamp_ ; + /** + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. + */ + @java.lang.Override + public long getRelativeTimestamp() { + return relativeTimestamp_; + } + /** + * int64 relative_timestamp = 1; + * @param value The relativeTimestamp to set. + * @return This builder for chaining. + */ + public Builder setRelativeTimestamp(long value) { + + relativeTimestamp_ = value; + onChanged(); + return this; + } + /** + * int64 relative_timestamp = 1; + * @return This builder for chaining. + */ + public Builder clearRelativeTimestamp() { + + relativeTimestamp_ = 0L; + onChanged(); + return this; + } + + private long mac_ ; + /** + *
+       * Integer encoding of the hex mac address (BSSID)
+       * e.g. 207394925843984
+       * 
+ * + * int64 mac = 2; + * @return The mac. + */ + @java.lang.Override + public long getMac() { + return mac_; + } + /** + *
+       * Integer encoding of the hex mac address (BSSID)
+       * e.g. 207394925843984
+       * 
+ * + * int64 mac = 2; + * @param value The mac to set. + * @return This builder for chaining. + */ + public Builder setMac(long value) { + + mac_ = value; + onChanged(); + return this; + } + /** + *
+       * Integer encoding of the hex mac address (BSSID)
+       * e.g. 207394925843984
+       * 
+ * + * int64 mac = 2; + * @return This builder for chaining. + */ + public Builder clearMac() { + + mac_ = 0L; onChanged(); return this; } - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Pressure_Sample parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (Pressure_Sample) e.getUnfinishedMessage(); - throw e.unwrapIOException(); - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - - private long relativeTimestamp_ ; + private int rssi_ ; /** - * optional int64 relative_timestamp = 1; + *
+       * rssi integer in dBm.
+       * typically between -120 and -10
+       * 
+ * + * int32 rssi = 3; + * @return The rssi. */ - public long getRelativeTimestamp() { - return relativeTimestamp_; + @java.lang.Override + public int getRssi() { + return rssi_; } /** - * optional int64 relative_timestamp = 1; + *
+       * rssi integer in dBm.
+       * typically between -120 and -10
+       * 
+ * + * int32 rssi = 3; + * @param value The rssi to set. + * @return This builder for chaining. */ - public Builder setRelativeTimestamp(long value) { + public Builder setRssi(int value) { - relativeTimestamp_ = value; + rssi_ = value; onChanged(); return this; } /** - * optional int64 relative_timestamp = 1; + *
+       * rssi integer in dBm.
+       * typically between -120 and -10
+       * 
+ * + * int32 rssi = 3; + * @return This builder for chaining. */ - public Builder clearRelativeTimestamp() { + public Builder clearRssi() { - relativeTimestamp_ = 0L; + rssi_ = 0; onChanged(); return this; } - private float pressure_ ; + private Traj.GNSSPosition position_; + private com.google.protobuf.SingleFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder> positionBuilder_; /** *
-       * mbar
+       * returned position
        * 
* - * optional float pressure = 2; + * optional .GNSSPosition position = 4; + * @return Whether the position field is set. */ - public float getPressure() { - return pressure_; + public boolean hasPosition() { + return ((bitField0_ & 0x00000001) != 0); } /** *
-       * mbar
+       * returned position
        * 
* - * optional float pressure = 2; + * optional .GNSSPosition position = 4; + * @return The position. */ - public Builder setPressure(float value) { - - pressure_ = value; - onChanged(); + public Traj.GNSSPosition getPosition() { + if (positionBuilder_ == null) { + return position_ == null ? Traj.GNSSPosition.getDefaultInstance() : position_; + } else { + return positionBuilder_.getMessage(); + } + } + /** + *
+       * returned position
+       * 
+ * + * optional .GNSSPosition position = 4; + */ + public Builder setPosition(Traj.GNSSPosition value) { + if (positionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + position_ = value; + onChanged(); + } else { + positionBuilder_.setMessage(value); + } + bitField0_ |= 0x00000001; return this; } /** *
-       * mbar
+       * returned position
        * 
* - * optional float pressure = 2; + * optional .GNSSPosition position = 4; */ - public Builder clearPressure() { - - pressure_ = 0F; - onChanged(); + public Builder setPosition( + Traj.GNSSPosition.Builder builderForValue) { + if (positionBuilder_ == null) { + position_ = builderForValue.build(); + onChanged(); + } else { + positionBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000001; + return this; + } + /** + *
+       * returned position
+       * 
+ * + * optional .GNSSPosition position = 4; + */ + public Builder mergePosition(Traj.GNSSPosition value) { + if (positionBuilder_ == null) { + if (((bitField0_ & 0x00000001) != 0) && + position_ != null && + position_ != Traj.GNSSPosition.getDefaultInstance()) { + position_ = + Traj.GNSSPosition.newBuilder(position_).mergeFrom(value).buildPartial(); + } else { + position_ = value; + } + onChanged(); + } else { + positionBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000001; + return this; + } + /** + *
+       * returned position
+       * 
+ * + * optional .GNSSPosition position = 4; + */ + public Builder clearPosition() { + if (positionBuilder_ == null) { + position_ = null; + onChanged(); + } else { + positionBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); return this; } + /** + *
+       * returned position
+       * 
+ * + * optional .GNSSPosition position = 4; + */ + public Traj.GNSSPosition.Builder getPositionBuilder() { + bitField0_ |= 0x00000001; + onChanged(); + return getPositionFieldBuilder().getBuilder(); + } + /** + *
+       * returned position
+       * 
+ * + * optional .GNSSPosition position = 4; + */ + public Traj.GNSSPositionOrBuilder getPositionOrBuilder() { + if (positionBuilder_ != null) { + return positionBuilder_.getMessageOrBuilder(); + } else { + return position_ == null ? + Traj.GNSSPosition.getDefaultInstance() : position_; + } + } + /** + *
+       * returned position
+       * 
+ * + * optional .GNSSPosition position = 4; + */ + private com.google.protobuf.SingleFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder> + getPositionFieldBuilder() { + if (positionBuilder_ == null) { + positionBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< + Traj.GNSSPosition, Traj.GNSSPosition.Builder, Traj.GNSSPositionOrBuilder>( + getPosition(), + getParentForChildren(), + isClean()); + position_ = null; + } + return positionBuilder_; + } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.setUnknownFields(unknownFields); } + @java.lang.Override public final Builder mergeUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:Pressure_Sample) + // @@protoc_insertion_point(builder_scope:RFScan) } - // @@protoc_insertion_point(class_scope:Pressure_Sample) - private static final Pressure_Sample DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:RFScan) + private static final Traj.RFScan DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new Pressure_Sample(); + DEFAULT_INSTANCE = new Traj.RFScan(); } - public static Pressure_Sample getDefaultInstance() { + public static Traj.RFScan getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - public Pressure_Sample parsePartialFrom( + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public RFScan parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { - return new Pressure_Sample(input, extensionRegistry); + return new RFScan(input, extensionRegistry); } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } - @Override - public com.google.protobuf.Parser getParserForType() { + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { return PARSER; } - public Pressure_Sample getDefaultInstanceForType() { + @java.lang.Override + public Traj.RFScan getDefaultInstanceForType() { return DEFAULT_INSTANCE; } } - public interface Light_SampleOrBuilder extends - // @@protoc_insertion_point(interface_extends:Light_Sample) + public interface WiFiRTTReadingOrBuilder extends + // @@protoc_insertion_point(interface_extends:WiFiRTTReading) com.google.protobuf.MessageOrBuilder { /** - * optional int64 relative_timestamp = 1; + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. */ long getRelativeTimestamp(); /** *
-     * lux
+     * cm
+     * Integer encoding of the hex mac address (BSSID)
+     * e.g. 207394925843984
      * 
* - * optional float light = 2; + * int64 mac = 2; + * @return The mac. */ - float getLight(); + long getMac(); + + /** + *
+     * in mm
+     * 
+ * + * float distance = 3; + * @return The distance. + */ + float getDistance(); + + /** + *
+     * in mm
+     * 
+ * + * float distance_std = 4; + * @return The distanceStd. + */ + float getDistanceStd(); + + /** + *
+     * rssi integer in dBm.
+     * typically between -120 and -10
+     * 
+ * + * int32 rssi = 5; + * @return The rssi. + */ + int getRssi(); } /** - * Protobuf type {@code Light_Sample} + * Protobuf type {@code WiFiRTTReading} */ - public static final class Light_Sample extends + public static final class WiFiRTTReading extends com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:Light_Sample) - Light_SampleOrBuilder { - // Use Light_Sample.newBuilder() to construct. - private Light_Sample(com.google.protobuf.GeneratedMessageV3.Builder builder) { + // @@protoc_insertion_point(message_implements:WiFiRTTReading) + WiFiRTTReadingOrBuilder { + private static final long serialVersionUID = 0L; + // Use WiFiRTTReading.newBuilder() to construct. + private WiFiRTTReading(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } - private Light_Sample() { - relativeTimestamp_ = 0L; - light_ = 0F; + private WiFiRTTReading() { + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new WiFiRTTReading(); } - @Override + @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + return this.unknownFields; } - private Light_Sample( + private WiFiRTTReading( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); - int mutable_bitField0_ = 0; + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { @@ -7953,68 +16404,141 @@ private Light_Sample( case 0: done = true; break; - default: { - if (!input.skipField(tag)) { - done = true; - } - break; - } case 8: { relativeTimestamp_ = input.readInt64(); break; } - case 21: { + case 16: { - light_ = input.readFloat(); + mac_ = input.readInt64(); + break; + } + case 29: { + + distance_ = input.readFloat(); + break; + } + case 37: { + + distanceStd_ = input.readFloat(); + break; + } + case 40: { + + rssi_ = input.readInt32(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { + this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Light_Sample_descriptor; + return Traj.internal_static_WiFiRTTReading_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Light_Sample_fieldAccessorTable + return Traj.internal_static_WiFiRTTReading_fieldAccessorTable .ensureFieldAccessorsInitialized( - Light_Sample.class, Builder.class); + Traj.WiFiRTTReading.class, Traj.WiFiRTTReading.Builder.class); } public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; private long relativeTimestamp_; /** - * optional int64 relative_timestamp = 1; + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. */ + @java.lang.Override public long getRelativeTimestamp() { return relativeTimestamp_; } - public static final int LIGHT_FIELD_NUMBER = 2; - private float light_; + public static final int MAC_FIELD_NUMBER = 2; + private long mac_; /** *
-     * lux
+     * cm
+     * Integer encoding of the hex mac address (BSSID)
+     * e.g. 207394925843984
      * 
* - * optional float light = 2; + * int64 mac = 2; + * @return The mac. */ - public float getLight() { - return light_; + @java.lang.Override + public long getMac() { + return mac_; + } + + public static final int DISTANCE_FIELD_NUMBER = 3; + private float distance_; + /** + *
+     * in mm
+     * 
+ * + * float distance = 3; + * @return The distance. + */ + @java.lang.Override + public float getDistance() { + return distance_; + } + + public static final int DISTANCE_STD_FIELD_NUMBER = 4; + private float distanceStd_; + /** + *
+     * in mm
+     * 
+ * + * float distance_std = 4; + * @return The distanceStd. + */ + @java.lang.Override + public float getDistanceStd() { + return distanceStd_; + } + + public static final int RSSI_FIELD_NUMBER = 5; + private int rssi_; + /** + *
+     * rssi integer in dBm.
+     * typically between -120 and -10
+     * 
+ * + * int32 rssi = 5; + * @return The rssi. + */ + @java.lang.Override + public int getRssi() { + return rssi_; } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; @@ -8024,16 +16548,28 @@ public final boolean isInitialized() { return true; } + @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { if (relativeTimestamp_ != 0L) { output.writeInt64(1, relativeTimestamp_); } - if (light_ != 0F) { - output.writeFloat(2, light_); + if (mac_ != 0L) { + output.writeInt64(2, mac_); + } + if (java.lang.Float.floatToRawIntBits(distance_) != 0) { + output.writeFloat(3, distance_); } + if (java.lang.Float.floatToRawIntBits(distanceStd_) != 0) { + output.writeFloat(4, distanceStd_); + } + if (rssi_ != 0) { + output.writeInt32(5, rssi_); + } + unknownFields.writeTo(output); } + @java.lang.Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; @@ -8043,105 +16579,142 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeInt64Size(1, relativeTimestamp_); } - if (light_ != 0F) { + if (mac_ != 0L) { + size += com.google.protobuf.CodedOutputStream + .computeInt64Size(2, mac_); + } + if (java.lang.Float.floatToRawIntBits(distance_) != 0) { size += com.google.protobuf.CodedOutputStream - .computeFloatSize(2, light_); + .computeFloatSize(3, distance_); + } + if (java.lang.Float.floatToRawIntBits(distanceStd_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeFloatSize(4, distanceStd_); + } + if (rssi_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(5, rssi_); } + size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } - private static final long serialVersionUID = 0L; - @Override - public boolean equals(final Object obj) { + @java.lang.Override + public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof Light_Sample)) { + if (!(obj instanceof Traj.WiFiRTTReading)) { return super.equals(obj); } - Light_Sample other = (Light_Sample) obj; - - boolean result = true; - result = result && (getRelativeTimestamp() - == other.getRelativeTimestamp()); - result = result && ( - Float.floatToIntBits(getLight()) - == Float.floatToIntBits( - other.getLight())); - return result; + Traj.WiFiRTTReading other = (Traj.WiFiRTTReading) obj; + + if (getRelativeTimestamp() + != other.getRelativeTimestamp()) return false; + if (getMac() + != other.getMac()) return false; + if (java.lang.Float.floatToIntBits(getDistance()) + != java.lang.Float.floatToIntBits( + other.getDistance())) return false; + if (java.lang.Float.floatToIntBits(getDistanceStd()) + != java.lang.Float.floatToIntBits( + other.getDistanceStd())) return false; + if (getRssi() + != other.getRssi()) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; } - @Override + @java.lang.Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; - hash = (19 * hash) + getDescriptorForType().hashCode(); + hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; hash = (53 * hash) + com.google.protobuf.Internal.hashLong( getRelativeTimestamp()); - hash = (37 * hash) + LIGHT_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getLight()); + hash = (37 * hash) + MAC_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getMac()); + hash = (37 * hash) + DISTANCE_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getDistance()); + hash = (37 * hash) + DISTANCE_STD_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getDistanceStd()); + hash = (37 * hash) + RSSI_FIELD_NUMBER; + hash = (53 * hash) + getRssi(); hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } - - public static Light_Sample parseFrom( + + public static Traj.WiFiRTTReading parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.WiFiRTTReading parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.WiFiRTTReading parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Light_Sample parseFrom( + public static Traj.WiFiRTTReading parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Light_Sample parseFrom(byte[] data) + public static Traj.WiFiRTTReading parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Light_Sample parseFrom( + public static Traj.WiFiRTTReading parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Light_Sample parseFrom(java.io.InputStream input) + public static Traj.WiFiRTTReading parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Light_Sample parseFrom( + public static Traj.WiFiRTTReading parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static Light_Sample parseDelimitedFrom(java.io.InputStream input) + public static Traj.WiFiRTTReading parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static Light_Sample parseDelimitedFrom( + public static Traj.WiFiRTTReading parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static Light_Sample parseFrom( + public static Traj.WiFiRTTReading parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Light_Sample parseFrom( + public static Traj.WiFiRTTReading parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -8149,44 +16722,47 @@ public static Light_Sample parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } + @java.lang.Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(Light_Sample prototype) { + public static Builder newBuilder(Traj.WiFiRTTReading prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } - @Override + @java.lang.Override protected Builder newBuilderForType( com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** - * Protobuf type {@code Light_Sample} + * Protobuf type {@code WiFiRTTReading} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:Light_Sample) - Light_SampleOrBuilder { + // @@protoc_insertion_point(builder_implements:WiFiRTTReading) + Traj.WiFiRTTReadingOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Light_Sample_descriptor; + return Traj.internal_static_WiFiRTTReading_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Light_Sample_fieldAccessorTable + return Traj.internal_static_WiFiRTTReading_fieldAccessorTable .ensureFieldAccessorsInitialized( - Light_Sample.class, Builder.class); + Traj.WiFiRTTReading.class, Traj.WiFiRTTReading.Builder.class); } - // Construct using Traj.Light_Sample.newBuilder() + // Construct using Traj.WiFiRTTReading.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -8201,100 +16777,133 @@ private void maybeForceBuilderInitialization() { .alwaysUseFieldBuilders) { } } + @java.lang.Override public Builder clear() { super.clear(); relativeTimestamp_ = 0L; - light_ = 0F; + mac_ = 0L; + + distance_ = 0F; + + distanceStd_ = 0F; + + rssi_ = 0; return this; } + @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return Traj.internal_static_Light_Sample_descriptor; + return Traj.internal_static_WiFiRTTReading_descriptor; } - public Light_Sample getDefaultInstanceForType() { - return Light_Sample.getDefaultInstance(); + @java.lang.Override + public Traj.WiFiRTTReading getDefaultInstanceForType() { + return Traj.WiFiRTTReading.getDefaultInstance(); } - public Light_Sample build() { - Light_Sample result = buildPartial(); + @java.lang.Override + public Traj.WiFiRTTReading build() { + Traj.WiFiRTTReading result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } - public Light_Sample buildPartial() { - Light_Sample result = new Light_Sample(this); + @java.lang.Override + public Traj.WiFiRTTReading buildPartial() { + Traj.WiFiRTTReading result = new Traj.WiFiRTTReading(this); result.relativeTimestamp_ = relativeTimestamp_; - result.light_ = light_; + result.mac_ = mac_; + result.distance_ = distance_; + result.distanceStd_ = distanceStd_; + result.rssi_ = rssi_; onBuilt(); return result; } + @java.lang.Override public Builder clone() { - return (Builder) super.clone(); + return super.clone(); } + @java.lang.Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); + java.lang.Object value) { + return super.setField(field, value); } + @java.lang.Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); + return super.clearField(field); } + @java.lang.Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); + return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); + java.lang.Object value) { + return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof Light_Sample) { - return mergeFrom((Light_Sample)other); + if (other instanceof Traj.WiFiRTTReading) { + return mergeFrom((Traj.WiFiRTTReading)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(Light_Sample other) { - if (other == Light_Sample.getDefaultInstance()) return this; + public Builder mergeFrom(Traj.WiFiRTTReading other) { + if (other == Traj.WiFiRTTReading.getDefaultInstance()) return this; if (other.getRelativeTimestamp() != 0L) { setRelativeTimestamp(other.getRelativeTimestamp()); } - if (other.getLight() != 0F) { - setLight(other.getLight()); + if (other.getMac() != 0L) { + setMac(other.getMac()); } + if (other.getDistance() != 0F) { + setDistance(other.getDistance()); + } + if (other.getDistanceStd() != 0F) { + setDistanceStd(other.getDistanceStd()); + } + if (other.getRssi() != 0) { + setRssi(other.getRssi()); + } + this.mergeUnknownFields(other.unknownFields); onChanged(); return this; } + @java.lang.Override public final boolean isInitialized() { return true; } + @java.lang.Override public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - Light_Sample parsedMessage = null; + Traj.WiFiRTTReading parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (Light_Sample) e.getUnfinishedMessage(); + parsedMessage = (Traj.WiFiRTTReading) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -8306,13 +16915,17 @@ public Builder mergeFrom( private long relativeTimestamp_ ; /** - * optional int64 relative_timestamp = 1; + * int64 relative_timestamp = 1; + * @return The relativeTimestamp. */ + @java.lang.Override public long getRelativeTimestamp() { return relativeTimestamp_; } /** - * optional int64 relative_timestamp = 1; + * int64 relative_timestamp = 1; + * @param value The relativeTimestamp to set. + * @return This builder for chaining. */ public Builder setRelativeTimestamp(long value) { @@ -8321,7 +16934,8 @@ public Builder setRelativeTimestamp(long value) { return this; } /** - * optional int64 relative_timestamp = 1; + * int64 relative_timestamp = 1; + * @return This builder for chaining. */ public Builder clearRelativeTimestamp() { @@ -8330,197 +16944,332 @@ public Builder clearRelativeTimestamp() { return this; } - private float light_ ; + private long mac_ ; /** *
-       * lux
+       * cm
+       * Integer encoding of the hex mac address (BSSID)
+       * e.g. 207394925843984
        * 
* - * optional float light = 2; + * int64 mac = 2; + * @return The mac. */ - public float getLight() { - return light_; + @java.lang.Override + public long getMac() { + return mac_; } /** *
-       * lux
+       * cm
+       * Integer encoding of the hex mac address (BSSID)
+       * e.g. 207394925843984
        * 
* - * optional float light = 2; + * int64 mac = 2; + * @param value The mac to set. + * @return This builder for chaining. */ - public Builder setLight(float value) { + public Builder setMac(long value) { - light_ = value; + mac_ = value; onChanged(); return this; } /** *
-       * lux
+       * cm
+       * Integer encoding of the hex mac address (BSSID)
+       * e.g. 207394925843984
        * 
* - * optional float light = 2; + * int64 mac = 2; + * @return This builder for chaining. */ - public Builder clearLight() { + public Builder clearMac() { - light_ = 0F; + mac_ = 0L; + onChanged(); + return this; + } + + private float distance_ ; + /** + *
+       * in mm
+       * 
+ * + * float distance = 3; + * @return The distance. + */ + @java.lang.Override + public float getDistance() { + return distance_; + } + /** + *
+       * in mm
+       * 
+ * + * float distance = 3; + * @param value The distance to set. + * @return This builder for chaining. + */ + public Builder setDistance(float value) { + + distance_ = value; + onChanged(); + return this; + } + /** + *
+       * in mm
+       * 
+ * + * float distance = 3; + * @return This builder for chaining. + */ + public Builder clearDistance() { + + distance_ = 0F; + onChanged(); + return this; + } + + private float distanceStd_ ; + /** + *
+       * in mm
+       * 
+ * + * float distance_std = 4; + * @return The distanceStd. + */ + @java.lang.Override + public float getDistanceStd() { + return distanceStd_; + } + /** + *
+       * in mm
+       * 
+ * + * float distance_std = 4; + * @param value The distanceStd to set. + * @return This builder for chaining. + */ + public Builder setDistanceStd(float value) { + + distanceStd_ = value; + onChanged(); + return this; + } + /** + *
+       * in mm
+       * 
+ * + * float distance_std = 4; + * @return This builder for chaining. + */ + public Builder clearDistanceStd() { + + distanceStd_ = 0F; + onChanged(); + return this; + } + + private int rssi_ ; + /** + *
+       * rssi integer in dBm.
+       * typically between -120 and -10
+       * 
+ * + * int32 rssi = 5; + * @return The rssi. + */ + @java.lang.Override + public int getRssi() { + return rssi_; + } + /** + *
+       * rssi integer in dBm.
+       * typically between -120 and -10
+       * 
+ * + * int32 rssi = 5; + * @param value The rssi to set. + * @return This builder for chaining. + */ + public Builder setRssi(int value) { + + rssi_ = value; + onChanged(); + return this; + } + /** + *
+       * rssi integer in dBm.
+       * typically between -120 and -10
+       * 
+ * + * int32 rssi = 5; + * @return This builder for chaining. + */ + public Builder clearRssi() { + + rssi_ = 0; onChanged(); return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.setUnknownFields(unknownFields); } + @java.lang.Override public final Builder mergeUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:Light_Sample) + // @@protoc_insertion_point(builder_scope:WiFiRTTReading) } - // @@protoc_insertion_point(class_scope:Light_Sample) - private static final Light_Sample DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:WiFiRTTReading) + private static final Traj.WiFiRTTReading DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new Light_Sample(); + DEFAULT_INSTANCE = new Traj.WiFiRTTReading(); } - public static Light_Sample getDefaultInstance() { + public static Traj.WiFiRTTReading getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - public Light_Sample parsePartialFrom( + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public WiFiRTTReading parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { - return new Light_Sample(input, extensionRegistry); + return new WiFiRTTReading(input, extensionRegistry); } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } - @Override - public com.google.protobuf.Parser getParserForType() { + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { return PARSER; } - public Light_Sample getDefaultInstanceForType() { + @java.lang.Override + public Traj.WiFiRTTReading getDefaultInstanceForType() { return DEFAULT_INSTANCE; } } - public interface GNSS_SampleOrBuilder extends - // @@protoc_insertion_point(interface_extends:GNSS_Sample) + public interface WiFiAPDataOrBuilder extends + // @@protoc_insertion_point(interface_extends:WiFiAPData) com.google.protobuf.MessageOrBuilder { - /** - * optional int64 relative_timestamp = 1; - */ - long getRelativeTimestamp(); - - /** - *
-     * degrees (minimum 6 significant figures)
-     * latitude between -90 and 90
-     * 
- * - * optional float latitude = 2; - */ - float getLatitude(); - /** *
-     * longitude between -180 and 180
+     * Integer encoding of the hex mac address (BSSID)
+     * e.g. 207394925843984
      * 
* - * optional float longitude = 3; + * int64 mac = 1; + * @return The mac. */ - float getLongitude(); + long getMac(); /** *
-     *metres
+     * E.g. 'Eduroam' or 'Starbucks_free_wifi'
      * 
* - * optional float altitude = 4; + * string ssid = 2; + * @return The ssid. */ - float getAltitude(); - + java.lang.String getSsid(); /** *
-     * metres
+     * E.g. 'Eduroam' or 'Starbucks_free_wifi'
      * 
* - * optional float accuracy = 5; + * string ssid = 2; + * @return The bytes for ssid. */ - float getAccuracy(); + com.google.protobuf.ByteString + getSsidBytes(); /** *
-     * m/s
+     * Typically 2.4GHz or 5GHz
      * 
* - * optional float speed = 6; + * int64 frequency = 3; + * @return The frequency. */ - float getSpeed(); + long getFrequency(); /** *
-     * e.g 'gps' or 'network'
-     * 
- * - * optional string provider = 7; - */ - String getProvider(); - /** - *
-     * e.g 'gps' or 'network'
+     * Flag to indicate if the AP supports RTT measurements
      * 
* - * optional string provider = 7; + * bool rtt_enabled = 4; + * @return The rttEnabled. */ - com.google.protobuf.ByteString - getProviderBytes(); + boolean getRttEnabled(); } /** - * Protobuf type {@code GNSS_Sample} + * Protobuf type {@code WiFiAPData} */ - public static final class GNSS_Sample extends + public static final class WiFiAPData extends com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:GNSS_Sample) - GNSS_SampleOrBuilder { - // Use GNSS_Sample.newBuilder() to construct. - private GNSS_Sample(com.google.protobuf.GeneratedMessageV3.Builder builder) { + // @@protoc_insertion_point(message_implements:WiFiAPData) + WiFiAPDataOrBuilder { + private static final long serialVersionUID = 0L; + // Use WiFiAPData.newBuilder() to construct. + private WiFiAPData(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } - private GNSS_Sample() { - relativeTimestamp_ = 0L; - latitude_ = 0F; - longitude_ = 0F; - altitude_ = 0F; - accuracy_ = 0F; - speed_ = 0F; - provider_ = ""; + private WiFiAPData() { + ssid_ = ""; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new WiFiAPData(); } - @Override + @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + return this.unknownFields; } - private GNSS_Sample( + private WiFiAPData( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); - int mutable_bitField0_ = 0; + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { @@ -8529,189 +17278,155 @@ private GNSS_Sample( case 0: done = true; break; - default: { - if (!input.skipField(tag)) { - done = true; - } - break; - } case 8: { - relativeTimestamp_ = input.readInt64(); - break; - } - case 21: { - - latitude_ = input.readFloat(); - break; - } - case 29: { - - longitude_ = input.readFloat(); + mac_ = input.readInt64(); break; } - case 37: { + case 18: { + java.lang.String s = input.readStringRequireUtf8(); - altitude_ = input.readFloat(); + ssid_ = s; break; } - case 45: { + case 24: { - accuracy_ = input.readFloat(); + frequency_ = input.readInt64(); break; } - case 53: { + case 32: { - speed_ = input.readFloat(); + rttEnabled_ = input.readBool(); break; } - case 58: { - String s = input.readStringRequireUtf8(); - - provider_ = s; + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { + this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_GNSS_Sample_descriptor; - } - - protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internalGetFieldAccessorTable() { - return Traj.internal_static_GNSS_Sample_fieldAccessorTable - .ensureFieldAccessorsInitialized( - GNSS_Sample.class, Builder.class); - } - - public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; - private long relativeTimestamp_; - /** - * optional int64 relative_timestamp = 1; - */ - public long getRelativeTimestamp() { - return relativeTimestamp_; - } - - public static final int LATITUDE_FIELD_NUMBER = 2; - private float latitude_; - /** - *
-     * degrees (minimum 6 significant figures)
-     * latitude between -90 and 90
-     * 
- * - * optional float latitude = 2; - */ - public float getLatitude() { - return latitude_; - } - - public static final int LONGITUDE_FIELD_NUMBER = 3; - private float longitude_; - /** - *
-     * longitude between -180 and 180
-     * 
- * - * optional float longitude = 3; - */ - public float getLongitude() { - return longitude_; - } - - public static final int ALTITUDE_FIELD_NUMBER = 4; - private float altitude_; - /** - *
-     *metres
-     * 
- * - * optional float altitude = 4; - */ - public float getAltitude() { - return altitude_; - } - - public static final int ACCURACY_FIELD_NUMBER = 5; - private float accuracy_; - /** - *
-     * metres
-     * 
- * - * optional float accuracy = 5; - */ - public float getAccuracy() { - return accuracy_; + return Traj.internal_static_WiFiAPData_descriptor; } - public static final int SPEED_FIELD_NUMBER = 6; - private float speed_; + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return Traj.internal_static_WiFiAPData_fieldAccessorTable + .ensureFieldAccessorsInitialized( + Traj.WiFiAPData.class, Traj.WiFiAPData.Builder.class); + } + + public static final int MAC_FIELD_NUMBER = 1; + private long mac_; /** *
-     * m/s
+     * Integer encoding of the hex mac address (BSSID)
+     * e.g. 207394925843984
      * 
* - * optional float speed = 6; + * int64 mac = 1; + * @return The mac. */ - public float getSpeed() { - return speed_; + @java.lang.Override + public long getMac() { + return mac_; } - public static final int PROVIDER_FIELD_NUMBER = 7; - private volatile Object provider_; + public static final int SSID_FIELD_NUMBER = 2; + private volatile java.lang.Object ssid_; /** *
-     * e.g 'gps' or 'network'
+     * E.g. 'Eduroam' or 'Starbucks_free_wifi'
      * 
* - * optional string provider = 7; + * string ssid = 2; + * @return The ssid. */ - public String getProvider() { - Object ref = provider_; - if (ref instanceof String) { - return (String) ref; + @java.lang.Override + public java.lang.String getSsid() { + java.lang.Object ref = ssid_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - provider_ = s; + java.lang.String s = bs.toStringUtf8(); + ssid_ = s; return s; } } /** *
-     * e.g 'gps' or 'network'
+     * E.g. 'Eduroam' or 'Starbucks_free_wifi'
      * 
* - * optional string provider = 7; + * string ssid = 2; + * @return The bytes for ssid. */ + @java.lang.Override public com.google.protobuf.ByteString - getProviderBytes() { - Object ref = provider_; - if (ref instanceof String) { + getSsidBytes() { + java.lang.Object ref = ssid_; + if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - provider_ = b; + (java.lang.String) ref); + ssid_ = b; return b; } else { return (com.google.protobuf.ByteString) ref; } } + public static final int FREQUENCY_FIELD_NUMBER = 3; + private long frequency_; + /** + *
+     * Typically 2.4GHz or 5GHz
+     * 
+ * + * int64 frequency = 3; + * @return The frequency. + */ + @java.lang.Override + public long getFrequency() { + return frequency_; + } + + public static final int RTT_ENABLED_FIELD_NUMBER = 4; + private boolean rttEnabled_; + /** + *
+     * Flag to indicate if the AP supports RTT measurements
+     * 
+ * + * bool rtt_enabled = 4; + * @return The rttEnabled. + */ + @java.lang.Override + public boolean getRttEnabled() { + return rttEnabled_; + } + private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; @@ -8721,190 +17436,158 @@ public final boolean isInitialized() { return true; } + @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (relativeTimestamp_ != 0L) { - output.writeInt64(1, relativeTimestamp_); - } - if (latitude_ != 0F) { - output.writeFloat(2, latitude_); - } - if (longitude_ != 0F) { - output.writeFloat(3, longitude_); - } - if (altitude_ != 0F) { - output.writeFloat(4, altitude_); + if (mac_ != 0L) { + output.writeInt64(1, mac_); } - if (accuracy_ != 0F) { - output.writeFloat(5, accuracy_); + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(ssid_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, ssid_); } - if (speed_ != 0F) { - output.writeFloat(6, speed_); + if (frequency_ != 0L) { + output.writeInt64(3, frequency_); } - if (!getProviderBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 7, provider_); + if (rttEnabled_ != false) { + output.writeBool(4, rttEnabled_); } + unknownFields.writeTo(output); } + @java.lang.Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; size = 0; - if (relativeTimestamp_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(1, relativeTimestamp_); - } - if (latitude_ != 0F) { - size += com.google.protobuf.CodedOutputStream - .computeFloatSize(2, latitude_); - } - if (longitude_ != 0F) { + if (mac_ != 0L) { size += com.google.protobuf.CodedOutputStream - .computeFloatSize(3, longitude_); + .computeInt64Size(1, mac_); } - if (altitude_ != 0F) { - size += com.google.protobuf.CodedOutputStream - .computeFloatSize(4, altitude_); + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(ssid_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, ssid_); } - if (accuracy_ != 0F) { + if (frequency_ != 0L) { size += com.google.protobuf.CodedOutputStream - .computeFloatSize(5, accuracy_); + .computeInt64Size(3, frequency_); } - if (speed_ != 0F) { + if (rttEnabled_ != false) { size += com.google.protobuf.CodedOutputStream - .computeFloatSize(6, speed_); - } - if (!getProviderBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(7, provider_); + .computeBoolSize(4, rttEnabled_); } + size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } - private static final long serialVersionUID = 0L; - @Override - public boolean equals(final Object obj) { + @java.lang.Override + public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof GNSS_Sample)) { + if (!(obj instanceof Traj.WiFiAPData)) { return super.equals(obj); } - GNSS_Sample other = (GNSS_Sample) obj; - - boolean result = true; - result = result && (getRelativeTimestamp() - == other.getRelativeTimestamp()); - result = result && ( - Float.floatToIntBits(getLatitude()) - == Float.floatToIntBits( - other.getLatitude())); - result = result && ( - Float.floatToIntBits(getLongitude()) - == Float.floatToIntBits( - other.getLongitude())); - result = result && ( - Float.floatToIntBits(getAltitude()) - == Float.floatToIntBits( - other.getAltitude())); - result = result && ( - Float.floatToIntBits(getAccuracy()) - == Float.floatToIntBits( - other.getAccuracy())); - result = result && ( - Float.floatToIntBits(getSpeed()) - == Float.floatToIntBits( - other.getSpeed())); - result = result && getProvider() - .equals(other.getProvider()); - return result; - } - - @Override + Traj.WiFiAPData other = (Traj.WiFiAPData) obj; + + if (getMac() + != other.getMac()) return false; + if (!getSsid() + .equals(other.getSsid())) return false; + if (getFrequency() + != other.getFrequency()) return false; + if (getRttEnabled() + != other.getRttEnabled()) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; - hash = (19 * hash) + getDescriptorForType().hashCode(); - hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + MAC_FIELD_NUMBER; hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getRelativeTimestamp()); - hash = (37 * hash) + LATITUDE_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getLatitude()); - hash = (37 * hash) + LONGITUDE_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getLongitude()); - hash = (37 * hash) + ALTITUDE_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getAltitude()); - hash = (37 * hash) + ACCURACY_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getAccuracy()); - hash = (37 * hash) + SPEED_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( - getSpeed()); - hash = (37 * hash) + PROVIDER_FIELD_NUMBER; - hash = (53 * hash) + getProvider().hashCode(); + getMac()); + hash = (37 * hash) + SSID_FIELD_NUMBER; + hash = (53 * hash) + getSsid().hashCode(); + hash = (37 * hash) + FREQUENCY_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + getFrequency()); + hash = (37 * hash) + RTT_ENABLED_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( + getRttEnabled()); hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } - public static GNSS_Sample parseFrom( + public static Traj.WiFiAPData parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.WiFiAPData parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.WiFiAPData parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static GNSS_Sample parseFrom( + public static Traj.WiFiAPData parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static GNSS_Sample parseFrom(byte[] data) + public static Traj.WiFiAPData parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static GNSS_Sample parseFrom( + public static Traj.WiFiAPData parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static GNSS_Sample parseFrom(java.io.InputStream input) + public static Traj.WiFiAPData parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static GNSS_Sample parseFrom( + public static Traj.WiFiAPData parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static GNSS_Sample parseDelimitedFrom(java.io.InputStream input) + public static Traj.WiFiAPData parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static GNSS_Sample parseDelimitedFrom( + public static Traj.WiFiAPData parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static GNSS_Sample parseFrom( + public static Traj.WiFiAPData parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static GNSS_Sample parseFrom( + public static Traj.WiFiAPData parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -8912,44 +17595,47 @@ public static GNSS_Sample parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } + @java.lang.Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(GNSS_Sample prototype) { + public static Builder newBuilder(Traj.WiFiAPData prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } - @Override + @java.lang.Override protected Builder newBuilderForType( com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** - * Protobuf type {@code GNSS_Sample} + * Protobuf type {@code WiFiAPData} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:GNSS_Sample) - GNSS_SampleOrBuilder { + // @@protoc_insertion_point(builder_implements:WiFiAPData) + Traj.WiFiAPDataOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_GNSS_Sample_descriptor; + return Traj.internal_static_WiFiAPData_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_GNSS_Sample_fieldAccessorTable + return Traj.internal_static_WiFiAPData_fieldAccessorTable .ensureFieldAccessorsInitialized( - GNSS_Sample.class, Builder.class); + Traj.WiFiAPData.class, Traj.WiFiAPData.Builder.class); } - // Construct using Traj.GNSS_Sample.newBuilder() + // Construct using Traj.WiFiAPData.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -8964,131 +17650,128 @@ private void maybeForceBuilderInitialization() { .alwaysUseFieldBuilders) { } } + @java.lang.Override public Builder clear() { super.clear(); - relativeTimestamp_ = 0L; - - latitude_ = 0F; - - longitude_ = 0F; - - altitude_ = 0F; + mac_ = 0L; - accuracy_ = 0F; + ssid_ = ""; - speed_ = 0F; + frequency_ = 0L; - provider_ = ""; + rttEnabled_ = false; return this; } + @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return Traj.internal_static_GNSS_Sample_descriptor; + return Traj.internal_static_WiFiAPData_descriptor; } - public GNSS_Sample getDefaultInstanceForType() { - return GNSS_Sample.getDefaultInstance(); + @java.lang.Override + public Traj.WiFiAPData getDefaultInstanceForType() { + return Traj.WiFiAPData.getDefaultInstance(); } - public GNSS_Sample build() { - GNSS_Sample result = buildPartial(); + @java.lang.Override + public Traj.WiFiAPData build() { + Traj.WiFiAPData result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } - public GNSS_Sample buildPartial() { - GNSS_Sample result = new GNSS_Sample(this); - result.relativeTimestamp_ = relativeTimestamp_; - result.latitude_ = latitude_; - result.longitude_ = longitude_; - result.altitude_ = altitude_; - result.accuracy_ = accuracy_; - result.speed_ = speed_; - result.provider_ = provider_; + @java.lang.Override + public Traj.WiFiAPData buildPartial() { + Traj.WiFiAPData result = new Traj.WiFiAPData(this); + result.mac_ = mac_; + result.ssid_ = ssid_; + result.frequency_ = frequency_; + result.rttEnabled_ = rttEnabled_; onBuilt(); return result; } + @java.lang.Override public Builder clone() { - return (Builder) super.clone(); + return super.clone(); } + @java.lang.Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); + java.lang.Object value) { + return super.setField(field, value); } + @java.lang.Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); + return super.clearField(field); } + @java.lang.Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); + return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); + java.lang.Object value) { + return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof GNSS_Sample) { - return mergeFrom((GNSS_Sample)other); + if (other instanceof Traj.WiFiAPData) { + return mergeFrom((Traj.WiFiAPData)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(GNSS_Sample other) { - if (other == GNSS_Sample.getDefaultInstance()) return this; - if (other.getRelativeTimestamp() != 0L) { - setRelativeTimestamp(other.getRelativeTimestamp()); - } - if (other.getLatitude() != 0F) { - setLatitude(other.getLatitude()); - } - if (other.getLongitude() != 0F) { - setLongitude(other.getLongitude()); - } - if (other.getAltitude() != 0F) { - setAltitude(other.getAltitude()); + public Builder mergeFrom(Traj.WiFiAPData other) { + if (other == Traj.WiFiAPData.getDefaultInstance()) return this; + if (other.getMac() != 0L) { + setMac(other.getMac()); } - if (other.getAccuracy() != 0F) { - setAccuracy(other.getAccuracy()); + if (!other.getSsid().isEmpty()) { + ssid_ = other.ssid_; + onChanged(); } - if (other.getSpeed() != 0F) { - setSpeed(other.getSpeed()); + if (other.getFrequency() != 0L) { + setFrequency(other.getFrequency()); } - if (!other.getProvider().isEmpty()) { - provider_ = other.provider_; - onChanged(); + if (other.getRttEnabled() != false) { + setRttEnabled(other.getRttEnabled()); } + this.mergeUnknownFields(other.unknownFields); onChanged(); return this; } + @java.lang.Override public final boolean isInitialized() { return true; } + @java.lang.Override public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - GNSS_Sample parsedMessage = null; + Traj.WiFiAPData parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (GNSS_Sample) e.getUnfinishedMessage(); + parsedMessage = (Traj.WiFiAPData) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -9098,422 +17781,399 @@ public Builder mergeFrom( return this; } - private long relativeTimestamp_ ; - /** - * optional int64 relative_timestamp = 1; - */ - public long getRelativeTimestamp() { - return relativeTimestamp_; - } - /** - * optional int64 relative_timestamp = 1; - */ - public Builder setRelativeTimestamp(long value) { - - relativeTimestamp_ = value; - onChanged(); - return this; - } - /** - * optional int64 relative_timestamp = 1; - */ - public Builder clearRelativeTimestamp() { - - relativeTimestamp_ = 0L; - onChanged(); - return this; - } - - private float latitude_ ; - /** - *
-       * degrees (minimum 6 significant figures)
-       * latitude between -90 and 90
-       * 
- * - * optional float latitude = 2; - */ - public float getLatitude() { - return latitude_; - } - /** - *
-       * degrees (minimum 6 significant figures)
-       * latitude between -90 and 90
-       * 
- * - * optional float latitude = 2; - */ - public Builder setLatitude(float value) { - - latitude_ = value; - onChanged(); - return this; - } - /** - *
-       * degrees (minimum 6 significant figures)
-       * latitude between -90 and 90
-       * 
- * - * optional float latitude = 2; - */ - public Builder clearLatitude() { - - latitude_ = 0F; - onChanged(); - return this; - } - - private float longitude_ ; + private long mac_ ; /** *
-       * longitude between -180 and 180
+       * Integer encoding of the hex mac address (BSSID)
+       * e.g. 207394925843984
        * 
* - * optional float longitude = 3; + * int64 mac = 1; + * @return The mac. */ - public float getLongitude() { - return longitude_; + @java.lang.Override + public long getMac() { + return mac_; } /** *
-       * longitude between -180 and 180
+       * Integer encoding of the hex mac address (BSSID)
+       * e.g. 207394925843984
        * 
* - * optional float longitude = 3; + * int64 mac = 1; + * @param value The mac to set. + * @return This builder for chaining. */ - public Builder setLongitude(float value) { + public Builder setMac(long value) { - longitude_ = value; + mac_ = value; onChanged(); return this; } /** *
-       * longitude between -180 and 180
+       * Integer encoding of the hex mac address (BSSID)
+       * e.g. 207394925843984
        * 
* - * optional float longitude = 3; + * int64 mac = 1; + * @return This builder for chaining. */ - public Builder clearLongitude() { + public Builder clearMac() { - longitude_ = 0F; + mac_ = 0L; onChanged(); return this; } - private float altitude_ ; + private java.lang.Object ssid_ = ""; /** *
-       *metres
+       * E.g. 'Eduroam' or 'Starbucks_free_wifi'
        * 
* - * optional float altitude = 4; + * string ssid = 2; + * @return The ssid. */ - public float getAltitude() { - return altitude_; + public java.lang.String getSsid() { + java.lang.Object ref = ssid_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + ssid_ = s; + return s; + } else { + return (java.lang.String) ref; + } } /** *
-       *metres
+       * E.g. 'Eduroam' or 'Starbucks_free_wifi'
        * 
* - * optional float altitude = 4; + * string ssid = 2; + * @return The bytes for ssid. */ - public Builder setAltitude(float value) { - - altitude_ = value; - onChanged(); - return this; + public com.google.protobuf.ByteString + getSsidBytes() { + java.lang.Object ref = ssid_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + ssid_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } } /** *
-       *metres
+       * E.g. 'Eduroam' or 'Starbucks_free_wifi'
        * 
* - * optional float altitude = 4; + * string ssid = 2; + * @param value The ssid to set. + * @return This builder for chaining. */ - public Builder clearAltitude() { - - altitude_ = 0F; + public Builder setSsid( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + ssid_ = value; onChanged(); return this; } - - private float accuracy_ ; - /** - *
-       * metres
-       * 
- * - * optional float accuracy = 5; - */ - public float getAccuracy() { - return accuracy_; - } /** *
-       * metres
+       * E.g. 'Eduroam' or 'Starbucks_free_wifi'
        * 
* - * optional float accuracy = 5; + * string ssid = 2; + * @return This builder for chaining. */ - public Builder setAccuracy(float value) { + public Builder clearSsid() { - accuracy_ = value; + ssid_ = getDefaultInstance().getSsid(); onChanged(); return this; } /** *
-       * metres
+       * E.g. 'Eduroam' or 'Starbucks_free_wifi'
        * 
* - * optional float accuracy = 5; + * string ssid = 2; + * @param value The bytes for ssid to set. + * @return This builder for chaining. */ - public Builder clearAccuracy() { + public Builder setSsidBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); - accuracy_ = 0F; + ssid_ = value; onChanged(); return this; } - private float speed_ ; + private long frequency_ ; /** *
-       * m/s
+       * Typically 2.4GHz or 5GHz
        * 
* - * optional float speed = 6; + * int64 frequency = 3; + * @return The frequency. */ - public float getSpeed() { - return speed_; + @java.lang.Override + public long getFrequency() { + return frequency_; } /** *
-       * m/s
+       * Typically 2.4GHz or 5GHz
        * 
* - * optional float speed = 6; + * int64 frequency = 3; + * @param value The frequency to set. + * @return This builder for chaining. */ - public Builder setSpeed(float value) { + public Builder setFrequency(long value) { - speed_ = value; + frequency_ = value; onChanged(); return this; } /** *
-       * m/s
+       * Typically 2.4GHz or 5GHz
        * 
* - * optional float speed = 6; + * int64 frequency = 3; + * @return This builder for chaining. */ - public Builder clearSpeed() { + public Builder clearFrequency() { - speed_ = 0F; + frequency_ = 0L; onChanged(); return this; } - private Object provider_ = ""; - /** - *
-       * e.g 'gps' or 'network'
-       * 
- * - * optional string provider = 7; - */ - public String getProvider() { - Object ref = provider_; - if (!(ref instanceof String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - provider_ = s; - return s; - } else { - return (String) ref; - } - } - /** - *
-       * e.g 'gps' or 'network'
-       * 
- * - * optional string provider = 7; - */ - public com.google.protobuf.ByteString - getProviderBytes() { - Object ref = provider_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - provider_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } + private boolean rttEnabled_ ; /** *
-       * e.g 'gps' or 'network'
+       * Flag to indicate if the AP supports RTT measurements
        * 
* - * optional string provider = 7; + * bool rtt_enabled = 4; + * @return The rttEnabled. */ - public Builder setProvider( - String value) { - if (value == null) { - throw new NullPointerException(); - } - - provider_ = value; - onChanged(); - return this; + @java.lang.Override + public boolean getRttEnabled() { + return rttEnabled_; } /** *
-       * e.g 'gps' or 'network'
+       * Flag to indicate if the AP supports RTT measurements
        * 
* - * optional string provider = 7; + * bool rtt_enabled = 4; + * @param value The rttEnabled to set. + * @return This builder for chaining. */ - public Builder clearProvider() { + public Builder setRttEnabled(boolean value) { - provider_ = getDefaultInstance().getProvider(); + rttEnabled_ = value; onChanged(); return this; } /** *
-       * e.g 'gps' or 'network'
+       * Flag to indicate if the AP supports RTT measurements
        * 
* - * optional string provider = 7; + * bool rtt_enabled = 4; + * @return This builder for chaining. */ - public Builder setProviderBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); + public Builder clearRttEnabled() { - provider_ = value; + rttEnabled_ = false; onChanged(); return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.setUnknownFields(unknownFields); } + @java.lang.Override public final Builder mergeUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:GNSS_Sample) + // @@protoc_insertion_point(builder_scope:WiFiAPData) } - // @@protoc_insertion_point(class_scope:GNSS_Sample) - private static final GNSS_Sample DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:WiFiAPData) + private static final Traj.WiFiAPData DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new GNSS_Sample(); + DEFAULT_INSTANCE = new Traj.WiFiAPData(); } - public static GNSS_Sample getDefaultInstance() { + public static Traj.WiFiAPData getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - public GNSS_Sample parsePartialFrom( + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public WiFiAPData parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { - return new GNSS_Sample(input, extensionRegistry); + return new WiFiAPData(input, extensionRegistry); } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } - @Override - public com.google.protobuf.Parser getParserForType() { + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { return PARSER; } - public GNSS_Sample getDefaultInstanceForType() { + @java.lang.Override + public Traj.WiFiAPData getDefaultInstanceForType() { return DEFAULT_INSTANCE; } } - public interface WiFi_SampleOrBuilder extends - // @@protoc_insertion_point(interface_extends:WiFi_Sample) + public interface BleDataOrBuilder extends + // @@protoc_insertion_point(interface_extends:BleData) com.google.protobuf.MessageOrBuilder { /** - * optional int64 relative_timestamp = 1; + * string mac_address = 1; + * @return The macAddress. */ - long getRelativeTimestamp(); + java.lang.String getMacAddress(); + /** + * string mac_address = 1; + * @return The bytes for macAddress. + */ + com.google.protobuf.ByteString + getMacAddressBytes(); + + /** + * string name = 2; + * @return The name. + */ + java.lang.String getName(); + /** + * string name = 2; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); /** - * repeated .Mac_Scan mac_scans = 2; + * int32 tx_power_level = 3; + * @return The txPowerLevel. */ - java.util.List - getMacScansList(); + int getTxPowerLevel(); + /** - * repeated .Mac_Scan mac_scans = 2; + * int32 advertise_flags = 4; + * @return The advertiseFlags. */ - Mac_Scan getMacScans(int index); + int getAdvertiseFlags(); + /** - * repeated .Mac_Scan mac_scans = 2; + * repeated string service_uuids = 5; + * @return A list containing the serviceUuids. */ - int getMacScansCount(); + java.util.List + getServiceUuidsList(); /** - * repeated .Mac_Scan mac_scans = 2; + * repeated string service_uuids = 5; + * @return The count of serviceUuids. */ - java.util.List - getMacScansOrBuilderList(); + int getServiceUuidsCount(); /** - * repeated .Mac_Scan mac_scans = 2; + * repeated string service_uuids = 5; + * @param index The index of the element to return. + * @return The serviceUuids at the given index. */ - Mac_ScanOrBuilder getMacScansOrBuilder( - int index); + java.lang.String getServiceUuids(int index); + /** + * repeated string service_uuids = 5; + * @param index The index of the value to return. + * @return The bytes of the serviceUuids at the given index. + */ + com.google.protobuf.ByteString + getServiceUuidsBytes(int index); + + /** + * bytes manufacturer_data = 6; + * @return The manufacturerData. + */ + com.google.protobuf.ByteString getManufacturerData(); } /** - * Protobuf type {@code WiFi_Sample} + * Protobuf type {@code BleData} */ - public static final class WiFi_Sample extends + public static final class BleData extends com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:WiFi_Sample) - WiFi_SampleOrBuilder { - // Use WiFi_Sample.newBuilder() to construct. - private WiFi_Sample(com.google.protobuf.GeneratedMessageV3.Builder builder) { + // @@protoc_insertion_point(message_implements:BleData) + BleDataOrBuilder { + private static final long serialVersionUID = 0L; + // Use BleData.newBuilder() to construct. + private BleData(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } - private WiFi_Sample() { - relativeTimestamp_ = 0L; - macScans_ = java.util.Collections.emptyList(); + private BleData() { + macAddress_ = ""; + name_ = ""; + serviceUuids_ = com.google.protobuf.LazyStringArrayList.EMPTY; + manufacturerData_ = com.google.protobuf.ByteString.EMPTY; + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new BleData(); } - @Override + @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + return this.unknownFields; } - private WiFi_Sample( + private BleData( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { @@ -9522,98 +18182,225 @@ private WiFi_Sample( case 0: done = true; break; - default: { - if (!input.skipField(tag)) { - done = true; + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + + macAddress_ = s; + break; + } + case 18: { + java.lang.String s = input.readStringRequireUtf8(); + + name_ = s; + break; + } + case 24: { + + txPowerLevel_ = input.readInt32(); + break; + } + case 32: { + + advertiseFlags_ = input.readInt32(); + break; + } + case 42: { + java.lang.String s = input.readStringRequireUtf8(); + if (!((mutable_bitField0_ & 0x00000001) != 0)) { + serviceUuids_ = new com.google.protobuf.LazyStringArrayList(); + mutable_bitField0_ |= 0x00000001; } + serviceUuids_.add(s); break; } - case 8: { + case 50: { - relativeTimestamp_ = input.readInt64(); + manufacturerData_ = input.readBytes(); break; } - case 18: { - if (!((mutable_bitField0_ & 0x00000002) == 0x00000002)) { - macScans_ = new java.util.ArrayList(); - mutable_bitField0_ |= 0x00000002; + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; } - macScans_.add( - input.readMessage(Mac_Scan.parser(), extensionRegistry)); break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { - if (((mutable_bitField0_ & 0x00000002) == 0x00000002)) { - macScans_ = java.util.Collections.unmodifiableList(macScans_); + if (((mutable_bitField0_ & 0x00000001) != 0)) { + serviceUuids_ = serviceUuids_.getUnmodifiableView(); } + this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_WiFi_Sample_descriptor; + return Traj.internal_static_BleData_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_WiFi_Sample_fieldAccessorTable + return Traj.internal_static_BleData_fieldAccessorTable .ensureFieldAccessorsInitialized( - WiFi_Sample.class, Builder.class); + Traj.BleData.class, Traj.BleData.Builder.class); } - private int bitField0_; - public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; - private long relativeTimestamp_; + public static final int MAC_ADDRESS_FIELD_NUMBER = 1; + private volatile java.lang.Object macAddress_; /** - * optional int64 relative_timestamp = 1; + * string mac_address = 1; + * @return The macAddress. */ - public long getRelativeTimestamp() { - return relativeTimestamp_; + @java.lang.Override + public java.lang.String getMacAddress() { + java.lang.Object ref = macAddress_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + macAddress_ = s; + return s; + } + } + /** + * string mac_address = 1; + * @return The bytes for macAddress. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getMacAddressBytes() { + java.lang.Object ref = macAddress_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + macAddress_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int NAME_FIELD_NUMBER = 2; + private volatile java.lang.Object name_; + /** + * string name = 2; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + * string name = 2; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } } - public static final int MAC_SCANS_FIELD_NUMBER = 2; - private java.util.List macScans_; + public static final int TX_POWER_LEVEL_FIELD_NUMBER = 3; + private int txPowerLevel_; /** - * repeated .Mac_Scan mac_scans = 2; + * int32 tx_power_level = 3; + * @return The txPowerLevel. */ - public java.util.List getMacScansList() { - return macScans_; + @java.lang.Override + public int getTxPowerLevel() { + return txPowerLevel_; } + + public static final int ADVERTISE_FLAGS_FIELD_NUMBER = 4; + private int advertiseFlags_; /** - * repeated .Mac_Scan mac_scans = 2; + * int32 advertise_flags = 4; + * @return The advertiseFlags. */ - public java.util.List - getMacScansOrBuilderList() { - return macScans_; + @java.lang.Override + public int getAdvertiseFlags() { + return advertiseFlags_; } + + public static final int SERVICE_UUIDS_FIELD_NUMBER = 5; + private com.google.protobuf.LazyStringList serviceUuids_; /** - * repeated .Mac_Scan mac_scans = 2; + * repeated string service_uuids = 5; + * @return A list containing the serviceUuids. */ - public int getMacScansCount() { - return macScans_.size(); + public com.google.protobuf.ProtocolStringList + getServiceUuidsList() { + return serviceUuids_; } /** - * repeated .Mac_Scan mac_scans = 2; + * repeated string service_uuids = 5; + * @return The count of serviceUuids. */ - public Mac_Scan getMacScans(int index) { - return macScans_.get(index); + public int getServiceUuidsCount() { + return serviceUuids_.size(); } /** - * repeated .Mac_Scan mac_scans = 2; + * repeated string service_uuids = 5; + * @param index The index of the element to return. + * @return The serviceUuids at the given index. */ - public Mac_ScanOrBuilder getMacScansOrBuilder( - int index) { - return macScans_.get(index); + public java.lang.String getServiceUuids(int index) { + return serviceUuids_.get(index); + } + /** + * repeated string service_uuids = 5; + * @param index The index of the value to return. + * @return The bytes of the serviceUuids at the given index. + */ + public com.google.protobuf.ByteString + getServiceUuidsBytes(int index) { + return serviceUuids_.getByteString(index); + } + + public static final int MANUFACTURER_DATA_FIELD_NUMBER = 6; + private com.google.protobuf.ByteString manufacturerData_; + /** + * bytes manufacturer_data = 6; + * @return The manufacturerData. + */ + @java.lang.Override + public com.google.protobuf.ByteString getManufacturerData() { + return manufacturerData_; } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; @@ -9623,123 +18410,182 @@ public final boolean isInitialized() { return true; } + @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (relativeTimestamp_ != 0L) { - output.writeInt64(1, relativeTimestamp_); + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(macAddress_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 1, macAddress_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 2, name_); + } + if (txPowerLevel_ != 0) { + output.writeInt32(3, txPowerLevel_); } - for (int i = 0; i < macScans_.size(); i++) { - output.writeMessage(2, macScans_.get(i)); + if (advertiseFlags_ != 0) { + output.writeInt32(4, advertiseFlags_); } + for (int i = 0; i < serviceUuids_.size(); i++) { + com.google.protobuf.GeneratedMessageV3.writeString(output, 5, serviceUuids_.getRaw(i)); + } + if (!manufacturerData_.isEmpty()) { + output.writeBytes(6, manufacturerData_); + } + unknownFields.writeTo(output); } + @java.lang.Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; size = 0; - if (relativeTimestamp_ != 0L) { + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(macAddress_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, macAddress_); + } + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, name_); + } + if (txPowerLevel_ != 0) { size += com.google.protobuf.CodedOutputStream - .computeInt64Size(1, relativeTimestamp_); + .computeInt32Size(3, txPowerLevel_); + } + if (advertiseFlags_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(4, advertiseFlags_); } - for (int i = 0; i < macScans_.size(); i++) { + { + int dataSize = 0; + for (int i = 0; i < serviceUuids_.size(); i++) { + dataSize += computeStringSizeNoTag(serviceUuids_.getRaw(i)); + } + size += dataSize; + size += 1 * getServiceUuidsList().size(); + } + if (!manufacturerData_.isEmpty()) { size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, macScans_.get(i)); + .computeBytesSize(6, manufacturerData_); } + size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } - private static final long serialVersionUID = 0L; - @Override - public boolean equals(final Object obj) { + @java.lang.Override + public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof WiFi_Sample)) { + if (!(obj instanceof Traj.BleData)) { return super.equals(obj); } - WiFi_Sample other = (WiFi_Sample) obj; - - boolean result = true; - result = result && (getRelativeTimestamp() - == other.getRelativeTimestamp()); - result = result && getMacScansList() - .equals(other.getMacScansList()); - return result; + Traj.BleData other = (Traj.BleData) obj; + + if (!getMacAddress() + .equals(other.getMacAddress())) return false; + if (!getName() + .equals(other.getName())) return false; + if (getTxPowerLevel() + != other.getTxPowerLevel()) return false; + if (getAdvertiseFlags() + != other.getAdvertiseFlags()) return false; + if (!getServiceUuidsList() + .equals(other.getServiceUuidsList())) return false; + if (!getManufacturerData() + .equals(other.getManufacturerData())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; } - @Override + @java.lang.Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; - hash = (19 * hash) + getDescriptorForType().hashCode(); - hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getRelativeTimestamp()); - if (getMacScansCount() > 0) { - hash = (37 * hash) + MAC_SCANS_FIELD_NUMBER; - hash = (53 * hash) + getMacScansList().hashCode(); - } + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + MAC_ADDRESS_FIELD_NUMBER; + hash = (53 * hash) + getMacAddress().hashCode(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + TX_POWER_LEVEL_FIELD_NUMBER; + hash = (53 * hash) + getTxPowerLevel(); + hash = (37 * hash) + ADVERTISE_FLAGS_FIELD_NUMBER; + hash = (53 * hash) + getAdvertiseFlags(); + if (getServiceUuidsCount() > 0) { + hash = (37 * hash) + SERVICE_UUIDS_FIELD_NUMBER; + hash = (53 * hash) + getServiceUuidsList().hashCode(); + } + hash = (37 * hash) + MANUFACTURER_DATA_FIELD_NUMBER; + hash = (53 * hash) + getManufacturerData().hashCode(); hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } - public static WiFi_Sample parseFrom( + public static Traj.BleData parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.BleData parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.BleData parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static WiFi_Sample parseFrom( + public static Traj.BleData parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static WiFi_Sample parseFrom(byte[] data) + public static Traj.BleData parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static WiFi_Sample parseFrom( + public static Traj.BleData parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static WiFi_Sample parseFrom(java.io.InputStream input) + public static Traj.BleData parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static WiFi_Sample parseFrom( + public static Traj.BleData parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static WiFi_Sample parseDelimitedFrom(java.io.InputStream input) + public static Traj.BleData parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static WiFi_Sample parseDelimitedFrom( + public static Traj.BleData parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static WiFi_Sample parseFrom( + public static Traj.BleData parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static WiFi_Sample parseFrom( + public static Traj.BleData parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -9747,44 +18593,47 @@ public static WiFi_Sample parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } + @java.lang.Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(WiFi_Sample prototype) { + public static Builder newBuilder(Traj.BleData prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } - @Override + @java.lang.Override protected Builder newBuilderForType( com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** - * Protobuf type {@code WiFi_Sample} + * Protobuf type {@code BleData} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:WiFi_Sample) - WiFi_SampleOrBuilder { + // @@protoc_insertion_point(builder_implements:BleData) + Traj.BleDataOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_WiFi_Sample_descriptor; + return Traj.internal_static_BleData_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_WiFi_Sample_fieldAccessorTable + return Traj.internal_static_BleData_fieldAccessorTable .ensureFieldAccessorsInitialized( - WiFi_Sample.class, Builder.class); + Traj.BleData.class, Traj.BleData.Builder.class); } - // Construct using Traj.WiFi_Sample.newBuilder() + // Construct using Traj.BleData.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -9797,141 +18646,155 @@ private Builder( private void maybeForceBuilderInitialization() { if (com.google.protobuf.GeneratedMessageV3 .alwaysUseFieldBuilders) { - getMacScansFieldBuilder(); } } + @java.lang.Override public Builder clear() { super.clear(); - relativeTimestamp_ = 0L; + macAddress_ = ""; + + name_ = ""; + + txPowerLevel_ = 0; + + advertiseFlags_ = 0; + + serviceUuids_ = com.google.protobuf.LazyStringArrayList.EMPTY; + bitField0_ = (bitField0_ & ~0x00000001); + manufacturerData_ = com.google.protobuf.ByteString.EMPTY; - if (macScansBuilder_ == null) { - macScans_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); - } else { - macScansBuilder_.clear(); - } return this; } + @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return Traj.internal_static_WiFi_Sample_descriptor; + return Traj.internal_static_BleData_descriptor; } - public WiFi_Sample getDefaultInstanceForType() { - return WiFi_Sample.getDefaultInstance(); + @java.lang.Override + public Traj.BleData getDefaultInstanceForType() { + return Traj.BleData.getDefaultInstance(); } - public WiFi_Sample build() { - WiFi_Sample result = buildPartial(); + @java.lang.Override + public Traj.BleData build() { + Traj.BleData result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } - public WiFi_Sample buildPartial() { - WiFi_Sample result = new WiFi_Sample(this); + @java.lang.Override + public Traj.BleData buildPartial() { + Traj.BleData result = new Traj.BleData(this); int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - result.relativeTimestamp_ = relativeTimestamp_; - if (macScansBuilder_ == null) { - if (((bitField0_ & 0x00000002) == 0x00000002)) { - macScans_ = java.util.Collections.unmodifiableList(macScans_); - bitField0_ = (bitField0_ & ~0x00000002); - } - result.macScans_ = macScans_; - } else { - result.macScans_ = macScansBuilder_.build(); - } - result.bitField0_ = to_bitField0_; + result.macAddress_ = macAddress_; + result.name_ = name_; + result.txPowerLevel_ = txPowerLevel_; + result.advertiseFlags_ = advertiseFlags_; + if (((bitField0_ & 0x00000001) != 0)) { + serviceUuids_ = serviceUuids_.getUnmodifiableView(); + bitField0_ = (bitField0_ & ~0x00000001); + } + result.serviceUuids_ = serviceUuids_; + result.manufacturerData_ = manufacturerData_; onBuilt(); return result; } + @java.lang.Override public Builder clone() { - return (Builder) super.clone(); + return super.clone(); } + @java.lang.Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); + java.lang.Object value) { + return super.setField(field, value); } + @java.lang.Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); + return super.clearField(field); } + @java.lang.Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); + return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); + java.lang.Object value) { + return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof WiFi_Sample) { - return mergeFrom((WiFi_Sample)other); + if (other instanceof Traj.BleData) { + return mergeFrom((Traj.BleData)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(WiFi_Sample other) { - if (other == WiFi_Sample.getDefaultInstance()) return this; - if (other.getRelativeTimestamp() != 0L) { - setRelativeTimestamp(other.getRelativeTimestamp()); + public Builder mergeFrom(Traj.BleData other) { + if (other == Traj.BleData.getDefaultInstance()) return this; + if (!other.getMacAddress().isEmpty()) { + macAddress_ = other.macAddress_; + onChanged(); } - if (macScansBuilder_ == null) { - if (!other.macScans_.isEmpty()) { - if (macScans_.isEmpty()) { - macScans_ = other.macScans_; - bitField0_ = (bitField0_ & ~0x00000002); - } else { - ensureMacScansIsMutable(); - macScans_.addAll(other.macScans_); - } - onChanged(); - } - } else { - if (!other.macScans_.isEmpty()) { - if (macScansBuilder_.isEmpty()) { - macScansBuilder_.dispose(); - macScansBuilder_ = null; - macScans_ = other.macScans_; - bitField0_ = (bitField0_ & ~0x00000002); - macScansBuilder_ = - com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? - getMacScansFieldBuilder() : null; - } else { - macScansBuilder_.addAllMessages(other.macScans_); - } + if (!other.getName().isEmpty()) { + name_ = other.name_; + onChanged(); + } + if (other.getTxPowerLevel() != 0) { + setTxPowerLevel(other.getTxPowerLevel()); + } + if (other.getAdvertiseFlags() != 0) { + setAdvertiseFlags(other.getAdvertiseFlags()); + } + if (!other.serviceUuids_.isEmpty()) { + if (serviceUuids_.isEmpty()) { + serviceUuids_ = other.serviceUuids_; + bitField0_ = (bitField0_ & ~0x00000001); + } else { + ensureServiceUuidsIsMutable(); + serviceUuids_.addAll(other.serviceUuids_); } + onChanged(); + } + if (other.getManufacturerData() != com.google.protobuf.ByteString.EMPTY) { + setManufacturerData(other.getManufacturerData()); } + this.mergeUnknownFields(other.unknownFields); onChanged(); return this; } + @java.lang.Override public final boolean isInitialized() { return true; } + @java.lang.Override public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - WiFi_Sample parsedMessage = null; + Traj.BleData parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (WiFi_Sample) e.getUnfinishedMessage(); + parsedMessage = (Traj.BleData) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -9942,377 +18805,479 @@ public Builder mergeFrom( } private int bitField0_; - private long relativeTimestamp_ ; + private java.lang.Object macAddress_ = ""; /** - * optional int64 relative_timestamp = 1; + * string mac_address = 1; + * @return The macAddress. */ - public long getRelativeTimestamp() { - return relativeTimestamp_; + public java.lang.String getMacAddress() { + java.lang.Object ref = macAddress_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + macAddress_ = s; + return s; + } else { + return (java.lang.String) ref; + } } /** - * optional int64 relative_timestamp = 1; + * string mac_address = 1; + * @return The bytes for macAddress. */ - public Builder setRelativeTimestamp(long value) { - - relativeTimestamp_ = value; + public com.google.protobuf.ByteString + getMacAddressBytes() { + java.lang.Object ref = macAddress_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + macAddress_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string mac_address = 1; + * @param value The macAddress to set. + * @return This builder for chaining. + */ + public Builder setMacAddress( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + macAddress_ = value; onChanged(); return this; } /** - * optional int64 relative_timestamp = 1; + * string mac_address = 1; + * @return This builder for chaining. */ - public Builder clearRelativeTimestamp() { + public Builder clearMacAddress() { - relativeTimestamp_ = 0L; + macAddress_ = getDefaultInstance().getMacAddress(); onChanged(); return this; } - - private java.util.List macScans_ = - java.util.Collections.emptyList(); - private void ensureMacScansIsMutable() { - if (!((bitField0_ & 0x00000002) == 0x00000002)) { - macScans_ = new java.util.ArrayList(macScans_); - bitField0_ |= 0x00000002; - } + /** + * string mac_address = 1; + * @param value The bytes for macAddress to set. + * @return This builder for chaining. + */ + public Builder setMacAddressBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + macAddress_ = value; + onChanged(); + return this; } - private com.google.protobuf.RepeatedFieldBuilderV3< - Mac_Scan, Mac_Scan.Builder, Mac_ScanOrBuilder> macScansBuilder_; - + private java.lang.Object name_ = ""; /** - * repeated .Mac_Scan mac_scans = 2; + * string name = 2; + * @return The name. */ - public java.util.List getMacScansList() { - if (macScansBuilder_ == null) { - return java.util.Collections.unmodifiableList(macScans_); + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; } else { - return macScansBuilder_.getMessageList(); + return (java.lang.String) ref; } } /** - * repeated .Mac_Scan mac_scans = 2; + * string name = 2; + * @return The bytes for name. */ - public int getMacScansCount() { - if (macScansBuilder_ == null) { - return macScans_.size(); + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; } else { - return macScansBuilder_.getCount(); + return (com.google.protobuf.ByteString) ref; } } /** - * repeated .Mac_Scan mac_scans = 2; + * string name = 2; + * @param value The name to set. + * @return This builder for chaining. */ - public Mac_Scan getMacScans(int index) { - if (macScansBuilder_ == null) { - return macScans_.get(index); - } else { - return macScansBuilder_.getMessage(index); - } + public Builder setName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + name_ = value; + onChanged(); + return this; } /** - * repeated .Mac_Scan mac_scans = 2; + * string name = 2; + * @return This builder for chaining. */ - public Builder setMacScans( - int index, Mac_Scan value) { - if (macScansBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureMacScansIsMutable(); - macScans_.set(index, value); - onChanged(); - } else { - macScansBuilder_.setMessage(index, value); - } + public Builder clearName() { + + name_ = getDefaultInstance().getName(); + onChanged(); return this; } /** - * repeated .Mac_Scan mac_scans = 2; + * string name = 2; + * @param value The bytes for name to set. + * @return This builder for chaining. */ - public Builder setMacScans( - int index, Mac_Scan.Builder builderForValue) { - if (macScansBuilder_ == null) { - ensureMacScansIsMutable(); - macScans_.set(index, builderForValue.build()); - onChanged(); - } else { - macScansBuilder_.setMessage(index, builderForValue.build()); - } + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + name_ = value; + onChanged(); return this; } + + private int txPowerLevel_ ; /** - * repeated .Mac_Scan mac_scans = 2; + * int32 tx_power_level = 3; + * @return The txPowerLevel. */ - public Builder addMacScans(Mac_Scan value) { - if (macScansBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureMacScansIsMutable(); - macScans_.add(value); - onChanged(); - } else { - macScansBuilder_.addMessage(value); - } - return this; + @java.lang.Override + public int getTxPowerLevel() { + return txPowerLevel_; } /** - * repeated .Mac_Scan mac_scans = 2; + * int32 tx_power_level = 3; + * @param value The txPowerLevel to set. + * @return This builder for chaining. */ - public Builder addMacScans( - int index, Mac_Scan value) { - if (macScansBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureMacScansIsMutable(); - macScans_.add(index, value); - onChanged(); - } else { - macScansBuilder_.addMessage(index, value); - } + public Builder setTxPowerLevel(int value) { + + txPowerLevel_ = value; + onChanged(); return this; } /** - * repeated .Mac_Scan mac_scans = 2; + * int32 tx_power_level = 3; + * @return This builder for chaining. */ - public Builder addMacScans( - Mac_Scan.Builder builderForValue) { - if (macScansBuilder_ == null) { - ensureMacScansIsMutable(); - macScans_.add(builderForValue.build()); - onChanged(); - } else { - macScansBuilder_.addMessage(builderForValue.build()); - } + public Builder clearTxPowerLevel() { + + txPowerLevel_ = 0; + onChanged(); return this; } + + private int advertiseFlags_ ; /** - * repeated .Mac_Scan mac_scans = 2; + * int32 advertise_flags = 4; + * @return The advertiseFlags. */ - public Builder addMacScans( - int index, Mac_Scan.Builder builderForValue) { - if (macScansBuilder_ == null) { - ensureMacScansIsMutable(); - macScans_.add(index, builderForValue.build()); - onChanged(); - } else { - macScansBuilder_.addMessage(index, builderForValue.build()); - } - return this; + @java.lang.Override + public int getAdvertiseFlags() { + return advertiseFlags_; } /** - * repeated .Mac_Scan mac_scans = 2; + * int32 advertise_flags = 4; + * @param value The advertiseFlags to set. + * @return This builder for chaining. */ - public Builder addAllMacScans( - Iterable values) { - if (macScansBuilder_ == null) { - ensureMacScansIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, macScans_); - onChanged(); - } else { - macScansBuilder_.addAllMessages(values); - } + public Builder setAdvertiseFlags(int value) { + + advertiseFlags_ = value; + onChanged(); return this; } /** - * repeated .Mac_Scan mac_scans = 2; + * int32 advertise_flags = 4; + * @return This builder for chaining. */ - public Builder clearMacScans() { - if (macScansBuilder_ == null) { - macScans_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000002); - onChanged(); - } else { - macScansBuilder_.clear(); - } + public Builder clearAdvertiseFlags() { + + advertiseFlags_ = 0; + onChanged(); return this; } + + private com.google.protobuf.LazyStringList serviceUuids_ = com.google.protobuf.LazyStringArrayList.EMPTY; + private void ensureServiceUuidsIsMutable() { + if (!((bitField0_ & 0x00000001) != 0)) { + serviceUuids_ = new com.google.protobuf.LazyStringArrayList(serviceUuids_); + bitField0_ |= 0x00000001; + } + } /** - * repeated .Mac_Scan mac_scans = 2; + * repeated string service_uuids = 5; + * @return A list containing the serviceUuids. */ - public Builder removeMacScans(int index) { - if (macScansBuilder_ == null) { - ensureMacScansIsMutable(); - macScans_.remove(index); - onChanged(); - } else { - macScansBuilder_.remove(index); - } + public com.google.protobuf.ProtocolStringList + getServiceUuidsList() { + return serviceUuids_.getUnmodifiableView(); + } + /** + * repeated string service_uuids = 5; + * @return The count of serviceUuids. + */ + public int getServiceUuidsCount() { + return serviceUuids_.size(); + } + /** + * repeated string service_uuids = 5; + * @param index The index of the element to return. + * @return The serviceUuids at the given index. + */ + public java.lang.String getServiceUuids(int index) { + return serviceUuids_.get(index); + } + /** + * repeated string service_uuids = 5; + * @param index The index of the value to return. + * @return The bytes of the serviceUuids at the given index. + */ + public com.google.protobuf.ByteString + getServiceUuidsBytes(int index) { + return serviceUuids_.getByteString(index); + } + /** + * repeated string service_uuids = 5; + * @param index The index to set the value at. + * @param value The serviceUuids to set. + * @return This builder for chaining. + */ + public Builder setServiceUuids( + int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + ensureServiceUuidsIsMutable(); + serviceUuids_.set(index, value); + onChanged(); return this; } /** - * repeated .Mac_Scan mac_scans = 2; + * repeated string service_uuids = 5; + * @param value The serviceUuids to add. + * @return This builder for chaining. */ - public Mac_Scan.Builder getMacScansBuilder( - int index) { - return getMacScansFieldBuilder().getBuilder(index); + public Builder addServiceUuids( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + ensureServiceUuidsIsMutable(); + serviceUuids_.add(value); + onChanged(); + return this; } /** - * repeated .Mac_Scan mac_scans = 2; + * repeated string service_uuids = 5; + * @param values The serviceUuids to add. + * @return This builder for chaining. */ - public Mac_ScanOrBuilder getMacScansOrBuilder( - int index) { - if (macScansBuilder_ == null) { - return macScans_.get(index); } else { - return macScansBuilder_.getMessageOrBuilder(index); - } + public Builder addAllServiceUuids( + java.lang.Iterable values) { + ensureServiceUuidsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, serviceUuids_); + onChanged(); + return this; } /** - * repeated .Mac_Scan mac_scans = 2; + * repeated string service_uuids = 5; + * @return This builder for chaining. */ - public java.util.List - getMacScansOrBuilderList() { - if (macScansBuilder_ != null) { - return macScansBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(macScans_); - } + public Builder clearServiceUuids() { + serviceUuids_ = com.google.protobuf.LazyStringArrayList.EMPTY; + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; } /** - * repeated .Mac_Scan mac_scans = 2; + * repeated string service_uuids = 5; + * @param value The bytes of the serviceUuids to add. + * @return This builder for chaining. */ - public Mac_Scan.Builder addMacScansBuilder() { - return getMacScansFieldBuilder().addBuilder( - Mac_Scan.getDefaultInstance()); + public Builder addServiceUuidsBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + ensureServiceUuidsIsMutable(); + serviceUuids_.add(value); + onChanged(); + return this; } + + private com.google.protobuf.ByteString manufacturerData_ = com.google.protobuf.ByteString.EMPTY; /** - * repeated .Mac_Scan mac_scans = 2; + * bytes manufacturer_data = 6; + * @return The manufacturerData. */ - public Mac_Scan.Builder addMacScansBuilder( - int index) { - return getMacScansFieldBuilder().addBuilder( - index, Mac_Scan.getDefaultInstance()); + @java.lang.Override + public com.google.protobuf.ByteString getManufacturerData() { + return manufacturerData_; } /** - * repeated .Mac_Scan mac_scans = 2; + * bytes manufacturer_data = 6; + * @param value The manufacturerData to set. + * @return This builder for chaining. */ - public java.util.List - getMacScansBuilderList() { - return getMacScansFieldBuilder().getBuilderList(); + public Builder setManufacturerData(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + + manufacturerData_ = value; + onChanged(); + return this; } - private com.google.protobuf.RepeatedFieldBuilderV3< - Mac_Scan, Mac_Scan.Builder, Mac_ScanOrBuilder> - getMacScansFieldBuilder() { - if (macScansBuilder_ == null) { - macScansBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - Mac_Scan, Mac_Scan.Builder, Mac_ScanOrBuilder>( - macScans_, - ((bitField0_ & 0x00000002) == 0x00000002), - getParentForChildren(), - isClean()); - macScans_ = null; - } - return macScansBuilder_; + /** + * bytes manufacturer_data = 6; + * @return This builder for chaining. + */ + public Builder clearManufacturerData() { + + manufacturerData_ = getDefaultInstance().getManufacturerData(); + onChanged(); + return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.setUnknownFields(unknownFields); } + @java.lang.Override public final Builder mergeUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:WiFi_Sample) + // @@protoc_insertion_point(builder_scope:BleData) } - // @@protoc_insertion_point(class_scope:WiFi_Sample) - private static final WiFi_Sample DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:BleData) + private static final Traj.BleData DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new WiFi_Sample(); + DEFAULT_INSTANCE = new Traj.BleData(); } - public static WiFi_Sample getDefaultInstance() { + public static Traj.BleData getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - public WiFi_Sample parsePartialFrom( + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public BleData parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { - return new WiFi_Sample(input, extensionRegistry); + return new BleData(input, extensionRegistry); } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } - @Override - public com.google.protobuf.Parser getParserForType() { + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { return PARSER; } - public WiFi_Sample getDefaultInstanceForType() { + @java.lang.Override + public Traj.BleData getDefaultInstanceForType() { return DEFAULT_INSTANCE; } } - public interface Mac_ScanOrBuilder extends - // @@protoc_insertion_point(interface_extends:Mac_Scan) + public interface Vector3OrBuilder extends + // @@protoc_insertion_point(interface_extends:Vector3) com.google.protobuf.MessageOrBuilder { /** - * optional int64 relative_timestamp = 1; + * float x = 1; + * @return The x. */ - long getRelativeTimestamp(); + float getX(); /** - *
-     * Integer encoding of the hex mac address
-     * e.g. 207394925843984
-     * 
- * - * optional int64 mac = 2; + * float y = 2; + * @return The y. */ - long getMac(); + float getY(); /** - *
-     * rssi integer in dBm.
-     * typically between -120 and -10
-     * 
- * - * optional int32 rssi = 3; + * float z = 3; + * @return The z. */ - int getRssi(); + float getZ(); } /** - * Protobuf type {@code Mac_Scan} + *
+   * --- Common Types ---
+   * 
+ * + * Protobuf type {@code Vector3} */ - public static final class Mac_Scan extends + public static final class Vector3 extends com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:Mac_Scan) - Mac_ScanOrBuilder { - // Use Mac_Scan.newBuilder() to construct. - private Mac_Scan(com.google.protobuf.GeneratedMessageV3.Builder builder) { + // @@protoc_insertion_point(message_implements:Vector3) + Vector3OrBuilder { + private static final long serialVersionUID = 0L; + // Use Vector3.newBuilder() to construct. + private Vector3(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } - private Mac_Scan() { - relativeTimestamp_ = 0L; - mac_ = 0L; - rssi_ = 0; + private Vector3() { + } + + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new Vector3(); } - @Override + @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + return this.unknownFields; } - private Mac_Scan( + private Vector3( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); - int mutable_bitField0_ = 0; + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { @@ -10321,88 +19286,90 @@ private Mac_Scan( case 0: done = true; break; - default: { - if (!input.skipField(tag)) { - done = true; - } + case 13: { + + x_ = input.readFloat(); break; } - case 8: { + case 21: { - relativeTimestamp_ = input.readInt64(); + y_ = input.readFloat(); break; } - case 16: { + case 29: { - mac_ = input.readInt64(); + z_ = input.readFloat(); break; } - case 24: { - - rssi_ = input.readInt32(); + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { + this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Mac_Scan_descriptor; + return Traj.internal_static_Vector3_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Mac_Scan_fieldAccessorTable + return Traj.internal_static_Vector3_fieldAccessorTable .ensureFieldAccessorsInitialized( - Mac_Scan.class, Builder.class); + Traj.Vector3.class, Traj.Vector3.Builder.class); } - public static final int RELATIVE_TIMESTAMP_FIELD_NUMBER = 1; - private long relativeTimestamp_; + public static final int X_FIELD_NUMBER = 1; + private float x_; /** - * optional int64 relative_timestamp = 1; + * float x = 1; + * @return The x. */ - public long getRelativeTimestamp() { - return relativeTimestamp_; + @java.lang.Override + public float getX() { + return x_; } - public static final int MAC_FIELD_NUMBER = 2; - private long mac_; + public static final int Y_FIELD_NUMBER = 2; + private float y_; /** - *
-     * Integer encoding of the hex mac address
-     * e.g. 207394925843984
-     * 
- * - * optional int64 mac = 2; + * float y = 2; + * @return The y. */ - public long getMac() { - return mac_; + @java.lang.Override + public float getY() { + return y_; } - - public static final int RSSI_FIELD_NUMBER = 3; - private int rssi_; - /** - *
-     * rssi integer in dBm.
-     * typically between -120 and -10
-     * 
- * - * optional int32 rssi = 3; + + public static final int Z_FIELD_NUMBER = 3; + private float z_; + /** + * float z = 3; + * @return The z. */ - public int getRssi() { - return rssi_; + @java.lang.Override + public float getZ() { + return z_; } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; @@ -10412,133 +19379,151 @@ public final boolean isInitialized() { return true; } + @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (relativeTimestamp_ != 0L) { - output.writeInt64(1, relativeTimestamp_); + if (java.lang.Float.floatToRawIntBits(x_) != 0) { + output.writeFloat(1, x_); } - if (mac_ != 0L) { - output.writeInt64(2, mac_); + if (java.lang.Float.floatToRawIntBits(y_) != 0) { + output.writeFloat(2, y_); } - if (rssi_ != 0) { - output.writeInt32(3, rssi_); + if (java.lang.Float.floatToRawIntBits(z_) != 0) { + output.writeFloat(3, z_); } + unknownFields.writeTo(output); } + @java.lang.Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; size = 0; - if (relativeTimestamp_ != 0L) { + if (java.lang.Float.floatToRawIntBits(x_) != 0) { size += com.google.protobuf.CodedOutputStream - .computeInt64Size(1, relativeTimestamp_); + .computeFloatSize(1, x_); } - if (mac_ != 0L) { + if (java.lang.Float.floatToRawIntBits(y_) != 0) { size += com.google.protobuf.CodedOutputStream - .computeInt64Size(2, mac_); + .computeFloatSize(2, y_); } - if (rssi_ != 0) { + if (java.lang.Float.floatToRawIntBits(z_) != 0) { size += com.google.protobuf.CodedOutputStream - .computeInt32Size(3, rssi_); + .computeFloatSize(3, z_); } + size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } - private static final long serialVersionUID = 0L; - @Override - public boolean equals(final Object obj) { + @java.lang.Override + public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof Mac_Scan)) { + if (!(obj instanceof Traj.Vector3)) { return super.equals(obj); } - Mac_Scan other = (Mac_Scan) obj; - - boolean result = true; - result = result && (getRelativeTimestamp() - == other.getRelativeTimestamp()); - result = result && (getMac() - == other.getMac()); - result = result && (getRssi() - == other.getRssi()); - return result; + Traj.Vector3 other = (Traj.Vector3) obj; + + if (java.lang.Float.floatToIntBits(getX()) + != java.lang.Float.floatToIntBits( + other.getX())) return false; + if (java.lang.Float.floatToIntBits(getY()) + != java.lang.Float.floatToIntBits( + other.getY())) return false; + if (java.lang.Float.floatToIntBits(getZ()) + != java.lang.Float.floatToIntBits( + other.getZ())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; } - @Override + @java.lang.Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; - hash = (19 * hash) + getDescriptorForType().hashCode(); - hash = (37 * hash) + RELATIVE_TIMESTAMP_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getRelativeTimestamp()); - hash = (37 * hash) + MAC_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getMac()); - hash = (37 * hash) + RSSI_FIELD_NUMBER; - hash = (53 * hash) + getRssi(); + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + X_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getX()); + hash = (37 * hash) + Y_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getY()); + hash = (37 * hash) + Z_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getZ()); hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } - public static Mac_Scan parseFrom( + public static Traj.Vector3 parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.Vector3 parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.Vector3 parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Mac_Scan parseFrom( + public static Traj.Vector3 parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Mac_Scan parseFrom(byte[] data) + public static Traj.Vector3 parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Mac_Scan parseFrom( + public static Traj.Vector3 parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Mac_Scan parseFrom(java.io.InputStream input) + public static Traj.Vector3 parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Mac_Scan parseFrom( + public static Traj.Vector3 parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static Mac_Scan parseDelimitedFrom(java.io.InputStream input) + public static Traj.Vector3 parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static Mac_Scan parseDelimitedFrom( + public static Traj.Vector3 parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static Mac_Scan parseFrom( + public static Traj.Vector3 parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Mac_Scan parseFrom( + public static Traj.Vector3 parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -10546,44 +19531,51 @@ public static Mac_Scan parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } + @java.lang.Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(Mac_Scan prototype) { + public static Builder newBuilder(Traj.Vector3 prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } - @Override + @java.lang.Override protected Builder newBuilderForType( com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** - * Protobuf type {@code Mac_Scan} + *
+     * --- Common Types ---
+     * 
+ * + * Protobuf type {@code Vector3} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:Mac_Scan) - Mac_ScanOrBuilder { + // @@protoc_insertion_point(builder_implements:Vector3) + Traj.Vector3OrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Mac_Scan_descriptor; + return Traj.internal_static_Vector3_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Mac_Scan_fieldAccessorTable + return Traj.internal_static_Vector3_fieldAccessorTable .ensureFieldAccessorsInitialized( - Mac_Scan.class, Builder.class); + Traj.Vector3.class, Traj.Vector3.Builder.class); } - // Construct using Traj.Mac_Scan.newBuilder() + // Construct using Traj.Vector3.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -10598,106 +19590,121 @@ private void maybeForceBuilderInitialization() { .alwaysUseFieldBuilders) { } } + @java.lang.Override public Builder clear() { super.clear(); - relativeTimestamp_ = 0L; + x_ = 0F; - mac_ = 0L; + y_ = 0F; - rssi_ = 0; + z_ = 0F; return this; } + @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return Traj.internal_static_Mac_Scan_descriptor; + return Traj.internal_static_Vector3_descriptor; } - public Mac_Scan getDefaultInstanceForType() { - return Mac_Scan.getDefaultInstance(); + @java.lang.Override + public Traj.Vector3 getDefaultInstanceForType() { + return Traj.Vector3.getDefaultInstance(); } - public Mac_Scan build() { - Mac_Scan result = buildPartial(); + @java.lang.Override + public Traj.Vector3 build() { + Traj.Vector3 result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } - public Mac_Scan buildPartial() { - Mac_Scan result = new Mac_Scan(this); - result.relativeTimestamp_ = relativeTimestamp_; - result.mac_ = mac_; - result.rssi_ = rssi_; + @java.lang.Override + public Traj.Vector3 buildPartial() { + Traj.Vector3 result = new Traj.Vector3(this); + result.x_ = x_; + result.y_ = y_; + result.z_ = z_; onBuilt(); return result; } + @java.lang.Override public Builder clone() { - return (Builder) super.clone(); + return super.clone(); } + @java.lang.Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); + java.lang.Object value) { + return super.setField(field, value); } + @java.lang.Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); + return super.clearField(field); } + @java.lang.Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); + return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); + java.lang.Object value) { + return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof Mac_Scan) { - return mergeFrom((Mac_Scan)other); + if (other instanceof Traj.Vector3) { + return mergeFrom((Traj.Vector3)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(Mac_Scan other) { - if (other == Mac_Scan.getDefaultInstance()) return this; - if (other.getRelativeTimestamp() != 0L) { - setRelativeTimestamp(other.getRelativeTimestamp()); + public Builder mergeFrom(Traj.Vector3 other) { + if (other == Traj.Vector3.getDefaultInstance()) return this; + if (other.getX() != 0F) { + setX(other.getX()); } - if (other.getMac() != 0L) { - setMac(other.getMac()); + if (other.getY() != 0F) { + setY(other.getY()); } - if (other.getRssi() != 0) { - setRssi(other.getRssi()); + if (other.getZ() != 0F) { + setZ(other.getZ()); } + this.mergeUnknownFields(other.unknownFields); onChanged(); return this; } + @java.lang.Override public final boolean isInitialized() { return true; } + @java.lang.Override public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - Mac_Scan parsedMessage = null; + Traj.Vector3 parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (Mac_Scan) e.getUnfinishedMessage(); + parsedMessage = (Traj.Vector3) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -10707,231 +19714,216 @@ public Builder mergeFrom( return this; } - private long relativeTimestamp_ ; + private float x_ ; /** - * optional int64 relative_timestamp = 1; + * float x = 1; + * @return The x. */ - public long getRelativeTimestamp() { - return relativeTimestamp_; + @java.lang.Override + public float getX() { + return x_; } /** - * optional int64 relative_timestamp = 1; + * float x = 1; + * @param value The x to set. + * @return This builder for chaining. */ - public Builder setRelativeTimestamp(long value) { + public Builder setX(float value) { - relativeTimestamp_ = value; + x_ = value; onChanged(); return this; } /** - * optional int64 relative_timestamp = 1; + * float x = 1; + * @return This builder for chaining. */ - public Builder clearRelativeTimestamp() { + public Builder clearX() { - relativeTimestamp_ = 0L; + x_ = 0F; onChanged(); return this; } - private long mac_ ; + private float y_ ; /** - *
-       * Integer encoding of the hex mac address
-       * e.g. 207394925843984
-       * 
- * - * optional int64 mac = 2; + * float y = 2; + * @return The y. */ - public long getMac() { - return mac_; + @java.lang.Override + public float getY() { + return y_; } /** - *
-       * Integer encoding of the hex mac address
-       * e.g. 207394925843984
-       * 
- * - * optional int64 mac = 2; + * float y = 2; + * @param value The y to set. + * @return This builder for chaining. */ - public Builder setMac(long value) { + public Builder setY(float value) { - mac_ = value; + y_ = value; onChanged(); return this; } /** - *
-       * Integer encoding of the hex mac address
-       * e.g. 207394925843984
-       * 
- * - * optional int64 mac = 2; + * float y = 2; + * @return This builder for chaining. */ - public Builder clearMac() { + public Builder clearY() { - mac_ = 0L; + y_ = 0F; onChanged(); return this; } - private int rssi_ ; + private float z_ ; /** - *
-       * rssi integer in dBm.
-       * typically between -120 and -10
-       * 
- * - * optional int32 rssi = 3; + * float z = 3; + * @return The z. */ - public int getRssi() { - return rssi_; + @java.lang.Override + public float getZ() { + return z_; } /** - *
-       * rssi integer in dBm.
-       * typically between -120 and -10
-       * 
- * - * optional int32 rssi = 3; + * float z = 3; + * @param value The z to set. + * @return This builder for chaining. */ - public Builder setRssi(int value) { + public Builder setZ(float value) { - rssi_ = value; + z_ = value; onChanged(); return this; } /** - *
-       * rssi integer in dBm.
-       * typically between -120 and -10
-       * 
- * - * optional int32 rssi = 3; + * float z = 3; + * @return This builder for chaining. */ - public Builder clearRssi() { + public Builder clearZ() { - rssi_ = 0; + z_ = 0F; onChanged(); return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.setUnknownFields(unknownFields); } + @java.lang.Override public final Builder mergeUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:Mac_Scan) + // @@protoc_insertion_point(builder_scope:Vector3) } - // @@protoc_insertion_point(class_scope:Mac_Scan) - private static final Mac_Scan DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:Vector3) + private static final Traj.Vector3 DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new Mac_Scan(); + DEFAULT_INSTANCE = new Traj.Vector3(); } - public static Mac_Scan getDefaultInstance() { + public static Traj.Vector3 getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - public Mac_Scan parsePartialFrom( + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Vector3 parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { - return new Mac_Scan(input, extensionRegistry); + return new Vector3(input, extensionRegistry); } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } - @Override - public com.google.protobuf.Parser getParserForType() { + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { return PARSER; } - public Mac_Scan getDefaultInstanceForType() { + @java.lang.Override + public Traj.Vector3 getDefaultInstanceForType() { return DEFAULT_INSTANCE; } } - public interface AP_DataOrBuilder extends - // @@protoc_insertion_point(interface_extends:AP_Data) + public interface QuaternionOrBuilder extends + // @@protoc_insertion_point(interface_extends:Quaternion) com.google.protobuf.MessageOrBuilder { /** - *
-     * Integer encoding of the hex mac address
-     * e.g. 207394925843984
-     * 
- * - * optional int64 mac = 1; + * float x = 1; + * @return The x. */ - long getMac(); + float getX(); /** - *
-     * E.g. 'Eduroam' or 'Starbucks_free_wifi'
-     * 
- * - * optional string ssid = 2; + * float y = 2; + * @return The y. */ - String getSsid(); + float getY(); + /** - *
-     * E.g. 'Eduroam' or 'Starbucks_free_wifi'
-     * 
- * - * optional string ssid = 2; + * float z = 3; + * @return The z. */ - com.google.protobuf.ByteString - getSsidBytes(); + float getZ(); /** - *
-     * Typically 2.4GHz or 5GHz
-     * 
- * - * optional int64 frequency = 3; + * float w = 4; + * @return The w. */ - long getFrequency(); + float getW(); } /** - * Protobuf type {@code AP_Data} + * Protobuf type {@code Quaternion} */ - public static final class AP_Data extends + public static final class Quaternion extends com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:AP_Data) - AP_DataOrBuilder { - // Use AP_Data.newBuilder() to construct. - private AP_Data(com.google.protobuf.GeneratedMessageV3.Builder builder) { + // @@protoc_insertion_point(message_implements:Quaternion) + QuaternionOrBuilder { + private static final long serialVersionUID = 0L; + // Use Quaternion.newBuilder() to construct. + private Quaternion(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } - private AP_Data() { - mac_ = 0L; - ssid_ = ""; - frequency_ = 0L; + private Quaternion() { } - @Override + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new Quaternion(); + } + + @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + return this.unknownFields; } - private AP_Data( + private Quaternion( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); - int mutable_bitField0_ = 0; + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { @@ -10940,121 +19932,106 @@ private AP_Data( case 0: done = true; break; - default: { - if (!input.skipField(tag)) { - done = true; - } + case 13: { + + x_ = input.readFloat(); break; } - case 8: { + case 21: { - mac_ = input.readInt64(); + y_ = input.readFloat(); break; } - case 18: { - String s = input.readStringRequireUtf8(); + case 29: { - ssid_ = s; + z_ = input.readFloat(); break; } - case 24: { + case 37: { - frequency_ = input.readInt64(); + w_ = input.readFloat(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } break; } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { + this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_AP_Data_descriptor; + return Traj.internal_static_Quaternion_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_AP_Data_fieldAccessorTable + return Traj.internal_static_Quaternion_fieldAccessorTable .ensureFieldAccessorsInitialized( - AP_Data.class, Builder.class); + Traj.Quaternion.class, Traj.Quaternion.Builder.class); } - public static final int MAC_FIELD_NUMBER = 1; - private long mac_; + public static final int X_FIELD_NUMBER = 1; + private float x_; /** - *
-     * Integer encoding of the hex mac address
-     * e.g. 207394925843984
-     * 
- * - * optional int64 mac = 1; + * float x = 1; + * @return The x. */ - public long getMac() { - return mac_; + @java.lang.Override + public float getX() { + return x_; } - public static final int SSID_FIELD_NUMBER = 2; - private volatile Object ssid_; + public static final int Y_FIELD_NUMBER = 2; + private float y_; /** - *
-     * E.g. 'Eduroam' or 'Starbucks_free_wifi'
-     * 
- * - * optional string ssid = 2; + * float y = 2; + * @return The y. */ - public String getSsid() { - Object ref = ssid_; - if (ref instanceof String) { - return (String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - ssid_ = s; - return s; - } + @java.lang.Override + public float getY() { + return y_; } + + public static final int Z_FIELD_NUMBER = 3; + private float z_; /** - *
-     * E.g. 'Eduroam' or 'Starbucks_free_wifi'
-     * 
- * - * optional string ssid = 2; + * float z = 3; + * @return The z. */ - public com.google.protobuf.ByteString - getSsidBytes() { - Object ref = ssid_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - ssid_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } + @java.lang.Override + public float getZ() { + return z_; } - public static final int FREQUENCY_FIELD_NUMBER = 3; - private long frequency_; + public static final int W_FIELD_NUMBER = 4; + private float w_; /** - *
-     * Typically 2.4GHz or 5GHz
-     * 
- * - * optional int64 frequency = 3; + * float w = 4; + * @return The w. */ - public long getFrequency() { - return frequency_; + @java.lang.Override + public float getW() { + return w_; } private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; @@ -11064,132 +20041,164 @@ public final boolean isInitialized() { return true; } + @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (mac_ != 0L) { - output.writeInt64(1, mac_); + if (java.lang.Float.floatToRawIntBits(x_) != 0) { + output.writeFloat(1, x_); } - if (!getSsidBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 2, ssid_); + if (java.lang.Float.floatToRawIntBits(y_) != 0) { + output.writeFloat(2, y_); } - if (frequency_ != 0L) { - output.writeInt64(3, frequency_); + if (java.lang.Float.floatToRawIntBits(z_) != 0) { + output.writeFloat(3, z_); } + if (java.lang.Float.floatToRawIntBits(w_) != 0) { + output.writeFloat(4, w_); + } + unknownFields.writeTo(output); } + @java.lang.Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; size = 0; - if (mac_ != 0L) { + if (java.lang.Float.floatToRawIntBits(x_) != 0) { size += com.google.protobuf.CodedOutputStream - .computeInt64Size(1, mac_); + .computeFloatSize(1, x_); } - if (!getSsidBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, ssid_); + if (java.lang.Float.floatToRawIntBits(y_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeFloatSize(2, y_); } - if (frequency_ != 0L) { + if (java.lang.Float.floatToRawIntBits(z_) != 0) { size += com.google.protobuf.CodedOutputStream - .computeInt64Size(3, frequency_); + .computeFloatSize(3, z_); + } + if (java.lang.Float.floatToRawIntBits(w_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeFloatSize(4, w_); } + size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } - private static final long serialVersionUID = 0L; - @Override - public boolean equals(final Object obj) { + @java.lang.Override + public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof AP_Data)) { + if (!(obj instanceof Traj.Quaternion)) { return super.equals(obj); } - AP_Data other = (AP_Data) obj; - - boolean result = true; - result = result && (getMac() - == other.getMac()); - result = result && getSsid() - .equals(other.getSsid()); - result = result && (getFrequency() - == other.getFrequency()); - return result; + Traj.Quaternion other = (Traj.Quaternion) obj; + + if (java.lang.Float.floatToIntBits(getX()) + != java.lang.Float.floatToIntBits( + other.getX())) return false; + if (java.lang.Float.floatToIntBits(getY()) + != java.lang.Float.floatToIntBits( + other.getY())) return false; + if (java.lang.Float.floatToIntBits(getZ()) + != java.lang.Float.floatToIntBits( + other.getZ())) return false; + if (java.lang.Float.floatToIntBits(getW()) + != java.lang.Float.floatToIntBits( + other.getW())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; } - @Override + @java.lang.Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; - hash = (19 * hash) + getDescriptorForType().hashCode(); - hash = (37 * hash) + MAC_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getMac()); - hash = (37 * hash) + SSID_FIELD_NUMBER; - hash = (53 * hash) + getSsid().hashCode(); - hash = (37 * hash) + FREQUENCY_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getFrequency()); + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + X_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getX()); + hash = (37 * hash) + Y_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getY()); + hash = (37 * hash) + Z_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getZ()); + hash = (37 * hash) + W_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getW()); hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } - public static AP_Data parseFrom( + public static Traj.Quaternion parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.Quaternion parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.Quaternion parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static AP_Data parseFrom( + public static Traj.Quaternion parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static AP_Data parseFrom(byte[] data) + public static Traj.Quaternion parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static AP_Data parseFrom( + public static Traj.Quaternion parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static AP_Data parseFrom(java.io.InputStream input) + public static Traj.Quaternion parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static AP_Data parseFrom( + public static Traj.Quaternion parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static AP_Data parseDelimitedFrom(java.io.InputStream input) + public static Traj.Quaternion parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static AP_Data parseDelimitedFrom( + public static Traj.Quaternion parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static AP_Data parseFrom( + public static Traj.Quaternion parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static AP_Data parseFrom( + public static Traj.Quaternion parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -11197,44 +20206,47 @@ public static AP_Data parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } + @java.lang.Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(AP_Data prototype) { + public static Builder newBuilder(Traj.Quaternion prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } - @Override + @java.lang.Override protected Builder newBuilderForType( com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** - * Protobuf type {@code AP_Data} + * Protobuf type {@code Quaternion} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:AP_Data) - AP_DataOrBuilder { + // @@protoc_insertion_point(builder_implements:Quaternion) + Traj.QuaternionOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_AP_Data_descriptor; + return Traj.internal_static_Quaternion_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_AP_Data_fieldAccessorTable + return Traj.internal_static_Quaternion_fieldAccessorTable .ensureFieldAccessorsInitialized( - AP_Data.class, Builder.class); + Traj.Quaternion.class, Traj.Quaternion.Builder.class); } - // Construct using Traj.AP_Data.newBuilder() + // Construct using Traj.Quaternion.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -11249,107 +20261,127 @@ private void maybeForceBuilderInitialization() { .alwaysUseFieldBuilders) { } } + @java.lang.Override public Builder clear() { super.clear(); - mac_ = 0L; + x_ = 0F; - ssid_ = ""; + y_ = 0F; - frequency_ = 0L; + z_ = 0F; + + w_ = 0F; return this; } + @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return Traj.internal_static_AP_Data_descriptor; + return Traj.internal_static_Quaternion_descriptor; } - public AP_Data getDefaultInstanceForType() { - return AP_Data.getDefaultInstance(); + @java.lang.Override + public Traj.Quaternion getDefaultInstanceForType() { + return Traj.Quaternion.getDefaultInstance(); } - public AP_Data build() { - AP_Data result = buildPartial(); + @java.lang.Override + public Traj.Quaternion build() { + Traj.Quaternion result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } - public AP_Data buildPartial() { - AP_Data result = new AP_Data(this); - result.mac_ = mac_; - result.ssid_ = ssid_; - result.frequency_ = frequency_; + @java.lang.Override + public Traj.Quaternion buildPartial() { + Traj.Quaternion result = new Traj.Quaternion(this); + result.x_ = x_; + result.y_ = y_; + result.z_ = z_; + result.w_ = w_; onBuilt(); return result; } + @java.lang.Override public Builder clone() { - return (Builder) super.clone(); + return super.clone(); } + @java.lang.Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); + java.lang.Object value) { + return super.setField(field, value); } + @java.lang.Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); + return super.clearField(field); } + @java.lang.Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); + return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); + java.lang.Object value) { + return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof AP_Data) { - return mergeFrom((AP_Data)other); + if (other instanceof Traj.Quaternion) { + return mergeFrom((Traj.Quaternion)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(AP_Data other) { - if (other == AP_Data.getDefaultInstance()) return this; - if (other.getMac() != 0L) { - setMac(other.getMac()); + public Builder mergeFrom(Traj.Quaternion other) { + if (other == Traj.Quaternion.getDefaultInstance()) return this; + if (other.getX() != 0F) { + setX(other.getX()); } - if (!other.getSsid().isEmpty()) { - ssid_ = other.ssid_; - onChanged(); + if (other.getY() != 0F) { + setY(other.getY()); } - if (other.getFrequency() != 0L) { - setFrequency(other.getFrequency()); + if (other.getZ() != 0F) { + setZ(other.getZ()); } + if (other.getW() != 0F) { + setW(other.getW()); + } + this.mergeUnknownFields(other.unknownFields); onChanged(); return this; } + @java.lang.Override public final boolean isInitialized() { return true; } + @java.lang.Override public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - AP_Data parsedMessage = null; + Traj.Quaternion parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (AP_Data) e.getUnfinishedMessage(); + parsedMessage = (Traj.Quaternion) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -11359,297 +20391,285 @@ public Builder mergeFrom( return this; } - private long mac_ ; + private float x_ ; /** - *
-       * Integer encoding of the hex mac address
-       * e.g. 207394925843984
-       * 
- * - * optional int64 mac = 1; + * float x = 1; + * @return The x. */ - public long getMac() { - return mac_; + @java.lang.Override + public float getX() { + return x_; } /** - *
-       * Integer encoding of the hex mac address
-       * e.g. 207394925843984
-       * 
- * - * optional int64 mac = 1; + * float x = 1; + * @param value The x to set. + * @return This builder for chaining. */ - public Builder setMac(long value) { + public Builder setX(float value) { - mac_ = value; + x_ = value; onChanged(); return this; } /** - *
-       * Integer encoding of the hex mac address
-       * e.g. 207394925843984
-       * 
- * - * optional int64 mac = 1; + * float x = 1; + * @return This builder for chaining. */ - public Builder clearMac() { + public Builder clearX() { - mac_ = 0L; + x_ = 0F; onChanged(); return this; } - private Object ssid_ = ""; + private float y_ ; /** - *
-       * E.g. 'Eduroam' or 'Starbucks_free_wifi'
-       * 
- * - * optional string ssid = 2; + * float y = 2; + * @return The y. */ - public String getSsid() { - Object ref = ssid_; - if (!(ref instanceof String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); - ssid_ = s; - return s; - } else { - return (String) ref; - } + @java.lang.Override + public float getY() { + return y_; } /** - *
-       * E.g. 'Eduroam' or 'Starbucks_free_wifi'
-       * 
- * - * optional string ssid = 2; + * float y = 2; + * @param value The y to set. + * @return This builder for chaining. */ - public com.google.protobuf.ByteString - getSsidBytes() { - Object ref = ssid_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); - ssid_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } + public Builder setY(float value) { + + y_ = value; + onChanged(); + return this; } /** - *
-       * E.g. 'Eduroam' or 'Starbucks_free_wifi'
-       * 
- * - * optional string ssid = 2; + * float y = 2; + * @return This builder for chaining. */ - public Builder setSsid( - String value) { - if (value == null) { - throw new NullPointerException(); - } - - ssid_ = value; + public Builder clearY() { + + y_ = 0F; onChanged(); return this; } + + private float z_ ; /** - *
-       * E.g. 'Eduroam' or 'Starbucks_free_wifi'
-       * 
- * - * optional string ssid = 2; + * float z = 3; + * @return The z. */ - public Builder clearSsid() { + @java.lang.Override + public float getZ() { + return z_; + } + /** + * float z = 3; + * @param value The z to set. + * @return This builder for chaining. + */ + public Builder setZ(float value) { - ssid_ = getDefaultInstance().getSsid(); + z_ = value; onChanged(); return this; } /** - *
-       * E.g. 'Eduroam' or 'Starbucks_free_wifi'
-       * 
- * - * optional string ssid = 2; + * float z = 3; + * @return This builder for chaining. */ - public Builder setSsidBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); + public Builder clearZ() { - ssid_ = value; + z_ = 0F; onChanged(); return this; } - private long frequency_ ; + private float w_ ; /** - *
-       * Typically 2.4GHz or 5GHz
-       * 
- * - * optional int64 frequency = 3; + * float w = 4; + * @return The w. */ - public long getFrequency() { - return frequency_; + @java.lang.Override + public float getW() { + return w_; } /** - *
-       * Typically 2.4GHz or 5GHz
-       * 
- * - * optional int64 frequency = 3; + * float w = 4; + * @param value The w to set. + * @return This builder for chaining. */ - public Builder setFrequency(long value) { + public Builder setW(float value) { - frequency_ = value; + w_ = value; onChanged(); return this; } /** - *
-       * Typically 2.4GHz or 5GHz
-       * 
- * - * optional int64 frequency = 3; + * float w = 4; + * @return This builder for chaining. */ - public Builder clearFrequency() { + public Builder clearW() { - frequency_ = 0L; + w_ = 0F; onChanged(); return this; } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.setUnknownFields(unknownFields); } + @java.lang.Override public final Builder mergeUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:AP_Data) + // @@protoc_insertion_point(builder_scope:Quaternion) } - // @@protoc_insertion_point(class_scope:AP_Data) - private static final AP_Data DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:Quaternion) + private static final Traj.Quaternion DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new AP_Data(); + DEFAULT_INSTANCE = new Traj.Quaternion(); } - public static AP_Data getDefaultInstance() { + public static Traj.Quaternion getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - public AP_Data parsePartialFrom( + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public Quaternion parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { - return new AP_Data(input, extensionRegistry); + return new Quaternion(input, extensionRegistry); } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } - @Override - public com.google.protobuf.Parser getParserForType() { + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { return PARSER; } - public AP_Data getDefaultInstanceForType() { + @java.lang.Override + public Traj.Quaternion getDefaultInstanceForType() { return DEFAULT_INSTANCE; } } - public interface Sensor_InfoOrBuilder extends - // @@protoc_insertion_point(interface_extends:Sensor_Info) + public interface SensorInfoOrBuilder extends + // @@protoc_insertion_point(interface_extends:SensorInfo) com.google.protobuf.MessageOrBuilder { /** - * optional string name = 1; + * string name = 1; + * @return The name. */ - String getName(); + java.lang.String getName(); /** - * optional string name = 1; + * string name = 1; + * @return The bytes for name. */ com.google.protobuf.ByteString getNameBytes(); /** - * optional string vendor = 2; + * string vendor = 2; + * @return The vendor. */ - String getVendor(); + java.lang.String getVendor(); /** - * optional string vendor = 2; + * string vendor = 2; + * @return The bytes for vendor. */ com.google.protobuf.ByteString getVendorBytes(); /** - * optional float resolution = 3; + * float resolution = 3; + * @return The resolution. */ float getResolution(); /** - * optional float power = 4; + * float power = 4; + * @return The power. */ float getPower(); /** - * optional int32 version = 5; + * int32 version = 5; + * @return The version. */ int getVersion(); /** - * optional int32 type = 6; + * int32 type = 6; + * @return The type. */ int getType(); + + /** + * float max_range = 7; + * @return The maxRange. + */ + float getMaxRange(); + + /** + * float frequency = 8; + * @return The frequency. + */ + float getFrequency(); } /** - * Protobuf type {@code Sensor_Info} + * Protobuf type {@code SensorInfo} */ - public static final class Sensor_Info extends + public static final class SensorInfo extends com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:Sensor_Info) - Sensor_InfoOrBuilder { - // Use Sensor_Info.newBuilder() to construct. - private Sensor_Info(com.google.protobuf.GeneratedMessageV3.Builder builder) { + // @@protoc_insertion_point(message_implements:SensorInfo) + SensorInfoOrBuilder { + private static final long serialVersionUID = 0L; + // Use SensorInfo.newBuilder() to construct. + private SensorInfo(com.google.protobuf.GeneratedMessageV3.Builder builder) { super(builder); } - private Sensor_Info() { + private SensorInfo() { name_ = ""; vendor_ = ""; - resolution_ = 0F; - power_ = 0F; - version_ = 0; - type_ = 0; } - @Override + @java.lang.Override + @SuppressWarnings({"unused"}) + protected java.lang.Object newInstance( + UnusedPrivateParameter unused) { + return new SensorInfo(); + } + + @java.lang.Override public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + return this.unknownFields; } - private Sensor_Info( + private SensorInfo( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { this(); - int mutable_bitField0_ = 0; + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); try { boolean done = false; while (!done) { @@ -11658,20 +20678,14 @@ private Sensor_Info( case 0: done = true; break; - default: { - if (!input.skipField(tag)) { - done = true; - } - break; - } case 10: { - String s = input.readStringRequireUtf8(); + java.lang.String s = input.readStringRequireUtf8(); name_ = s; break; } case 18: { - String s = input.readStringRequireUtf8(); + java.lang.String s = input.readStringRequireUtf8(); vendor_ = s; break; @@ -11696,56 +20710,81 @@ private Sensor_Info( type_ = input.readInt32(); break; } + case 61: { + + maxRange_ = input.readFloat(); + break; + } + case 69: { + + frequency_ = input.readFloat(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { throw e.setUnfinishedMessage(this); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(this); } catch (java.io.IOException e) { throw new com.google.protobuf.InvalidProtocolBufferException( e).setUnfinishedMessage(this); } finally { + this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } } public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Sensor_Info_descriptor; + return Traj.internal_static_SensorInfo_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Sensor_Info_fieldAccessorTable + return Traj.internal_static_SensorInfo_fieldAccessorTable .ensureFieldAccessorsInitialized( - Sensor_Info.class, Builder.class); + Traj.SensorInfo.class, Traj.SensorInfo.Builder.class); } public static final int NAME_FIELD_NUMBER = 1; - private volatile Object name_; + private volatile java.lang.Object name_; /** - * optional string name = 1; + * string name = 1; + * @return The name. */ - public String getName() { - Object ref = name_; - if (ref instanceof String) { - return (String) ref; + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); + java.lang.String s = bs.toStringUtf8(); name_ = s; return s; } } /** - * optional string name = 1; + * string name = 1; + * @return The bytes for name. */ + @java.lang.Override public com.google.protobuf.ByteString getNameBytes() { - Object ref = name_; - if (ref instanceof String) { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); + (java.lang.String) ref); name_ = b; return b; } else { @@ -11754,32 +20793,36 @@ public String getName() { } public static final int VENDOR_FIELD_NUMBER = 2; - private volatile Object vendor_; + private volatile java.lang.Object vendor_; /** - * optional string vendor = 2; + * string vendor = 2; + * @return The vendor. */ - public String getVendor() { - Object ref = vendor_; - if (ref instanceof String) { - return (String) ref; + @java.lang.Override + public java.lang.String getVendor() { + java.lang.Object ref = vendor_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; } else { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); + java.lang.String s = bs.toStringUtf8(); vendor_ = s; return s; } } /** - * optional string vendor = 2; + * string vendor = 2; + * @return The bytes for vendor. */ + @java.lang.Override public com.google.protobuf.ByteString getVendorBytes() { - Object ref = vendor_; - if (ref instanceof String) { + java.lang.Object ref = vendor_; + if (ref instanceof java.lang.String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); + (java.lang.String) ref); vendor_ = b; return b; } else { @@ -11790,8 +20833,10 @@ public String getVendor() { public static final int RESOLUTION_FIELD_NUMBER = 3; private float resolution_; /** - * optional float resolution = 3; + * float resolution = 3; + * @return The resolution. */ + @java.lang.Override public float getResolution() { return resolution_; } @@ -11799,8 +20844,10 @@ public float getResolution() { public static final int POWER_FIELD_NUMBER = 4; private float power_; /** - * optional float power = 4; + * float power = 4; + * @return The power. */ + @java.lang.Override public float getPower() { return power_; } @@ -11808,8 +20855,10 @@ public float getPower() { public static final int VERSION_FIELD_NUMBER = 5; private int version_; /** - * optional int32 version = 5; + * int32 version = 5; + * @return The version. */ + @java.lang.Override public int getVersion() { return version_; } @@ -11817,13 +20866,38 @@ public int getVersion() { public static final int TYPE_FIELD_NUMBER = 6; private int type_; /** - * optional int32 type = 6; + * int32 type = 6; + * @return The type. */ + @java.lang.Override public int getType() { return type_; } + public static final int MAX_RANGE_FIELD_NUMBER = 7; + private float maxRange_; + /** + * float max_range = 7; + * @return The maxRange. + */ + @java.lang.Override + public float getMaxRange() { + return maxRange_; + } + + public static final int FREQUENCY_FIELD_NUMBER = 8; + private float frequency_; + /** + * float frequency = 8; + * @return The frequency. + */ + @java.lang.Override + public float getFrequency() { + return frequency_; + } + private byte memoizedIsInitialized = -1; + @java.lang.Override public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; if (isInitialized == 1) return true; @@ -11833,18 +20907,19 @@ public final boolean isInitialized() { return true; } + @java.lang.Override public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!getNameBytes().isEmpty()) { + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(name_)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 1, name_); } - if (!getVendorBytes().isEmpty()) { + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(vendor_)) { com.google.protobuf.GeneratedMessageV3.writeString(output, 2, vendor_); } - if (resolution_ != 0F) { + if (java.lang.Float.floatToRawIntBits(resolution_) != 0) { output.writeFloat(3, resolution_); } - if (power_ != 0F) { + if (java.lang.Float.floatToRawIntBits(power_) != 0) { output.writeFloat(4, power_); } if (version_ != 0) { @@ -11853,24 +20928,32 @@ public void writeTo(com.google.protobuf.CodedOutputStream output) if (type_ != 0) { output.writeInt32(6, type_); } + if (java.lang.Float.floatToRawIntBits(maxRange_) != 0) { + output.writeFloat(7, maxRange_); + } + if (java.lang.Float.floatToRawIntBits(frequency_) != 0) { + output.writeFloat(8, frequency_); + } + unknownFields.writeTo(output); } + @java.lang.Override public int getSerializedSize() { int size = memoizedSize; if (size != -1) return size; size = 0; - if (!getNameBytes().isEmpty()) { + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(name_)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, name_); } - if (!getVendorBytes().isEmpty()) { + if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(vendor_)) { size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, vendor_); } - if (resolution_ != 0F) { + if (java.lang.Float.floatToRawIntBits(resolution_) != 0) { size += com.google.protobuf.CodedOutputStream .computeFloatSize(3, resolution_); } - if (power_ != 0F) { + if (java.lang.Float.floatToRawIntBits(power_) != 0) { size += com.google.protobuf.CodedOutputStream .computeFloatSize(4, power_); } @@ -11882,119 +20965,148 @@ public int getSerializedSize() { size += com.google.protobuf.CodedOutputStream .computeInt32Size(6, type_); } + if (java.lang.Float.floatToRawIntBits(maxRange_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeFloatSize(7, maxRange_); + } + if (java.lang.Float.floatToRawIntBits(frequency_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeFloatSize(8, frequency_); + } + size += unknownFields.getSerializedSize(); memoizedSize = size; return size; } - private static final long serialVersionUID = 0L; - @Override - public boolean equals(final Object obj) { + @java.lang.Override + public boolean equals(final java.lang.Object obj) { if (obj == this) { return true; } - if (!(obj instanceof Sensor_Info)) { + if (!(obj instanceof Traj.SensorInfo)) { return super.equals(obj); } - Sensor_Info other = (Sensor_Info) obj; - - boolean result = true; - result = result && getName() - .equals(other.getName()); - result = result && getVendor() - .equals(other.getVendor()); - result = result && ( - Float.floatToIntBits(getResolution()) - == Float.floatToIntBits( - other.getResolution())); - result = result && ( - Float.floatToIntBits(getPower()) - == Float.floatToIntBits( - other.getPower())); - result = result && (getVersion() - == other.getVersion()); - result = result && (getType() - == other.getType()); - return result; - } - - @Override + Traj.SensorInfo other = (Traj.SensorInfo) obj; + + if (!getName() + .equals(other.getName())) return false; + if (!getVendor() + .equals(other.getVendor())) return false; + if (java.lang.Float.floatToIntBits(getResolution()) + != java.lang.Float.floatToIntBits( + other.getResolution())) return false; + if (java.lang.Float.floatToIntBits(getPower()) + != java.lang.Float.floatToIntBits( + other.getPower())) return false; + if (getVersion() + != other.getVersion()) return false; + if (getType() + != other.getType()) return false; + if (java.lang.Float.floatToIntBits(getMaxRange()) + != java.lang.Float.floatToIntBits( + other.getMaxRange())) return false; + if (java.lang.Float.floatToIntBits(getFrequency()) + != java.lang.Float.floatToIntBits( + other.getFrequency())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override public int hashCode() { if (memoizedHashCode != 0) { return memoizedHashCode; } int hash = 41; - hash = (19 * hash) + getDescriptorForType().hashCode(); + hash = (19 * hash) + getDescriptor().hashCode(); hash = (37 * hash) + NAME_FIELD_NUMBER; hash = (53 * hash) + getName().hashCode(); hash = (37 * hash) + VENDOR_FIELD_NUMBER; hash = (53 * hash) + getVendor().hashCode(); hash = (37 * hash) + RESOLUTION_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( + hash = (53 * hash) + java.lang.Float.floatToIntBits( getResolution()); hash = (37 * hash) + POWER_FIELD_NUMBER; - hash = (53 * hash) + Float.floatToIntBits( + hash = (53 * hash) + java.lang.Float.floatToIntBits( getPower()); hash = (37 * hash) + VERSION_FIELD_NUMBER; hash = (53 * hash) + getVersion(); hash = (37 * hash) + TYPE_FIELD_NUMBER; hash = (53 * hash) + getType(); + hash = (37 * hash) + MAX_RANGE_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getMaxRange()); + hash = (37 * hash) + FREQUENCY_FIELD_NUMBER; + hash = (53 * hash) + java.lang.Float.floatToIntBits( + getFrequency()); hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; } - public static Sensor_Info parseFrom( + public static Traj.SensorInfo parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static Traj.SensorInfo parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static Traj.SensorInfo parseFrom( com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Sensor_Info parseFrom( + public static Traj.SensorInfo parseFrom( com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Sensor_Info parseFrom(byte[] data) + public static Traj.SensorInfo parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data); } - public static Sensor_Info parseFrom( + public static Traj.SensorInfo parseFrom( byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { return PARSER.parseFrom(data, extensionRegistry); } - public static Sensor_Info parseFrom(java.io.InputStream input) + public static Traj.SensorInfo parseFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Sensor_Info parseFrom( + public static Traj.SensorInfo parseFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input, extensionRegistry); } - public static Sensor_Info parseDelimitedFrom(java.io.InputStream input) + public static Traj.SensorInfo parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input); } - public static Sensor_Info parseDelimitedFrom( + public static Traj.SensorInfo parseDelimitedFrom( java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseDelimitedWithIOException(PARSER, input, extensionRegistry); } - public static Sensor_Info parseFrom( + public static Traj.SensorInfo parseFrom( com.google.protobuf.CodedInputStream input) throws java.io.IOException { return com.google.protobuf.GeneratedMessageV3 .parseWithIOException(PARSER, input); } - public static Sensor_Info parseFrom( + public static Traj.SensorInfo parseFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { @@ -12002,44 +21114,47 @@ public static Sensor_Info parseFrom( .parseWithIOException(PARSER, input, extensionRegistry); } + @java.lang.Override public Builder newBuilderForType() { return newBuilder(); } public static Builder newBuilder() { return DEFAULT_INSTANCE.toBuilder(); } - public static Builder newBuilder(Sensor_Info prototype) { + public static Builder newBuilder(Traj.SensorInfo prototype) { return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); } + @java.lang.Override public Builder toBuilder() { return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); } - @Override + @java.lang.Override protected Builder newBuilderForType( com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { Builder builder = new Builder(parent); return builder; } /** - * Protobuf type {@code Sensor_Info} + * Protobuf type {@code SensorInfo} */ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:Sensor_Info) - Sensor_InfoOrBuilder { + // @@protoc_insertion_point(builder_implements:SensorInfo) + Traj.SensorInfoOrBuilder { public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return Traj.internal_static_Sensor_Info_descriptor; + return Traj.internal_static_SensorInfo_descriptor; } + @java.lang.Override protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return Traj.internal_static_Sensor_Info_fieldAccessorTable + return Traj.internal_static_SensorInfo_fieldAccessorTable .ensureFieldAccessorsInitialized( - Sensor_Info.class, Builder.class); + Traj.SensorInfo.class, Traj.SensorInfo.Builder.class); } - // Construct using Traj.Sensor_Info.newBuilder() + // Construct using Traj.SensorInfo.newBuilder() private Builder() { maybeForceBuilderInitialization(); } @@ -12054,6 +21169,7 @@ private void maybeForceBuilderInitialization() { .alwaysUseFieldBuilders) { } } + @java.lang.Override public Builder clear() { super.clear(); name_ = ""; @@ -12068,75 +21184,92 @@ public Builder clear() { type_ = 0; + maxRange_ = 0F; + + frequency_ = 0F; + return this; } + @java.lang.Override public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return Traj.internal_static_Sensor_Info_descriptor; + return Traj.internal_static_SensorInfo_descriptor; } - public Sensor_Info getDefaultInstanceForType() { - return Sensor_Info.getDefaultInstance(); + @java.lang.Override + public Traj.SensorInfo getDefaultInstanceForType() { + return Traj.SensorInfo.getDefaultInstance(); } - public Sensor_Info build() { - Sensor_Info result = buildPartial(); + @java.lang.Override + public Traj.SensorInfo build() { + Traj.SensorInfo result = buildPartial(); if (!result.isInitialized()) { throw newUninitializedMessageException(result); } return result; } - public Sensor_Info buildPartial() { - Sensor_Info result = new Sensor_Info(this); + @java.lang.Override + public Traj.SensorInfo buildPartial() { + Traj.SensorInfo result = new Traj.SensorInfo(this); result.name_ = name_; result.vendor_ = vendor_; result.resolution_ = resolution_; result.power_ = power_; result.version_ = version_; result.type_ = type_; + result.maxRange_ = maxRange_; + result.frequency_ = frequency_; onBuilt(); return result; } + @java.lang.Override public Builder clone() { - return (Builder) super.clone(); + return super.clone(); } + @java.lang.Override public Builder setField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); + java.lang.Object value) { + return super.setField(field, value); } + @java.lang.Override public Builder clearField( com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); + return super.clearField(field); } + @java.lang.Override public Builder clearOneof( com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); + return super.clearOneof(oneof); } + @java.lang.Override public Builder setRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); } + @java.lang.Override public Builder addRepeatedField( com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); + java.lang.Object value) { + return super.addRepeatedField(field, value); } + @java.lang.Override public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof Sensor_Info) { - return mergeFrom((Sensor_Info)other); + if (other instanceof Traj.SensorInfo) { + return mergeFrom((Traj.SensorInfo)other); } else { super.mergeFrom(other); return this; } } - public Builder mergeFrom(Sensor_Info other) { - if (other == Sensor_Info.getDefaultInstance()) return this; + public Builder mergeFrom(Traj.SensorInfo other) { + if (other == Traj.SensorInfo.getDefaultInstance()) return this; if (!other.getName().isEmpty()) { name_ = other.name_; onChanged(); @@ -12157,23 +21290,32 @@ public Builder mergeFrom(Sensor_Info other) { if (other.getType() != 0) { setType(other.getType()); } + if (other.getMaxRange() != 0F) { + setMaxRange(other.getMaxRange()); + } + if (other.getFrequency() != 0F) { + setFrequency(other.getFrequency()); + } + this.mergeUnknownFields(other.unknownFields); onChanged(); return this; } + @java.lang.Override public final boolean isInitialized() { return true; } + @java.lang.Override public Builder mergeFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - Sensor_Info parsedMessage = null; + Traj.SensorInfo parsedMessage = null; try { parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (Sensor_Info) e.getUnfinishedMessage(); + parsedMessage = (Traj.SensorInfo) e.getUnfinishedMessage(); throw e.unwrapIOException(); } finally { if (parsedMessage != null) { @@ -12183,32 +21325,34 @@ public Builder mergeFrom( return this; } - private Object name_ = ""; + private java.lang.Object name_ = ""; /** - * optional string name = 1; + * string name = 1; + * @return The name. */ - public String getName() { - Object ref = name_; - if (!(ref instanceof String)) { + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); + java.lang.String s = bs.toStringUtf8(); name_ = s; return s; } else { - return (String) ref; + return (java.lang.String) ref; } } /** - * optional string name = 1; + * string name = 1; + * @return The bytes for name. */ public com.google.protobuf.ByteString getNameBytes() { - Object ref = name_; + java.lang.Object ref = name_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); + (java.lang.String) ref); name_ = b; return b; } else { @@ -12216,10 +21360,12 @@ public String getName() { } } /** - * optional string name = 1; + * string name = 1; + * @param value The name to set. + * @return This builder for chaining. */ public Builder setName( - String value) { + java.lang.String value) { if (value == null) { throw new NullPointerException(); } @@ -12229,7 +21375,8 @@ public Builder setName( return this; } /** - * optional string name = 1; + * string name = 1; + * @return This builder for chaining. */ public Builder clearName() { @@ -12238,7 +21385,9 @@ public Builder clearName() { return this; } /** - * optional string name = 1; + * string name = 1; + * @param value The bytes for name to set. + * @return This builder for chaining. */ public Builder setNameBytes( com.google.protobuf.ByteString value) { @@ -12252,32 +21401,34 @@ public Builder setNameBytes( return this; } - private Object vendor_ = ""; + private java.lang.Object vendor_ = ""; /** - * optional string vendor = 2; + * string vendor = 2; + * @return The vendor. */ - public String getVendor() { - Object ref = vendor_; - if (!(ref instanceof String)) { + public java.lang.String getVendor() { + java.lang.Object ref = vendor_; + if (!(ref instanceof java.lang.String)) { com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; - String s = bs.toStringUtf8(); + java.lang.String s = bs.toStringUtf8(); vendor_ = s; return s; } else { - return (String) ref; + return (java.lang.String) ref; } } /** - * optional string vendor = 2; + * string vendor = 2; + * @return The bytes for vendor. */ public com.google.protobuf.ByteString getVendorBytes() { - Object ref = vendor_; + java.lang.Object ref = vendor_; if (ref instanceof String) { com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8( - (String) ref); + (java.lang.String) ref); vendor_ = b; return b; } else { @@ -12285,10 +21436,12 @@ public String getVendor() { } } /** - * optional string vendor = 2; + * string vendor = 2; + * @param value The vendor to set. + * @return This builder for chaining. */ public Builder setVendor( - String value) { + java.lang.String value) { if (value == null) { throw new NullPointerException(); } @@ -12298,7 +21451,8 @@ public Builder setVendor( return this; } /** - * optional string vendor = 2; + * string vendor = 2; + * @return This builder for chaining. */ public Builder clearVendor() { @@ -12307,7 +21461,9 @@ public Builder clearVendor() { return this; } /** - * optional string vendor = 2; + * string vendor = 2; + * @param value The bytes for vendor to set. + * @return This builder for chaining. */ public Builder setVendorBytes( com.google.protobuf.ByteString value) { @@ -12323,13 +21479,17 @@ public Builder setVendorBytes( private float resolution_ ; /** - * optional float resolution = 3; + * float resolution = 3; + * @return The resolution. */ + @java.lang.Override public float getResolution() { return resolution_; } /** - * optional float resolution = 3; + * float resolution = 3; + * @param value The resolution to set. + * @return This builder for chaining. */ public Builder setResolution(float value) { @@ -12338,7 +21498,8 @@ public Builder setResolution(float value) { return this; } /** - * optional float resolution = 3; + * float resolution = 3; + * @return This builder for chaining. */ public Builder clearResolution() { @@ -12349,13 +21510,17 @@ public Builder clearResolution() { private float power_ ; /** - * optional float power = 4; + * float power = 4; + * @return The power. */ + @java.lang.Override public float getPower() { return power_; } /** - * optional float power = 4; + * float power = 4; + * @param value The power to set. + * @return This builder for chaining. */ public Builder setPower(float value) { @@ -12364,7 +21529,8 @@ public Builder setPower(float value) { return this; } /** - * optional float power = 4; + * float power = 4; + * @return This builder for chaining. */ public Builder clearPower() { @@ -12375,13 +21541,17 @@ public Builder clearPower() { private int version_ ; /** - * optional int32 version = 5; + * int32 version = 5; + * @return The version. */ + @java.lang.Override public int getVersion() { return version_; } /** - * optional int32 version = 5; + * int32 version = 5; + * @param value The version to set. + * @return This builder for chaining. */ public Builder setVersion(int value) { @@ -12390,7 +21560,8 @@ public Builder setVersion(int value) { return this; } /** - * optional int32 version = 5; + * int32 version = 5; + * @return This builder for chaining. */ public Builder clearVersion() { @@ -12401,13 +21572,17 @@ public Builder clearVersion() { private int type_ ; /** - * optional int32 type = 6; + * int32 type = 6; + * @return The type. */ + @java.lang.Override public int getType() { return type_; } /** - * optional int32 type = 6; + * int32 type = 6; + * @param value The type to set. + * @return This builder for chaining. */ public Builder setType(int value) { @@ -12416,7 +21591,8 @@ public Builder setType(int value) { return this; } /** - * optional int32 type = 6; + * int32 type = 6; + * @return This builder for chaining. */ public Builder clearType() { @@ -12424,50 +21600,116 @@ public Builder clearType() { onChanged(); return this; } + + private float maxRange_ ; + /** + * float max_range = 7; + * @return The maxRange. + */ + @java.lang.Override + public float getMaxRange() { + return maxRange_; + } + /** + * float max_range = 7; + * @param value The maxRange to set. + * @return This builder for chaining. + */ + public Builder setMaxRange(float value) { + + maxRange_ = value; + onChanged(); + return this; + } + /** + * float max_range = 7; + * @return This builder for chaining. + */ + public Builder clearMaxRange() { + + maxRange_ = 0F; + onChanged(); + return this; + } + + private float frequency_ ; + /** + * float frequency = 8; + * @return The frequency. + */ + @java.lang.Override + public float getFrequency() { + return frequency_; + } + /** + * float frequency = 8; + * @param value The frequency to set. + * @return This builder for chaining. + */ + public Builder setFrequency(float value) { + + frequency_ = value; + onChanged(); + return this; + } + /** + * float frequency = 8; + * @return This builder for chaining. + */ + public Builder clearFrequency() { + + frequency_ = 0F; + onChanged(); + return this; + } + @java.lang.Override public final Builder setUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.setUnknownFields(unknownFields); } + @java.lang.Override public final Builder mergeUnknownFields( final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; + return super.mergeUnknownFields(unknownFields); } - // @@protoc_insertion_point(builder_scope:Sensor_Info) + // @@protoc_insertion_point(builder_scope:SensorInfo) } - // @@protoc_insertion_point(class_scope:Sensor_Info) - private static final Sensor_Info DEFAULT_INSTANCE; + // @@protoc_insertion_point(class_scope:SensorInfo) + private static final Traj.SensorInfo DEFAULT_INSTANCE; static { - DEFAULT_INSTANCE = new Sensor_Info(); + DEFAULT_INSTANCE = new Traj.SensorInfo(); } - public static Sensor_Info getDefaultInstance() { + public static Traj.SensorInfo getDefaultInstance() { return DEFAULT_INSTANCE; } - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - public Sensor_Info parsePartialFrom( + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public SensorInfo parsePartialFrom( com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws com.google.protobuf.InvalidProtocolBufferException { - return new Sensor_Info(input, extensionRegistry); + return new SensorInfo(input, extensionRegistry); } }; - public static com.google.protobuf.Parser parser() { + public static com.google.protobuf.Parser parser() { return PARSER; } - @Override - public com.google.protobuf.Parser getParserForType() { + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { return PARSER; } - public Sensor_Info getDefaultInstanceForType() { + @java.lang.Override + public Traj.SensorInfo getDefaultInstanceForType() { return DEFAULT_INSTANCE; } @@ -12479,55 +21721,85 @@ public Sensor_Info getDefaultInstanceForType() { com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_Trajectory_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_Pdr_Sample_descriptor; + internal_static_RelativePosition_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_RelativePosition_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_IMUReading_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_IMUReading_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_MagnetometerReading_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_MagnetometerReading_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_BarometerReading_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_BarometerReading_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_LightReading_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_LightReading_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_ProximityReading_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_ProximityReading_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_GNSSPosition_descriptor; private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_Pdr_Sample_fieldAccessorTable; + internal_static_GNSSPosition_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_Motion_Sample_descriptor; + internal_static_GNSSReading_descriptor; private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_Motion_Sample_fieldAccessorTable; + internal_static_GNSSReading_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_Position_Sample_descriptor; + internal_static_Fingerprint_descriptor; private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_Position_Sample_fieldAccessorTable; + internal_static_Fingerprint_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_Pressure_Sample_descriptor; + internal_static_RFScan_descriptor; private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_Pressure_Sample_fieldAccessorTable; + internal_static_RFScan_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_Light_Sample_descriptor; + internal_static_WiFiRTTReading_descriptor; private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_Light_Sample_fieldAccessorTable; + internal_static_WiFiRTTReading_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_GNSS_Sample_descriptor; + internal_static_WiFiAPData_descriptor; private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_GNSS_Sample_fieldAccessorTable; + internal_static_WiFiAPData_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_WiFi_Sample_descriptor; + internal_static_BleData_descriptor; private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_WiFi_Sample_fieldAccessorTable; + internal_static_BleData_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_Mac_Scan_descriptor; + internal_static_Vector3_descriptor; private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_Mac_Scan_fieldAccessorTable; + internal_static_Vector3_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_AP_Data_descriptor; + internal_static_Quaternion_descriptor; private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_AP_Data_fieldAccessorTable; + internal_static_Quaternion_fieldAccessorTable; private static final com.google.protobuf.Descriptors.Descriptor - internal_static_Sensor_Info_descriptor; + internal_static_SensorInfo_descriptor; private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_Sensor_Info_fieldAccessorTable; + internal_static_SensorInfo_fieldAccessorTable; public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { @@ -12536,128 +21808,177 @@ public Sensor_Info getDefaultInstanceForType() { private static com.google.protobuf.Descriptors.FileDescriptor descriptor; static { - String[] descriptorData = { - "\n#Cloud/app/src/main/proto/traj.proto\"\337\004" + - "\n\nTrajectory\022\027\n\017android_version\030\001 \001(\t\022 \n" + - "\010imu_data\030\002 \003(\0132\016.Motion_Sample\022\035\n\010pdr_d" + - "ata\030\003 \003(\0132\013.Pdr_Sample\022\'\n\rposition_data\030" + - "\004 \003(\0132\020.Position_Sample\022\'\n\rpressure_data" + - "\030\005 \003(\0132\020.Pressure_Sample\022!\n\nlight_data\030\006" + - " \003(\0132\r.Light_Sample\022\037\n\tgnss_data\030\007 \003(\0132\014" + - ".GNSS_Sample\022\037\n\twifi_data\030\010 \003(\0132\014.WiFi_S" + - "ample\022\032\n\010aps_data\030\t \003(\0132\010.AP_Data\022\027\n\017sta" + - "rt_timestamp\030\n \001(\003\022\027\n\017data_identifier\030\013 ", - "\001(\t\022(\n\022accelerometer_info\030\014 \001(\0132\014.Sensor" + - "_Info\022$\n\016gyroscope_info\030\r \001(\0132\014.Sensor_I" + - "nfo\022*\n\024rotation_vector_info\030\016 \001(\0132\014.Sens" + - "or_Info\022\'\n\021magnetometer_info\030\017 \001(\0132\014.Sen" + - "sor_Info\022$\n\016barometer_info\030\020 \001(\0132\014.Senso" + - "r_Info\022\'\n\021light_sensor_info\030\021 \001(\0132\014.Sens" + - "or_Info\">\n\nPdr_Sample\022\032\n\022relative_timest" + - "amp\030\001 \001(\003\022\t\n\001x\030\002 \001(\002\022\t\n\001y\030\003 \001(\002\"\205\002\n\rMoti" + - "on_Sample\022\032\n\022relative_timestamp\030\001 \001(\003\022\r\n" + - "\005acc_x\030\002 \001(\002\022\r\n\005acc_y\030\003 \001(\002\022\r\n\005acc_z\030\004 \001", - "(\002\022\r\n\005gyr_x\030\005 \001(\002\022\r\n\005gyr_y\030\006 \001(\002\022\r\n\005gyr_" + - "z\030\007 \001(\002\022\031\n\021rotation_vector_x\030\010 \001(\002\022\031\n\021ro" + - "tation_vector_y\030\t \001(\002\022\031\n\021rotation_vector" + - "_z\030\n \001(\002\022\031\n\021rotation_vector_w\030\013 \001(\002\022\022\n\ns" + - "tep_count\030\014 \001(\005\"Z\n\017Position_Sample\022\032\n\022re" + - "lative_timestamp\030\001 \001(\003\022\r\n\005mag_x\030\002 \001(\002\022\r\n" + - "\005mag_y\030\003 \001(\002\022\r\n\005mag_z\030\004 \001(\002\"?\n\017Pressure_" + - "Sample\022\032\n\022relative_timestamp\030\001 \001(\003\022\020\n\010pr" + - "essure\030\002 \001(\002\"9\n\014Light_Sample\022\032\n\022relative" + - "_timestamp\030\001 \001(\003\022\r\n\005light\030\002 \001(\002\"\223\001\n\013GNSS", - "_Sample\022\032\n\022relative_timestamp\030\001 \001(\003\022\020\n\010l" + - "atitude\030\002 \001(\002\022\021\n\tlongitude\030\003 \001(\002\022\020\n\010alti" + - "tude\030\004 \001(\002\022\020\n\010accuracy\030\005 \001(\002\022\r\n\005speed\030\006 " + - "\001(\002\022\020\n\010provider\030\007 \001(\t\"G\n\013WiFi_Sample\022\032\n\022" + - "relative_timestamp\030\001 \001(\003\022\034\n\tmac_scans\030\002 " + - "\003(\0132\t.Mac_Scan\"A\n\010Mac_Scan\022\032\n\022relative_t" + - "imestamp\030\001 \001(\003\022\013\n\003mac\030\002 \001(\003\022\014\n\004rssi\030\003 \001(" + - "\005\"7\n\007AP_Data\022\013\n\003mac\030\001 \001(\003\022\014\n\004ssid\030\002 \001(\t\022" + - "\021\n\tfrequency\030\003 \001(\003\"m\n\013Sensor_Info\022\014\n\004nam" + - "e\030\001 \001(\t\022\016\n\006vendor\030\002 \001(\t\022\022\n\nresolution\030\003 ", - "\001(\002\022\r\n\005power\030\004 \001(\002\022\017\n\007version\030\005 \001(\005\022\014\n\004t" + - "ype\030\006 \001(\005b\006proto3" + java.lang.String[] descriptorData = { + "\n\035app/src/main/proto/traj.proto\"\277\007\n\nTraj" + + "ectory\022\027\n\017android_version\030\001 \001(\t\022\032\n\022traje" + + "ctory_version\030\002 \001(\002\022\025\n\rtrajectory_id\030\003 \001" + + "(\t\022\035\n\010imu_data\030\004 \003(\0132\013.IMUReading\022#\n\010pdr" + + "_data\030\005 \003(\0132\021.RelativePosition\022/\n\021magnet" + + "ometer_data\030\006 \003(\0132\024.MagnetometerReading\022" + + "(\n\rpressure_data\030\007 \003(\0132\021.BarometerReadin" + + "g\022!\n\nlight_data\030\010 \003(\0132\r.LightReading\022)\n\016" + + "proximity_data\030\t \003(\0132\021.ProximityReading\022" + + "\037\n\tgnss_data\030\n \003(\0132\014.GNSSReading\022\'\n\021wifi" + + "_fingerprints\030\013 \003(\0132\014.Fingerprint\022\035\n\010aps" + + "_data\030\014 \003(\0132\013.WiFiAPData\022&\n\rwifi_rtt_dat" + + "a\030\r \003(\0132\017.WiFiRTTReading\022&\n\020ble_fingerpr" + + "ints\030\016 \003(\0132\014.Fingerprint\022\032\n\010ble_data\030\017 \003" + + "(\0132\010.BleData\022\027\n\017start_timestamp\030\020 \001(\003\022\'\n" + + "\020initial_position\030\021 \001(\0132\r.GNSSPosition\022*" + + "\n\023corrected_positions\030\022 \003(\0132\r.GNSSPositi" + + "on\022\'\n\022accelerometer_info\030\023 \001(\0132\013.SensorI" + + "nfo\022#\n\016gyroscope_info\030\024 \001(\0132\013.SensorInfo" + + "\022)\n\024rotation_vector_info\030\025 \001(\0132\013.SensorI" + + "nfo\022&\n\021magnetometer_info\030\026 \001(\0132\013.SensorI" + + "nfo\022#\n\016barometer_info\030\027 \001(\0132\013.SensorInfo" + + "\022&\n\021light_sensor_info\030\030 \001(\0132\013.SensorInfo" + + "\022#\n\016proximity_info\030\031 \001(\0132\013.SensorInfo\022\"\n" + + "\013test_points\030\032 \003(\0132\r.GNSSPosition\"D\n\020Rel" + + "ativePosition\022\032\n\022relative_timestamp\030\001 \001(" + + "\003\022\t\n\001x\030\002 \001(\002\022\t\n\001y\030\003 \001(\002\"\220\001\n\nIMUReading\022\032" + + "\n\022relative_timestamp\030\001 \001(\003\022\025\n\003acc\030\002 \001(\0132" + + "\010.Vector3\022\025\n\003gyr\030\003 \001(\0132\010.Vector3\022$\n\017rota" + + "tion_vector\030\004 \001(\0132\013.Quaternion\022\022\n\nstep_c" + + "ount\030\005 \001(\005\"H\n\023MagnetometerReading\022\032\n\022rel" + + "ative_timestamp\030\001 \001(\003\022\025\n\003mag\030\002 \001(\0132\010.Vec" + + "tor3\"@\n\020BarometerReading\022\032\n\022relative_tim" + + "estamp\030\001 \001(\003\022\020\n\010pressure\030\002 \001(\002\"9\n\014LightR" + + "eading\022\032\n\022relative_timestamp\030\001 \001(\003\022\r\n\005li" + + "ght\030\002 \001(\002\"@\n\020ProximityReading\022\032\n\022relativ" + + "e_timestamp\030\001 \001(\003\022\020\n\010distance\030\002 \001(\002\"\177\n\014G" + + "NSSPosition\022\032\n\022relative_timestamp\030\001 \001(\003\022" + + "\020\n\010latitude\030\002 \001(\001\022\021\n\tlongitude\030\003 \001(\001\022\020\n\010" + + "altitude\030\004 \001(\001\022\022\n\005floor\030\005 \001(\tH\000\210\001\001B\010\n\006_f" + + "loor\"r\n\013GNSSReading\022\037\n\010position\030\001 \001(\0132\r." + + "GNSSPosition\022\020\n\010accuracy\030\002 \001(\002\022\r\n\005speed\030" + + "\003 \001(\002\022\017\n\007bearing\030\004 \001(\002\022\020\n\010provider\030\005 \001(\t" + + "\"D\n\013Fingerprint\022\032\n\022relative_timestamp\030\001 " + + "\001(\003\022\031\n\010rf_scans\030\002 \003(\0132\007.RFScan\"r\n\006RFScan" + + "\022\032\n\022relative_timestamp\030\001 \001(\003\022\013\n\003mac\030\002 \001(" + + "\003\022\014\n\004rssi\030\003 \001(\005\022$\n\010position\030\004 \001(\0132\r.GNSS" + + "PositionH\000\210\001\001B\013\n\t_position\"o\n\016WiFiRTTRea" + + "ding\022\032\n\022relative_timestamp\030\001 \001(\003\022\013\n\003mac\030" + + "\002 \001(\003\022\020\n\010distance\030\003 \001(\002\022\024\n\014distance_std\030" + + "\004 \001(\002\022\014\n\004rssi\030\005 \001(\005\"O\n\nWiFiAPData\022\013\n\003mac" + + "\030\001 \001(\003\022\014\n\004ssid\030\002 \001(\t\022\021\n\tfrequency\030\003 \001(\003\022" + + "\023\n\013rtt_enabled\030\004 \001(\010\"\217\001\n\007BleData\022\023\n\013mac_" + + "address\030\001 \001(\t\022\014\n\004name\030\002 \001(\t\022\026\n\016tx_power_" + + "level\030\003 \001(\005\022\027\n\017advertise_flags\030\004 \001(\005\022\025\n\r" + + "service_uuids\030\005 \003(\t\022\031\n\021manufacturer_data" + + "\030\006 \001(\014\"*\n\007Vector3\022\t\n\001x\030\001 \001(\002\022\t\n\001y\030\002 \001(\002\022" + + "\t\n\001z\030\003 \001(\002\"8\n\nQuaternion\022\t\n\001x\030\001 \001(\002\022\t\n\001y" + + "\030\002 \001(\002\022\t\n\001z\030\003 \001(\002\022\t\n\001w\030\004 \001(\002\"\222\001\n\nSensorI" + + "nfo\022\014\n\004name\030\001 \001(\t\022\016\n\006vendor\030\002 \001(\t\022\022\n\nres" + + "olution\030\003 \001(\002\022\r\n\005power\030\004 \001(\002\022\017\n\007version\030" + + "\005 \001(\005\022\014\n\004type\030\006 \001(\005\022\021\n\tmax_range\030\007 \001(\002\022\021" + + "\n\tfrequency\030\010 \001(\002b\006proto3" }; - com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { - public com.google.protobuf.ExtensionRegistry assignDescriptors( - com.google.protobuf.Descriptors.FileDescriptor root) { - descriptor = root; - return null; - } - }; - com.google.protobuf.Descriptors.FileDescriptor + descriptor = com.google.protobuf.Descriptors.FileDescriptor .internalBuildGeneratedFileFrom(descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] { - }, assigner); + }); internal_static_Trajectory_descriptor = getDescriptor().getMessageTypes().get(0); internal_static_Trajectory_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_Trajectory_descriptor, - new String[] { "AndroidVersion", "ImuData", "PdrData", "PositionData", "PressureData", "LightData", "GnssData", "WifiData", "ApsData", "StartTimestamp", "DataIdentifier", "AccelerometerInfo", "GyroscopeInfo", "RotationVectorInfo", "MagnetometerInfo", "BarometerInfo", "LightSensorInfo", }); - internal_static_Pdr_Sample_descriptor = + new java.lang.String[] { "AndroidVersion", "TrajectoryVersion", "TrajectoryId", "ImuData", "PdrData", "MagnetometerData", "PressureData", "LightData", "ProximityData", "GnssData", "WifiFingerprints", "ApsData", "WifiRttData", "BleFingerprints", "BleData", "StartTimestamp", "InitialPosition", "CorrectedPositions", "AccelerometerInfo", "GyroscopeInfo", "RotationVectorInfo", "MagnetometerInfo", "BarometerInfo", "LightSensorInfo", "ProximityInfo", "TestPoints", }); + internal_static_RelativePosition_descriptor = getDescriptor().getMessageTypes().get(1); - internal_static_Pdr_Sample_fieldAccessorTable = new + internal_static_RelativePosition_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_Pdr_Sample_descriptor, - new String[] { "RelativeTimestamp", "X", "Y", }); - internal_static_Motion_Sample_descriptor = + internal_static_RelativePosition_descriptor, + new java.lang.String[] { "RelativeTimestamp", "X", "Y", }); + internal_static_IMUReading_descriptor = getDescriptor().getMessageTypes().get(2); - internal_static_Motion_Sample_fieldAccessorTable = new + internal_static_IMUReading_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_Motion_Sample_descriptor, - new String[] { "RelativeTimestamp", "AccX", "AccY", "AccZ", "GyrX", "GyrY", "GyrZ", "RotationVectorX", "RotationVectorY", "RotationVectorZ", "RotationVectorW", "StepCount", }); - internal_static_Position_Sample_descriptor = + internal_static_IMUReading_descriptor, + new java.lang.String[] { "RelativeTimestamp", "Acc", "Gyr", "RotationVector", "StepCount", }); + internal_static_MagnetometerReading_descriptor = getDescriptor().getMessageTypes().get(3); - internal_static_Position_Sample_fieldAccessorTable = new + internal_static_MagnetometerReading_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_Position_Sample_descriptor, - new String[] { "RelativeTimestamp", "MagX", "MagY", "MagZ", }); - internal_static_Pressure_Sample_descriptor = + internal_static_MagnetometerReading_descriptor, + new java.lang.String[] { "RelativeTimestamp", "Mag", }); + internal_static_BarometerReading_descriptor = getDescriptor().getMessageTypes().get(4); - internal_static_Pressure_Sample_fieldAccessorTable = new + internal_static_BarometerReading_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_Pressure_Sample_descriptor, - new String[] { "RelativeTimestamp", "Pressure", }); - internal_static_Light_Sample_descriptor = + internal_static_BarometerReading_descriptor, + new java.lang.String[] { "RelativeTimestamp", "Pressure", }); + internal_static_LightReading_descriptor = getDescriptor().getMessageTypes().get(5); - internal_static_Light_Sample_fieldAccessorTable = new + internal_static_LightReading_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_Light_Sample_descriptor, - new String[] { "RelativeTimestamp", "Light", }); - internal_static_GNSS_Sample_descriptor = + internal_static_LightReading_descriptor, + new java.lang.String[] { "RelativeTimestamp", "Light", }); + internal_static_ProximityReading_descriptor = getDescriptor().getMessageTypes().get(6); - internal_static_GNSS_Sample_fieldAccessorTable = new + internal_static_ProximityReading_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_GNSS_Sample_descriptor, - new String[] { "RelativeTimestamp", "Latitude", "Longitude", "Altitude", "Accuracy", "Speed", "Provider", }); - internal_static_WiFi_Sample_descriptor = + internal_static_ProximityReading_descriptor, + new java.lang.String[] { "RelativeTimestamp", "Distance", }); + internal_static_GNSSPosition_descriptor = getDescriptor().getMessageTypes().get(7); - internal_static_WiFi_Sample_fieldAccessorTable = new + internal_static_GNSSPosition_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_WiFi_Sample_descriptor, - new String[] { "RelativeTimestamp", "MacScans", }); - internal_static_Mac_Scan_descriptor = + internal_static_GNSSPosition_descriptor, + new java.lang.String[] { "RelativeTimestamp", "Latitude", "Longitude", "Altitude", "Floor", "Floor", }); + internal_static_GNSSReading_descriptor = getDescriptor().getMessageTypes().get(8); - internal_static_Mac_Scan_fieldAccessorTable = new + internal_static_GNSSReading_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_Mac_Scan_descriptor, - new String[] { "RelativeTimestamp", "Mac", "Rssi", }); - internal_static_AP_Data_descriptor = + internal_static_GNSSReading_descriptor, + new java.lang.String[] { "Position", "Accuracy", "Speed", "Bearing", "Provider", }); + internal_static_Fingerprint_descriptor = getDescriptor().getMessageTypes().get(9); - internal_static_AP_Data_fieldAccessorTable = new + internal_static_Fingerprint_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_AP_Data_descriptor, - new String[] { "Mac", "Ssid", "Frequency", }); - internal_static_Sensor_Info_descriptor = + internal_static_Fingerprint_descriptor, + new java.lang.String[] { "RelativeTimestamp", "RfScans", }); + internal_static_RFScan_descriptor = getDescriptor().getMessageTypes().get(10); - internal_static_Sensor_Info_fieldAccessorTable = new + internal_static_RFScan_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_RFScan_descriptor, + new java.lang.String[] { "RelativeTimestamp", "Mac", "Rssi", "Position", "Position", }); + internal_static_WiFiRTTReading_descriptor = + getDescriptor().getMessageTypes().get(11); + internal_static_WiFiRTTReading_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_WiFiRTTReading_descriptor, + new java.lang.String[] { "RelativeTimestamp", "Mac", "Distance", "DistanceStd", "Rssi", }); + internal_static_WiFiAPData_descriptor = + getDescriptor().getMessageTypes().get(12); + internal_static_WiFiAPData_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_WiFiAPData_descriptor, + new java.lang.String[] { "Mac", "Ssid", "Frequency", "RttEnabled", }); + internal_static_BleData_descriptor = + getDescriptor().getMessageTypes().get(13); + internal_static_BleData_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_BleData_descriptor, + new java.lang.String[] { "MacAddress", "Name", "TxPowerLevel", "AdvertiseFlags", "ServiceUuids", "ManufacturerData", }); + internal_static_Vector3_descriptor = + getDescriptor().getMessageTypes().get(14); + internal_static_Vector3_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_Vector3_descriptor, + new java.lang.String[] { "X", "Y", "Z", }); + internal_static_Quaternion_descriptor = + getDescriptor().getMessageTypes().get(15); + internal_static_Quaternion_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_Quaternion_descriptor, + new java.lang.String[] { "X", "Y", "Z", "W", }); + internal_static_SensorInfo_descriptor = + getDescriptor().getMessageTypes().get(16); + internal_static_SensorInfo_fieldAccessorTable = new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_Sensor_Info_descriptor, - new String[] { "Name", "Vendor", "Resolution", "Power", "Version", "Type", }); + internal_static_SensorInfo_descriptor, + new java.lang.String[] { "Name", "Vendor", "Resolution", "Power", "Version", "Type", "MaxRange", "Frequency", }); } // @@protoc_insertion_point(outer_class_scope) diff --git a/app/src/main/java/com/openpositioning/PositionMe/data/local/TrajParser.java b/app/src/main/java/com/openpositioning/PositionMe/data/local/TrajParser.java index 2d2b1cbf..5149a263 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/data/local/TrajParser.java +++ b/app/src/main/java/com/openpositioning/PositionMe/data/local/TrajParser.java @@ -3,7 +3,6 @@ import android.content.Context; import android.hardware.SensorManager; import android.util.Log; - import com.google.android.gms.maps.model.LatLng; import com.google.gson.Gson; import com.google.gson.JsonArray; @@ -11,7 +10,6 @@ import com.google.gson.JsonParser; import com.openpositioning.PositionMe.presentation.fragment.ReplayFragment; import com.openpositioning.PositionMe.sensors.SensorFusion; - import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -21,33 +19,32 @@ import java.util.List; /** - * Handles parsing of trajectory data stored in JSON files, combining IMU, PDR, and GNSS data - * to reconstruct motion paths. + * Handles parsing of trajectory data stored in JSON files, combining IMU, PDR, and GNSS data to + * reconstruct motion paths. + * + *

The **TrajParser** is primarily responsible for processing recorded trajectory data and + * reconstructing motion information, including estimated positions, GNSS coordinates, speed, and + * orientation. It does this by reading a JSON file containing: * - *

- * The **TrajParser** is primarily responsible for processing recorded trajectory data and - * reconstructing motion information, including estimated positions, GNSS coordinates, speed, and orientation. - * It does this by reading a JSON file containing: - *

*
    - *
  • IMU (Inertial Measurement Unit) data
  • - *
  • PDR (Pedestrian Dead Reckoning) position data
  • - *
  • GNSS (Global Navigation Satellite System) location data
  • + *
  • IMU (Inertial Measurement Unit) data + *
  • PDR (Pedestrian Dead Reckoning) position data + *
  • GNSS (Global Navigation Satellite System) location data *
* - *

- * **Usage in Module 'PositionMe.app.main':** - *

+ *

**Usage in Module 'PositionMe.app.main':** + * *

    - *
  • **ReplayFragment** - Calls `parseTrajectoryData()` to read recorded trajectory files and process movement.
  • - *
  • Stores parsed trajectory data as `ReplayPoint` objects.
  • - *
  • Provides data for updating map visualizations in `ReplayFragment`.
  • + *
  • **ReplayFragment** - Calls `parseTrajectoryData()` to read recorded trajectory files and + * process movement. + *
  • Stores parsed trajectory data as `ReplayPoint` objects. + *
  • Provides data for updating map visualizations in `ReplayFragment`. *
* * @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 com.openpositioning.PositionMe.presentation.fragment.ReplayFragment for implementation + * details. * @author Shu Gu * @author Lin Cheng */ @@ -60,72 +57,135 @@ public class TrajParser { * orientation, speed, and timestamp. */ public static class ReplayPoint { - public LatLng pdrLocation; // PDR-derived location estimate + public LatLng pdrLocation; // PDR-derived location estimate public LatLng gnssLocation; // GNSS 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 + public LatLng fusionLocation; // Fusion location + public float orientation; // Orientation in degrees + public float speed; // Speed in meters per second + public long timestamp; // Relative timestamp + public LatLng testPoint; // Test point location (null if not a test point) + public int testPointNumber; // Test point number (0 if not a test point) + public String testPointTime; // Formatted time for test point /** * Constructs a ReplayPoint. * - * @param pdrLocation The pedestrian dead reckoning (PDR) location. + * @param pdrLocation The pedestrian dead reckoning (PDR) location. * @param gnssLocation The GNSS location, or null if unavailable. - * @param orientation The orientation angle in degrees. - * @param speed The speed in meters per second. - * @param timestamp The timestamp associated with this point. + * @param orientation The orientation angle in degrees. + * @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 fusionLocation, + float orientation, + float speed, + long timestamp) { this.pdrLocation = pdrLocation; this.gnssLocation = gnssLocation; + this.fusionLocation = fusionLocation; this.orientation = orientation; this.speed = speed; this.timestamp = timestamp; + this.testPoint = null; + this.testPointNumber = 0; + this.testPointTime = null; } } - /** Represents an IMU (Inertial Measurement Unit) data record used for orientation calculations. */ + /** + * Represents an IMU (Inertial Measurement Unit) data record used for orientation calculations. + */ private static class ImuRecord { public long relativeTimestamp; public float accX, accY, accZ; // Accelerometer values public float gyrX, gyrY, gyrZ; // Gyroscope values - public float rotationVectorX, rotationVectorY, rotationVectorZ, rotationVectorW; // Rotation quaternion + public float rotationVectorX, + rotationVectorY, + rotationVectorZ, + rotationVectorW; // Rotation quaternion } - /** Represents a Pedestrian Dead Reckoning (PDR) data record storing position shifts over time. */ + /** + * Represents a Pedestrian Dead Reckoning (PDR) data record storing position shifts over time. + */ private static class PdrRecord { public long relativeTimestamp; public float x, y; // Position relative to the starting point } - /** Represents a GNSS (Global Navigation Satellite System) data record with latitude/longitude. */ + /** + * Represents a GNSS (Global Navigation Satellite System) data record with latitude/longitude. + */ private static class GnssRecord { public long relativeTimestamp; public double latitude, longitude; // GNSS coordinates } + /** Represents a Test Point marker saved during recording. */ + private static class TestPointRecord { + public long relativeTimestamp; + public double latitude, longitude, altitude; + } + + /** Represents a Fused (Corrected) position record. */ + private static class FusionRecord { + public long relativeTimestamp; + public double latitude, longitude; + } + + /** Parses Corrected Positions (Fusion) data from JSON. */ + private static List parseFusionData(JsonArray fusionArray) { + List list = new ArrayList<>(); + if (fusionArray == null) return list; + + for (int i = 0; i < fusionArray.size(); i++) { + try { + JsonObject obj = fusionArray.get(i).getAsJsonObject(); + FusionRecord record = new FusionRecord(); + record.relativeTimestamp = + obj.has("relativeTimestamp") ? obj.get("relativeTimestamp").getAsLong() : 0; + record.latitude = obj.has("latitude") ? obj.get("latitude").getAsDouble() : 0.0; + record.longitude = obj.has("longitude") ? obj.get("longitude").getAsDouble() : 0.0; + list.add(record); + } catch (Exception e) { + Log.e(TAG, "Error parsing Fusion record: " + e.getMessage()); + } + } + return list; + } + + /** Finds the closest Fusion record to the given timestamp. */ + private static FusionRecord findClosestFusionRecord( + List list, long targetTimestamp) { + return list.stream() + .min(Comparator.comparingLong(f -> Math.abs(f.relativeTimestamp - targetTimestamp))) + .orElse(null); + } + /** * Parses trajectory data from a JSON file and reconstructs a list of replay points. * - *

- * This method processes a trajectory log file, extracting IMU, PDR, and GNSS records, - * and uses them to generate **ReplayPoint** objects. Each point contains: - *

+ *

This method processes a trajectory log file, extracting IMU, PDR, and GNSS records, and + * uses them to generate **ReplayPoint** objects. Each point contains: + * *

    - *
  • Estimated PDR-based position.
  • - *
  • GNSS location (if available).
  • - *
  • Computed orientation using rotation vectors.
  • - *
  • Speed estimation based on movement data.
  • + *
  • Estimated PDR-based position. + *
  • GNSS location (if available). + *
  • Computed orientation using rotation vectors. + *
  • Speed estimation based on movement data. *
* - * @param filePath Path to the JSON file containing trajectory data. - * @param context Android application context (used for sensor processing). + * @param filePath Path to the JSON file containing trajectory data. + * @param context Android application context (used for sensor processing). * @param originLat Latitude of the reference origin. * @param originLng Longitude of the reference origin. * @return A list of parsed {@link ReplayPoint} objects. */ - public static List parseTrajectoryData(String filePath, Context context, - double originLat, double originLng) { + public static List parseTrajectoryData( + String filePath, Context context, double originLat, double originLng) { List result = new ArrayList<>(); try { @@ -145,26 +205,40 @@ public static List parseTrajectoryData(String filePath, Context con Log.i(TAG, "Successfully read trajectory file: " + filePath); - long startTimestamp = root.has("startTimestamp") ? root.get("startTimestamp").getAsLong() : 0; + long startTimestamp = + root.has("startTimestamp") ? root.get("startTimestamp").getAsLong() : 0; List imuList = parseImuData(root.getAsJsonArray("imuData")); List pdrList = parsePdrData(root.getAsJsonArray("pdrData")); List gnssList = parseGnssData(root.getAsJsonArray("gnssData")); - - Log.i(TAG, "Parsed data - IMU: " + imuList.size() + " records, PDR: " - + pdrList.size() + " records, GNSS: " + gnssList.size() + " records"); + List testPointList = + parseTestPoints(root.getAsJsonArray("testPoints")); + List fusionList = + parseFusionData(root.getAsJsonArray("correctedPositions")); + + Log.i( + TAG, + "Parsed data - IMU: " + + imuList.size() + + " records, PDR: " + + pdrList.size() + + " records, GNSS: " + + gnssList.size() + + " records"); for (int i = 0; i < pdrList.size(); i++) { PdrRecord pdr = pdrList.get(i); ImuRecord closestImu = findClosestImuRecord(imuList, pdr.relativeTimestamp); - float orientationDeg = closestImu != null ? computeOrientationFromRotationVector( - closestImu.rotationVectorX, - closestImu.rotationVectorY, - closestImu.rotationVectorZ, - closestImu.rotationVectorW, - context - ) : 0f; + float orientationDeg = + closestImu != null + ? computeOrientationFromRotationVector( + closestImu.rotationVectorX, + closestImu.rotationVectorY, + closestImu.rotationVectorZ, + closestImu.rotationVectorW, + context) + : 0f; float speed = 0f; if (i > 0) { @@ -176,17 +250,52 @@ public static List parseTrajectoryData(String filePath, Context con if (dt > 0) speed = (float) (distance / dt); } - double lat = originLat + pdr.y * 1E-5; double lng = originLng + pdr.x * 1E-5; LatLng pdrLocation = new LatLng(lat, lng); GnssRecord closestGnss = findClosestGnssRecord(gnssList, pdr.relativeTimestamp); - LatLng gnssLocation = closestGnss != null ? - new LatLng(closestGnss.latitude, closestGnss.longitude) : null; + LatLng gnssLocation = + closestGnss != null + ? new LatLng(closestGnss.latitude, closestGnss.longitude) + : null; + + FusionRecord closestFusion = + findClosestFusionRecord(fusionList, pdr.relativeTimestamp); + LatLng fusionLocation = + closestFusion != null + ? new LatLng(closestFusion.latitude, closestFusion.longitude) + : null; + + result.add( + new ReplayPoint( + pdrLocation, + gnssLocation, + fusionLocation, + orientationDeg, + speed, + pdr.relativeTimestamp)); + } - result.add(new ReplayPoint(pdrLocation, gnssLocation, orientationDeg, - 0f, pdr.relativeTimestamp)); + // Match test points to ReplayPoints by finding closest timestamp + for (int i = 0; i < testPointList.size(); i++) { + TestPointRecord testPt = testPointList.get(i); + + ReplayPoint closest = + result.stream() + .min( + Comparator.comparingLong( + rp -> + Math.abs( + rp.timestamp + - testPt.relativeTimestamp))) + .orElse(null); + + if (closest != null) { + closest.testPoint = new LatLng(testPt.latitude, testPt.longitude); + closest.testPointNumber = i + 1; + closest.testPointTime = formatTimestamp(testPt.relativeTimestamp); + } } Collections.sort(result, Comparator.comparingLong(rp -> rp.timestamp)); @@ -199,58 +308,161 @@ public static List parseTrajectoryData(String filePath, Context con return result; } -/** Parses IMU data from JSON. */ -private static List parseImuData(JsonArray imuArray) { - List imuList = new ArrayList<>(); - if (imuArray == null) return imuList; - Gson gson = new Gson(); - for (int i = 0; i < imuArray.size(); i++) { - ImuRecord record = gson.fromJson(imuArray.get(i), ImuRecord.class); - imuList.add(record); + + /** Parses IMU data from JSON. */ + private static List parseImuData(JsonArray imuArray) { + List imuList = new ArrayList<>(); + if (imuArray == null) return imuList; + + for (int i = 0; i < imuArray.size(); i++) { + try { + JsonObject imuObj = imuArray.get(i).getAsJsonObject(); + ImuRecord record = new ImuRecord(); + + record.relativeTimestamp = + imuObj.has("relativeTimestamp") + ? imuObj.get("relativeTimestamp").getAsLong() + : 0; + + // Parse acc (nested) + if (imuObj.has("acc")) { + JsonObject acc = imuObj.getAsJsonObject("acc"); + record.accX = acc.has("x") ? acc.get("x").getAsFloat() : 0f; + record.accY = acc.has("y") ? acc.get("y").getAsFloat() : 0f; + record.accZ = acc.has("z") ? acc.get("z").getAsFloat() : 0f; + } + + // Parse gyr (nested) + if (imuObj.has("gyr")) { + JsonObject gyr = imuObj.getAsJsonObject("gyr"); + record.gyrX = gyr.has("x") ? gyr.get("x").getAsFloat() : 0f; + record.gyrY = gyr.has("y") ? gyr.get("y").getAsFloat() : 0f; + record.gyrZ = gyr.has("z") ? gyr.get("z").getAsFloat() : 0f; + } + + // Parse rotationVector (nested) + if (imuObj.has("rotationVector")) { + JsonObject rot = imuObj.getAsJsonObject("rotationVector"); + record.rotationVectorX = rot.has("x") ? rot.get("x").getAsFloat() : 0f; + record.rotationVectorY = rot.has("y") ? rot.get("y").getAsFloat() : 0f; + record.rotationVectorZ = rot.has("z") ? rot.get("z").getAsFloat() : 0f; + record.rotationVectorW = rot.has("w") ? rot.get("w").getAsFloat() : 1f; + } + + imuList.add(record); + } catch (Exception e) { + Log.e(TAG, "Error parsing IMU record: " + e.getMessage()); + } + } + return imuList; + } + + /** Parses PDR data from JSON. */ + private static List parsePdrData(JsonArray pdrArray) { + List pdrList = new ArrayList<>(); + if (pdrArray == null) return pdrList; + Gson gson = new Gson(); + for (int i = 0; i < pdrArray.size(); i++) { + PdrRecord record = gson.fromJson(pdrArray.get(i), PdrRecord.class); + pdrList.add(record); + } + return pdrList; + } + + /** Parses GNSS data from JSON. */ + private static List parseGnssData(JsonArray gnssArray) { + List gnssList = new ArrayList<>(); + if (gnssArray == null) return gnssList; + + for (int i = 0; i < gnssArray.size(); i++) { + try { + JsonObject gnssObj = gnssArray.get(i).getAsJsonObject(); + GnssRecord record = new GnssRecord(); + + // Check if position object exists (nested structure) + if (gnssObj.has("position")) { + JsonObject position = gnssObj.getAsJsonObject("position"); + record.relativeTimestamp = + position.has("relativeTimestamp") + ? position.get("relativeTimestamp").getAsLong() + : 0; + record.latitude = + position.has("latitude") ? position.get("latitude").getAsDouble() : 0.0; + record.longitude = + position.has("longitude") + ? position.get("longitude").getAsDouble() + : 0.0; + } else { + // Flat structure (fallback) + record.relativeTimestamp = + gnssObj.has("relativeTimestamp") + ? gnssObj.get("relativeTimestamp").getAsLong() + : 0; + record.latitude = + gnssObj.has("latitude") ? gnssObj.get("latitude").getAsDouble() : 0.0; + record.longitude = + gnssObj.has("longitude") ? gnssObj.get("longitude").getAsDouble() : 0.0; + } + gnssList.add(record); + } catch (Exception e) { + Log.e(TAG, "Error parsing GNSS record: " + e.getMessage()); + } + } + return gnssList; } - return imuList; -}/** Parses PDR data from JSON. */ -private static List parsePdrData(JsonArray pdrArray) { - List pdrList = new ArrayList<>(); - if (pdrArray == null) return pdrList; - Gson gson = new Gson(); - for (int i = 0; i < pdrArray.size(); i++) { - PdrRecord record = gson.fromJson(pdrArray.get(i), PdrRecord.class); - pdrList.add(record); + + /** Parses Test Points data from JSON. */ + private static List parseTestPoints(JsonArray testPointsArray) { + List testPointsList = new ArrayList<>(); + if (testPointsArray == null) return testPointsList; + Gson gson = new Gson(); + for (int i = 0; i < testPointsArray.size(); i++) { + TestPointRecord record = gson.fromJson(testPointsArray.get(i), TestPointRecord.class); + testPointsList.add(record); + } + return testPointsList; } - return pdrList; -}/** Parses GNSS data from JSON. */ -private static List parseGnssData(JsonArray gnssArray) { - List gnssList = new ArrayList<>(); - if (gnssArray == null) return gnssList; - Gson gson = new Gson(); - for (int i = 0; i < gnssArray.size(); i++) { - GnssRecord record = gson.fromJson(gnssArray.get(i), GnssRecord.class); - gnssList.add(record); + + /** Finds the closest IMU record to the given timestamp. */ + private static ImuRecord findClosestImuRecord(List imuList, long targetTimestamp) { + return imuList.stream() + .min( + Comparator.comparingLong( + imu -> Math.abs(imu.relativeTimestamp - targetTimestamp))) + .orElse(null); } - return gnssList; -}/** Finds the closest IMU record to the given timestamp. */ -private static ImuRecord findClosestImuRecord(List 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 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 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]; - float[] orientationAngles = new float[3]; - - SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); - SensorManager.getRotationMatrixFromVector(rotationMatrix, rotationVector); - SensorManager.getOrientation(rotationMatrix, orientationAngles); - - float azimuthDeg = (float) Math.toDegrees(orientationAngles[0]); - return azimuthDeg < 0 ? azimuthDeg + 360.0f : azimuthDeg; -} -} \ No newline at end of file + /** Finds the closest GNSS record to the given timestamp. */ + private static GnssRecord findClosestGnssRecord( + List 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 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]; + float[] orientationAngles = new float[3]; + + SensorManager sensorManager = + (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); + SensorManager.getRotationMatrixFromVector(rotationMatrix, rotationVector); + SensorManager.getOrientation(rotationMatrix, orientationAngles); + + float azimuthDeg = (float) Math.toDegrees(orientationAngles[0]); + return azimuthDeg < 0 ? azimuthDeg + 360.0f : azimuthDeg; + } + + /** Formats a relative timestamp into MM:SS format */ + private static String formatTimestamp(long relativeTimestamp) { + long seconds = relativeTimestamp / 1000; + long minutes = seconds / 60; + seconds = seconds % 60; + return String.format("%02d:%02d", minutes, seconds); + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/data/remote/LoginManager.java b/app/src/main/java/com/openpositioning/PositionMe/data/remote/LoginManager.java new file mode 100644 index 00000000..9f59c28b --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/data/remote/LoginManager.java @@ -0,0 +1,142 @@ +package com.openpositioning.PositionMe.data.remote; + +import static com.openpositioning.PositionMe.utils.UtilConstants.CREDENTIALS_FILE_NAME; +import static com.openpositioning.PositionMe.utils.UtilConstants.CREDENTIALS_KEY_EMAIL; +import static com.openpositioning.PositionMe.utils.UtilConstants.CREDENTIALS_KEY_PASSWORD; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; +import androidx.security.crypto.EncryptedSharedPreferences; +import androidx.security.crypto.MasterKey; +import java.util.Map; + +/** + * The LoginManager class handles the user's identity, both when signing in (email and password) and + * when other classes call upon the user's information as returned from the server (username and API + * key) + * + *

The user's login credentials are securely stored on their device. + * + *

Implements the Singleton design pattern such that only one instance of the LoginManager can + * exist. This allows the user's details to be stored in one object and accessed by any other class. + * + * @see EncryptedSharedPreferences + * @see ServerCommunications + */ +public class LoginManager { + private final String TAG = "LoginManager"; + + private boolean isLoggedIn; + + private String username; + private String userKey; + + // Secure persistent storage of credentials (save password box) + SharedPreferences credentialStore; + + // Singleton Class + private static final LoginManager loginManager = new LoginManager(); + + private LoginManager() { + this.isLoggedIn = false; + } + + public static LoginManager getInstance() { + return loginManager; + } + + /** Run once on startup to initialise the credential store */ + public void initialise(Context context) { + if (credentialStore == null) { + try { + MasterKey masterKey = + new MasterKey.Builder(context) + .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) + .build(); + credentialStore = + EncryptedSharedPreferences.create( + context, + CREDENTIALS_FILE_NAME, + masterKey, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM); + Log.d(TAG, "Credential storage initialised"); + } catch (Exception e) { + Log.w(TAG, "Error initialising the login credentials store: " + e.getMessage()); + } + } + } + + /** + * Saves user's name and API key to this instance of the {@link LoginManager}. These details + * will be cleared upon {@link LoginManager#endLoginSession() logging out} or closing the app. + * + * @param username The user's username, for UI elements + * @param userKey The user's API key, for network requests + */ + public void startLoginSession(String username, String userKey) { + this.username = username; + this.userKey = userKey; + this.isLoggedIn = true; + Log.d( + TAG, + "Login session for \"" + + username + + "\" started. API key will be used for future requests"); + } + + /** Clears the user's details from app session storage */ + public void endLoginSession() { + this.username = null; + this.userKey = null; + this.isLoggedIn = false; + Log.d(TAG, "Login session ended. User will need to log in again"); + } + + /** + * Save the provided credentials to the persistent storage. + * + *

Unlike {@link LoginManager#startLoginSession(String, String) startLoginSession()}, these + * credentials are saved to disk and can be retrieved between app launches. + * + * @param email The user's email address + * @param password The user's password + */ + public void saveLoginToDevice(String email, String password) { + credentialStore + .edit() + .putString(CREDENTIALS_KEY_EMAIL, email) + .putString(CREDENTIALS_KEY_PASSWORD, password) + .apply(); + Log.i(TAG, "Credentials successfully saved on device"); + } + + /** + * Retrieves the user's credentials, if they exist on the device + * + * @return The user's email and password + */ + public Map getSavedLoginDetails() { + if (credentialStore.contains(CREDENTIALS_KEY_EMAIL) + && credentialStore.contains(CREDENTIALS_KEY_PASSWORD)) { + Log.i(TAG, "Credentials found"); + return (Map) credentialStore.getAll(); + } else { + Log.d(TAG, "No saved credentials found"); + return null; + } + } + + public boolean checkLoginStatus() { + return isLoggedIn; + } + + public String getUsername() { + return username; + } + + public String getUserKey() { + return userKey; + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/data/remote/ServerCommunications.java b/app/src/main/java/com/openpositioning/PositionMe/data/remote/ServerCommunications.java index 7f7e74b2..1d337d56 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/data/remote/ServerCommunications.java +++ b/app/src/main/java/com/openpositioning/PositionMe/data/remote/ServerCommunications.java @@ -1,16 +1,17 @@ package com.openpositioning.PositionMe.data.remote; -import android.util.Log; -import java.util.Map; -import java.util.HashMap; -import java.util.Iterator; -import java.io.BufferedReader; -import java.io.FileReader; -import org.json.JSONObject; -import android.os.Environment; - -import java.io.FileInputStream; -import java.io.OutputStream; +import static com.openpositioning.PositionMe.utils.UtilConstants.API_KEY_MASTER; +import static com.openpositioning.PositionMe.utils.UtilConstants.API_POST_LOGIN; +import static com.openpositioning.PositionMe.utils.UtilConstants.API_POST_SIGN_UP; +import static com.openpositioning.PositionMe.utils.UtilConstants.API_POST_TRAJECTORIES; +import static com.openpositioning.PositionMe.utils.UtilConstants.BUILDING_NAME_OUTSIDE; +import static com.openpositioning.PositionMe.utils.UtilConstants.FLOOR_PLAN_POLL_TIME_MS; +import static com.openpositioning.PositionMe.utils.UtilConstants.PROTOCOL_APP_JSON; +import static com.openpositioning.PositionMe.utils.UtilConstants.PROTOCOL_MULTIPART; +import static com.openpositioning.PositionMe.utils.UtilConstants.URL_API; +import static com.openpositioning.PositionMe.utils.UtilConstants.URL_GET_TRAJECTORIES_HEAD; +import static com.openpositioning.PositionMe.utils.UtilConstants.URL_GET_TRAJECTORIES_TAIL; +import static com.openpositioning.PositionMe.utils.UtilConstants.URL_POST_FLOORPLANS; import android.content.Context; import android.content.SharedPreferences; @@ -20,36 +21,46 @@ import android.os.Environment; import android.os.Handler; import android.os.Looper; +import android.util.Log; import android.widget.Toast; - import androidx.annotation.NonNull; import androidx.preference.PreferenceManager; - +import com.google.android.gms.maps.model.LatLng; import com.google.protobuf.util.JsonFormat; -import com.openpositioning.PositionMe.BuildConfig; +import com.openpositioning.PositionMe.R; import com.openpositioning.PositionMe.Traj; -import com.openpositioning.PositionMe.presentation.fragment.FilesFragment; import com.openpositioning.PositionMe.presentation.activity.MainActivity; +import com.openpositioning.PositionMe.presentation.fragment.FilesFragment; +import com.openpositioning.PositionMe.presentation.fragment.LoginFragment; +import com.openpositioning.PositionMe.presentation.fragment.RegisterFragment; import com.openpositioning.PositionMe.sensors.Observable; import com.openpositioning.PositionMe.sensors.Observer; - +import com.openpositioning.PositionMe.sensors.Wifi; +import com.openpositioning.PositionMe.utils.IndoorMapManager; +import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.nio.file.Files; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; -import java.util.zip.ZipEntry; +import java.util.Map; +import java.util.Set; import java.util.zip.ZipInputStream; - import okhttp3.Call; import okhttp3.Callback; -import okhttp3.Headers; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttp; @@ -58,21 +69,38 @@ import okhttp3.RequestBody; import okhttp3.Response; import okhttp3.ResponseBody; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; /** - * This class handles communications with the server through HTTPs. The class uses an - * {@link OkHttpClient} for making requests to the server. The class includes methods for sending - * a recorded trajectory, uploading locally-stored trajectories, downloading trajectories from the - * server and requesting information about the uploaded trajectories. + * This class handles communications with the server through HTTPs. The class uses an {@link + * OkHttpClient} for making requests to the server. The class includes methods for interfacing with + * the OpenPosition REST API. * - * Keys and URLs are hardcoded strings, given the simple and academic nature of the project. + *

The key methods {@link ServerCommunications#sendRequestGET(String, String, REQUEST, Object) + * sendRequestGET()} and {@link ServerCommunications#sendRequestPOST(String, RequestBody, String, + * String, REQUEST, Object) sendRequestPOST()} are used to sent HTTP GET and POST requests + * respectively, and are called by public methods which format the requests as required. + * + *

As the OpenPosition API evolves, these two methods can be extended to support handling more + * requests to the server. * * @author Michal Dvorak * @author Mate Stodulka */ public class ServerCommunications implements Observable { + private static final String TAG = "ServerCommunications"; public static Map downloadRecords = new HashMap<>(); + // Application context for handling permissions and devices + private static final int OBSERVER_INDEX_FILES = 0; + private static final int OBSERVER_INDEX_MAIN = 1; + private static final int OBSERVER_INDEX_INDOOR_MAPS = 2; + private static final int OBSERVER_INDEX_LOGIN = 3; + private static final int OBSERVER_INDEX_REGISTER = 4; + private static final int TRAJECTORY_REQUEST_BUFFER = 10; + private final Context context; // Network status checking @@ -80,34 +108,33 @@ public class ServerCommunications implements Observable { private boolean isWifiConn; private boolean isMobileConn; private SharedPreferences settings; + private LoginManager loginManager; private String infoResponse; private boolean success; - private List observers; - - // Static constants necessary for communications - private static final String userKey = BuildConfig.OPENPOSITIONING_API_KEY; - private static final String masterKey = BuildConfig.OPENPOSITIONING_MASTER_KEY; - private static final String uploadURL = - "https://openpositioning.org/api/live/trajectory/upload/" + userKey - + "/?key=" + masterKey; - private static final String downloadURL = - "https://openpositioning.org/api/live/trajectory/download/" + userKey - + "?skip=0&limit=30&key=" + masterKey; - private static final String infoRequestURL = - "https://openpositioning.org/api/live/users/trajectories/" + userKey - + "?key=" + masterKey; - private static final String PROTOCOL_CONTENT_TYPE = "multipart/form-data"; - private static final String PROTOCOL_ACCEPT_TYPE = "application/json"; - + private Set observers; + private long lastTime = 0; + + // Enum to iterate through possible API requests + private enum REQUEST { + GET_TRAJECTORIES_LIST, + GET_TRAJECTORY_SINGLE, + POST_TRAJECTORY_RECORDED, + POST_TRAJECTORY_LOCAL, + POST_FLOOR_PLANS, + POST_SIGN_UP, + POST_LOG_IN + } + private String ERROR_CODE_NO_SERVER; + private String ERROR_MESSAGE_NO_SERVER; /** * Public default constructor of {@link ServerCommunications}. The constructor saves context, - * initialises a {@link ConnectivityManager}, {@link Observer} and gets the user preferences. + * initialises a {@link ConnectivityManager}, {@link Observer}, and gets the user preferences. * Boolean variables storing WiFi and Mobile Data connection status are initialised to false. * - * @param context application context for handling permissions and devices. + * @param context application context for handling permissions and devices. */ public ServerCommunications(Context context) { this.context = context; @@ -117,246 +144,570 @@ public ServerCommunications(Context context) { this.isMobileConn = false; checkNetworkStatus(); - this.observers = new ArrayList<>(); + ERROR_CODE_NO_SERVER = context.getString(R.string.errorCodeNoServerResponse); + ERROR_MESSAGE_NO_SERVER = context.getString(R.string.errorMessageNoServerResponse); + this.observers = new LinkedHashSet<>(); + loginManager = LoginManager.getInstance(); } + ////////////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////////////// + /** - * Outgoing communication request with a {@link Traj trajectory} object. The recorded - * trajectory is passed to the method. It is processed into the right format for sending - * to the API server. + * Sends an HTTP GET request to the provided URL, and handles responses. * - * @param trajectory Traj object matching all the timing and formal restrictions. + * @param url The URL of the API + * @param headerAccept The header string defining the response data type expected + * @param requestType An encoded value used to determine how to process the server's response + * @param additionalData Additional data used in processing the server's response. Varies from + * request to request + * @see REQUEST */ - public void sendTrajectory(Traj.Trajectory trajectory){ + private void sendRequestGET( + String url, String headerAccept, REQUEST requestType, Object additionalData) { + OkHttpClient client = new OkHttpClient(); + Request request = + new Request.Builder().url(url).addHeader("accept", headerAccept).get().build(); + Log.d(TAG, "GET Request:\n" + url + "\n" + request.headers()); + client.newCall(request) + .enqueue( + new Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + // Notify users + Log.w(TAG, "Error: " + e.getMessage()); + String errorMessage = ERROR_MESSAGE_NO_SERVER; + success = false; + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + context, + errorMessage, + Toast.LENGTH_SHORT) + .show(); + }); + infoResponse = ERROR_CODE_NO_SERVER + ":" + errorMessage; + + switch (requestType) { + case GET_TRAJECTORIES_LIST: + notifyObservers(OBSERVER_INDEX_FILES); + return; + case GET_TRAJECTORY_SINGLE: + return; + default: + return; + } + } + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) + throws IOException { + try (ResponseBody responseBody = response.body()) { + String responseCode = String.valueOf(response.code()); + Log.i(TAG, "GET response: Code " + responseCode); + + if (!response.isSuccessful()) { + String errorBody = responseBody.string(); + Log.w(TAG, "Error: " + errorBody); + infoResponse = responseCode + ":" + errorBody; + success = false; + + switch (requestType) { + case GET_TRAJECTORIES_LIST: + parseErrorResponse(infoResponse); + notifyObservers(OBSERVER_INDEX_FILES); + return; + case GET_TRAJECTORY_SINGLE: + parseErrorResponse(infoResponse); + return; + default: + return; + } + } + + switch (requestType) { + case GET_TRAJECTORIES_LIST: + // Save the requested information from the response body + infoResponse = responseBody.string(); + success = true; + notifyObservers(OBSERVER_INDEX_FILES); + return; + case GET_TRAJECTORY_SINGLE: + @SuppressWarnings("unchecked") + List data = (List) additionalData; + + String id = data.get(0).toString(); + int position = (int) data.get(1); + String dateSubmitted = data.get(2).toString(); + + processDownloadedTrajectory( + responseBody, id, position, dateSubmitted); + return; + default: + return; + } + } + } + }); + } + + /** + * Sends an HTTP POST request to the provided URL, and handles responses. + * + * @param url The URL of the API + * @param payload The data to be sent in the POST request + * @param headerAccept The header string defining the response data type expected + * @param headerContentType The header string defining the data type of the payload + * @param requestType An encoded value used to determine how to process the server's response + * @param additionalData Additional data used in processing the server's response. Varies from + * request to request + * @see REQUEST + */ + private void sendRequestPOST( + String url, + RequestBody payload, + String headerAccept, + String headerContentType, + REQUEST requestType, + Object additionalData) { + OkHttpClient client = new OkHttpClient(); + Request request = + new Request.Builder() + .url(url) + .post(payload) + .addHeader("accept", headerAccept) + .addHeader("Content-Type", headerContentType) + .build(); + Log.d(TAG, "POST Request:\n" + url + "\n" + request.headers()); + client.newCall(request) + .enqueue( + new Callback() { + + /** When the attempt to send the request has failed, notify the user. */ + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + Log.w(TAG, "Error: " + e.getMessage()); + String errorMessage = ERROR_MESSAGE_NO_SERVER; + success = false; + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + context, + errorMessage, + Toast.LENGTH_SHORT) + .show(); + }); + infoResponse = ERROR_CODE_NO_SERVER + ":" + errorMessage; + + switch (requestType) { + case POST_LOG_IN: + notifyObservers(OBSERVER_INDEX_LOGIN); + return; + case POST_SIGN_UP: + notifyObservers(OBSERVER_INDEX_REGISTER); + return; + case POST_TRAJECTORY_RECORDED: + case POST_TRAJECTORY_LOCAL: + notifyObservers(OBSERVER_INDEX_MAIN); + return; + case POST_FLOOR_PLANS: + notifyObservers(OBSERVER_INDEX_INDOOR_MAPS); + return; + default: + return; + } + } + + /** + * Process the response from the server, based on it's HTTP response + * code. + * + *

For non-error codes (2XX-3XX), process the response. + * + *

For error codes (4XX), send the code to the {@link Observer} + * instance to handle directly. + */ + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) + throws IOException { + try (ResponseBody responseBody = response.body()) { + String responseCode = String.valueOf(response.code()); + Log.i(TAG, "POST response: Code " + responseCode); + + if (!response.isSuccessful()) { + String errorBody = responseBody.string(); + Log.w(TAG, "Error: " + errorBody); + infoResponse = responseCode + ":" + errorBody; + success = false; + + switch (requestType) { + case POST_LOG_IN: + parseErrorResponse(infoResponse); + notifyObservers(OBSERVER_INDEX_LOGIN); + return; + case POST_SIGN_UP: + parseErrorResponse(infoResponse); + notifyObservers(OBSERVER_INDEX_REGISTER); + return; + case POST_TRAJECTORY_RECORDED: + case POST_TRAJECTORY_LOCAL: + // Invalid trajectories should not be saved + File badTrajectoryLocal = (File) additionalData; + badTrajectoryLocal.delete(); + Log.d( + TAG, + "Trajectory " + + badTrajectoryLocal.getName() + + " deleted"); + Log.d(TAG, "Sending " + errorBody); + notifyObservers(OBSERVER_INDEX_MAIN); + return; + case POST_FLOOR_PLANS: + parseErrorResponse(infoResponse); + notifyObservers(OBSERVER_INDEX_INDOOR_MAPS); + return; + default: + return; + } + } + switch (requestType) { + case POST_LOG_IN: + infoResponse = responseBody.string(); + success = true; + notifyObservers(OBSERVER_INDEX_LOGIN); + return; + case POST_SIGN_UP: + infoResponse = responseBody.string(); + success = true; + notifyObservers(OBSERVER_INDEX_REGISTER); + return; + case POST_TRAJECTORY_RECORDED: + File originalFile = (File) additionalData; + infoResponse = responseBody.string(); + success = processTrajectoryResponse(originalFile); + notifyObservers(OBSERVER_INDEX_MAIN); + return; + case POST_TRAJECTORY_LOCAL: + File localFile = (File) additionalData; + infoResponse = responseBody.string(); + success = localFile.delete(); + notifyObservers(OBSERVER_INDEX_MAIN); + return; + case POST_FLOOR_PLANS: + infoResponse = responseBody.string(); + success = true; + notifyObservers(OBSERVER_INDEX_INDOOR_MAPS); + return; + default: + return; + } + } + } + }); + } + + /** + * Error responses from the server share the same output format, so this function will parse + * that response and produce a user-friendly {@link Toast} explaining the problem. + * + * @param infoString String formatted as "errorCode:JSONResponse" + */ + private void parseErrorResponse(String infoString) { + String[] errorElements = infoString.split(":", 2); + String errorCode = errorElements[0]; + String errorCause = errorElements[1]; + + // Only perform JSON data extraction if response is in JSON format + if (!errorCause.contains("{")) { + Log.i(TAG, "\"" + errorCause + "\" is not a JSON response"); + } else { + try { + JSONObject jsonObject = new JSONObject(errorCause); + JSONArray detailArray = jsonObject.optJSONArray("detail"); + if (detailArray != null) { + for (int i = 0; i < detailArray.length(); i++) { + JSONObject problem = detailArray.getJSONObject(i); + String type = problem.getString("type"); + if (type.contains("value_error")) { + String badValue = type.split("\\.", 2)[1]; + if (badValue.equals("missing")) { + badValue = problem.getJSONArray("loc").getString(1); + badValue = + badValue.substring(0, 1).toUpperCase() + + badValue.substring(1); + errorCause = badValue + " " + problem.getString("msg"); + } else { + badValue = + badValue.substring(0, 1).toUpperCase() + + badValue.substring(1); + errorCause = + badValue + " " + problem.getString("msg").split(" ", 2)[1]; + } + } else { + errorCause = problem.getString("msg"); + } + } + } else { + // If error response is not JSON format, print as-is + errorCause = jsonObject.getString("detail"); + } + } catch (JSONException e) { + Log.w(TAG, e.getMessage()); + errorCause = "Unknown error"; + } + } + + String errorMessage = errorCause + " (HTTP Error " + errorCode + ")"; + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT).show(); + }); + } + + ////////////////////////////////////////////////////////////////////////////// + + /** + * Handle the server response from uploading a newly recorded trajectory, and delete the + * trajectory file saved on disk during the recording. + * + *

+ * + * @param originalFile The trajectory file created during the recording + * @return True if the processing is completed successfully. False otherwise. + */ + private boolean processTrajectoryResponse(File originalFile) { + // Copy the file to the Downloads folder + File downloadsDir = + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); + File downloadFile = new File(downloadsDir, originalFile.getName()); + try { + copyFile(originalFile, downloadFile); + Log.i(TAG, "Trajectory file copied to Downloads: " + downloadFile.getAbsolutePath()); + } catch (IOException e) { + Log.e(TAG, "Failed to copy file to Downloads: " + e.getMessage()); + } + + return originalFile.delete(); + } + + /** + * Helper function to copy a {@link File file's} contents from one location to another. + * + * @param src The source file + * @param dst The destination file + * @see ServerCommunications#processTrajectoryResponse(File) + */ + private void copyFile(File src, File dst) throws IOException { + try (InputStream in = new FileInputStream(src); + OutputStream out = new FileOutputStream(dst)) { + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + } + } + + /** + * Outgoing communication request with a {@link Traj trajectory} object. The recorded trajectory + * is passed to the method. It is processed into the right format for sending to the API server. + * + * @param trajectory Traj object matching all the timing and formal restrictions. + * @param campaign The building associated with the route + */ + public void sendTrajectory(Traj.Trajectory trajectory, String campaign) { + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + context, + "Now uploading '" + campaign + "' trajectory...", + Toast.LENGTH_SHORT) + .show(); + }); logDataSize(trajectory); + File file = convertTrajectoryToFile(trajectory); + + // Only proceed if campaign is valid + if (campaign.isBlank() || campaign.equals(BUILDING_NAME_OUTSIDE)) { + String message = "Invalid campaign ('" + campaign + "') - Cancelling upload"; + Log.w(TAG, message); + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); + }); + return; + } + + // Check connections available before sending data + checkNetworkStatus(); + + // Check if user preference allows for syncing with mobile data + // TODO: add sync delay and enforce settings + boolean enableMobileData = this.settings.getBoolean("mobile_sync", false); + + // Check if device is connected to WiFi or to mobile data with enabled preference + if (!this.isWifiConn && !(enableMobileData && isMobileConn)) { + // If the device is not connected to network or allowed to send, + // do not send trajectory and notify observers and user + String errorMessage = "No uploading allowed right now!"; + infoResponse = ERROR_CODE_NO_SERVER + ":" + errorMessage; + Log.w(TAG, infoResponse); + success = false; + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT).show(); + }); + notifyObservers(OBSERVER_INDEX_MAIN); + return; + } + // Create a request body with a file to upload in multipart/form-data format + RequestBody requestBody = + new MultipartBody.Builder() + .setType(MultipartBody.FORM) + .addFormDataPart( + "file", + file.getName(), + RequestBody.create(MediaType.parse("text/plain"), file)) + .build(); + + // Create a POST request with the required headers + String uploadURL = createTrajectoryUploadURL(campaign); + sendRequestPOST( + uploadURL, + requestBody, + PROTOCOL_APP_JSON, + PROTOCOL_MULTIPART, + REQUEST.POST_TRAJECTORY_RECORDED, + file); + } + + /** + * Helper function to convert the recorded {@link Traj trajectory} object into a {@link File} + * for uploading + * + *

+ * + * @param trajectory The recorded trajectory object. + * @return A {@link File} prepared for uploading. + */ + private File convertTrajectoryToFile(Traj.Trajectory trajectory) { // Convert the trajectory to byte array byte[] binaryTrajectory = trajectory.toByteArray(); File path = null; - // for android 13 or higher use dedicated external storage + // For Android 13 or higher, use dedicated external storage if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { path = context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS); if (path == null) { path = context.getFilesDir(); } - } else { // for android 12 or lower use internal storage + } else { + // For Android 12 or lower, use internal storage path = context.getFilesDir(); } - System.out.println(path.toString()); + Log.i(TAG, path.toString()); // Format the file name according to date SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yy-HH-mm-ss"); Date date = new Date(); - File file = new File(path, "trajectory_" + dateFormat.format(date) + ".txt"); + File file = new File(path, "trajectory_" + dateFormat.format(date) + ".txt"); try { // Write the binary data to the file FileOutputStream stream = new FileOutputStream(file); stream.write(binaryTrajectory); stream.close(); - System.out.println("Recorded binary trajectory for debugging stored in: " + path); - } catch (IOException ee) { + Log.i(TAG, "Recorded binary trajectory for debugging stored in: " + path); + } catch (IOException e) { // Catch and print if writing to the file fails - System.err.println("Storing of recorded binary trajectory failed: " + ee.getMessage()); + Log.e(TAG, "Storing of recorded binary trajectory failed: " + e.getMessage()); } - // Check connections available before sending data - checkNetworkStatus(); - - // Check if user preference allows for syncing with mobile data - // TODO: add sync delay and enforce settings - boolean enableMobileData = this.settings.getBoolean("mobile_sync", false); - // Check if device is connected to WiFi or to mobile data with enabled preference - if(this.isWifiConn || (enableMobileData && isMobileConn)) { - // Instantiate client for HTTP requests - OkHttpClient client = new OkHttpClient(); - - // Creaet a equest body with a file to upload in multipart/form-data format - RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM) - .addFormDataPart("file", file.getName(), - RequestBody.create(MediaType.parse("text/plain"), file)) - .build(); - - // Create a POST request with the required headers - Request request = new Request.Builder().url(uploadURL).post(requestBody) - .addHeader("accept", PROTOCOL_ACCEPT_TYPE) - .addHeader("Content-Type", PROTOCOL_CONTENT_TYPE).build(); - - // Enqueue the request to be executed asynchronously and handle the response - client.newCall(request).enqueue(new Callback() { - - // Handle failure to get response from the server - @Override public void onFailure(Call call, IOException e) { - e.printStackTrace(); - System.err.println("Failure to get response"); - // Delete the local file and set success to false - //file.delete(); - success = false; - notifyObservers(1); - } - - private void copyFile(File src, File dst) throws IOException { - try (InputStream in = new FileInputStream(src); - OutputStream out = new FileOutputStream(dst)) { - byte[] buf = new byte[1024]; - int len; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - } - } - - // Process the server's response - @Override public void onResponse(Call call, Response response) throws IOException { - try (ResponseBody responseBody = response.body()) { - // If the response is unsuccessful, delete the local file and throw an - // exception - if (!response.isSuccessful()) { - //file.delete(); -// System.err.println("POST error response: " + responseBody.string()); - - String errorBody = responseBody.string(); - infoResponse = "Upload failed: " + errorBody; - new Handler(Looper.getMainLooper()).post(() -> - Toast.makeText(context, infoResponse, Toast.LENGTH_SHORT).show()); // show error message to users - - System.err.println("POST error response: " + errorBody); - success = false; - notifyObservers(1); - throw new IOException("Unexpected code " + response); - } - - // Print the response headers - Headers responseHeaders = response.headers(); - for (int i = 0, size = responseHeaders.size(); i < size; i++) { - System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); - } - // Print a confirmation of a successful POST to API - System.out.println("Successful post response: " + responseBody.string()); - - System.out.println("Get file: " + file.getName()); - String originalPath = file.getAbsolutePath(); - System.out.println("Original trajectory file saved at: " + originalPath); - - // Copy the file to the Downloads folder - File downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); - File downloadFile = new File(downloadsDir, file.getName()); - try { - copyFile(file, downloadFile); - System.out.println("Trajectory file copied to Downloads: " + downloadFile.getAbsolutePath()); - } catch (IOException e) { - e.printStackTrace(); - System.err.println("Failed to copy file to Downloads: " + e.getMessage()); - } - - // Delete local file and set success to true - success = file.delete(); - notifyObservers(1); - } - } - }); - } - else { - // If the device is not connected to network or allowed to send, do not send trajectory - // and notify observers and user - System.err.println("No uploading allowed right now!"); - success = false; - notifyObservers(1); - } + return file; } /** - * Uploads a local trajectory file to the API server in the specified format. - * {@link OkHttp} library is used for the asynchronous POST request. + * Uploads a local trajectory file to the API server in the specified format. {@link OkHttp} + * library is used for the asynchronous POST request. * * @param localTrajectory the File object of the local trajectory to be uploaded + * @param campaign The building associated with the route */ - public void uploadLocalTrajectory(File localTrajectory) { + public void uploadLocalTrajectory(File localTrajectory, String campaign) { + // Only proceed if campaign is valid + if (campaign.isBlank() || campaign.equals(BUILDING_NAME_OUTSIDE)) { + String message = "Invalid campaign ('" + campaign + "') - Cancelling upload"; + Log.w(TAG, message); + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); + }); + return; + } - // Instantiate client for HTTP requests - OkHttpClient client = new OkHttpClient(); + if (!localTrajectory.exists()) { + Log.e(TAG, "Unable to use file!"); + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + context, + "Trajectory has been deleted. Please refresh the" + + " view.", + Toast.LENGTH_SHORT) + .show(); + }); + return; + } - // robustness improvement + // Robustness improvement RequestBody fileRequestBody; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { try { byte[] fileBytes = Files.readAllBytes(localTrajectory.toPath()); fileRequestBody = RequestBody.create(MediaType.parse("text/plain"), fileBytes); } catch (IOException e) { - e.printStackTrace(); + Log.e(TAG, "Error: " + e.getMessage()); // if failed, use File object to construct RequestBody - fileRequestBody = RequestBody.create(MediaType.parse("text/plain"), localTrajectory); + fileRequestBody = + RequestBody.create(MediaType.parse("text/plain"), localTrajectory); } } else { fileRequestBody = RequestBody.create(MediaType.parse("text/plain"), localTrajectory); } // Create request body with a file to upload in multipart/form-data format - RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM) - .addFormDataPart("file", localTrajectory.getName(), fileRequestBody) - .build(); + RequestBody requestBody = + new MultipartBody.Builder() + .setType(MultipartBody.FORM) + .addFormDataPart("file", localTrajectory.getName(), fileRequestBody) + .build(); // Create a POST request with the required headers - okhttp3.Request request = new okhttp3.Request.Builder().url(uploadURL).post(requestBody) - .addHeader("accept", PROTOCOL_ACCEPT_TYPE) - .addHeader("Content-Type", PROTOCOL_CONTENT_TYPE).build(); - - // Enqueue the request to be executed asynchronously and handle the response - client.newCall(request).enqueue(new okhttp3.Callback() { - @Override - public void onFailure(Call call, IOException e) { - // Print error message, set success to false and notify observers - e.printStackTrace(); -// localTrajectory.delete(); - success = false; - System.err.println("UPLOAD: Failure to get response"); - notifyObservers(1); - infoResponse = "Upload failed: " + e.getMessage(); // Store error message - new Handler(Looper.getMainLooper()).post(() -> - Toast.makeText(context, infoResponse, Toast.LENGTH_SHORT).show()); // show error message to users - } - - @Override - public void onResponse(Call call, Response response) throws IOException { - try (ResponseBody responseBody = response.body()) { - if (!response.isSuccessful()) { - // Print error message, set success to false and throw an exception - success = false; -// System.err.println("UPLOAD unsuccessful: " + responseBody.string()); - notifyObservers(1); -// localTrajectory.delete(); - assert responseBody != null; - String errorBody = responseBody.string(); - System.err.println("UPLOAD unsuccessful: " + errorBody); - infoResponse = "Upload failed: " + errorBody; - new Handler(Looper.getMainLooper()).post(() -> - Toast.makeText(context, infoResponse, Toast.LENGTH_SHORT).show()); - throw new IOException("UPLOAD failed with code " + response); - } - - // Print the response headers - Headers responseHeaders = response.headers(); - for (int i = 0, size = responseHeaders.size(); i < size; i++) { - System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); - } - - // Print a confirmation of a successful POST to API - assert responseBody != null; - System.out.println("UPLOAD SUCCESSFUL: " + responseBody.string()); - - // Delete local file, set success to true and notify observers - success = localTrajectory.delete(); - notifyObservers(1); - } - } - }); + String uploadURL = createTrajectoryUploadURL(campaign); + + sendRequestPOST( + uploadURL, + requestBody, + PROTOCOL_APP_JSON, + PROTOCOL_MULTIPART, + REQUEST.POST_TRAJECTORY_LOCAL, + localTrajectory); } /** - * Loads download records from a JSON file and updates the downloadRecords map. - * If the file exists, it reads the JSON content and populates the map. + * Loads download records from a JSON file and updates the downloadRecords map. If the file + * exists, it reads the JSON content and populates the map. */ private void loadDownloadRecords() { // Point to the app-specific Downloads folder @@ -379,31 +730,33 @@ private void loadDownloadRecords() { String id = record.getString("id"); downloadRecords.put(id, record); } catch (Exception e) { - System.err.println("Error loading record with key: " + key); - e.printStackTrace(); + Log.e( + TAG, + "[" + e.getMessage() + "] Error loading record with key: " + key); } } - System.out.println("Loaded downloadRecords: " + downloadRecords); + Log.i(TAG, "Loaded downloadRecords: " + downloadRecords); } catch (Exception e) { - e.printStackTrace(); + Log.e(TAG, "Error: " + e.getMessage()); } } else { - System.out.println("Download_records.json not found in app-specific directory."); + Log.i(TAG, "Download_records.json not found in app-specific directory."); } } /** - * Saves a download record to a JSON file. - * The method creates or updates the JSON file with the provided details. + * Saves a download record to a JSON file. The method creates or updates the JSON file with the + * provided details. * * @param startTimestamp the start timestamp of the trajectory * @param fileName the name of the file * @param id the ID of the trajectory * @param dateSubmitted the date the trajectory was submitted */ - private void saveDownloadRecord(long startTimestamp, String fileName, String id, String dateSubmitted) { + private void saveDownloadRecord( + long startTimestamp, String fileName, String id, String dateSubmitted) { File recordsDir = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS); File recordsFile = new File(recordsDir, "download_records.json"); JSONObject jsonObject; @@ -419,7 +772,7 @@ private void saveDownloadRecord(long startTimestamp, String fileName, String id, if (recordsFile.createNewFile()) { jsonObject = new JSONObject(); } else { - System.err.println("Failed to create file: " + recordsFile.getAbsolutePath()); + Log.e(TAG, "Failed to create file: " + recordsFile.getAbsolutePath()); return; } } else { @@ -432,9 +785,10 @@ private void saveDownloadRecord(long startTimestamp, String fileName, String id, } } // If file is empty or invalid JSON, use a fresh JSONObject - jsonObject = jsonBuilder.length() > 0 - ? new JSONObject(jsonBuilder.toString()) - : new JSONObject(); + jsonObject = + jsonBuilder.length() > 0 + ? new JSONObject(jsonBuilder.toString()) + : new JSONObject(); } // Create the new record details @@ -453,158 +807,267 @@ private void saveDownloadRecord(long startTimestamp, String fileName, String id, writer.flush(); } - System.out.println("Download record saved successfully at: " + recordsFile.getAbsolutePath()); + Log.i(TAG, "Download record saved successfully at: " + recordsFile.getAbsolutePath()); } catch (Exception e) { - e.printStackTrace(); - System.err.println("Error saving download record: " + e.getMessage()); + Log.e(TAG, "Error saving download record: " + e.getMessage()); } } /** * Perform API request for downloading a Trajectory uploaded to the server. The trajectory is * retrieved from a zip file, with the method accepting a position argument specifying the - * trajectory to be downloaded. The trajectory is then converted to a protobuf object and - * then to a JSON string to be downloaded to the device's Downloads folder. + * trajectory to be downloaded. The trajectory is then converted to a protobuf object and then + * to a JSON string to be downloaded to the device's Downloads folder. * - * @param position the position of the trajectory in the zip file to retrieve - * @param id the ID of the trajectory - * @param dateSubmitted the date the trajectory was submitted + * @param position The position of the trajectory in the zip file to retrieve + * @param id The ID of the trajectory + * @param dateSubmitted The date the trajectory was submitted */ public void downloadTrajectory(int position, String id, String dateSubmitted) { - loadDownloadRecords(); // Load existing records from app-specific directory + // Load existing records from app-specific directory + loadDownloadRecords(); + + String url = + URL_GET_TRAJECTORIES_HEAD + + "/" + + loginManager.getUserKey() + + "?skip=0&limit=" + + (position + TRAJECTORY_REQUEST_BUFFER) + + URL_GET_TRAJECTORIES_TAIL; + + List additionalData = new ArrayList<>(); + additionalData.add(id); + additionalData.add(position); + additionalData.add(dateSubmitted); - // Initialise OkHttp client - OkHttpClient client = new OkHttpClient(); + // Enqueue the GET request for asynchronous execution + sendRequestGET(url, PROTOCOL_APP_JSON, REQUEST.GET_TRAJECTORY_SINGLE, additionalData); + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + context, + "Request sent for Trajectory " + id, + Toast.LENGTH_SHORT) + .show(); + }); + } - // Create GET request with required header - okhttp3.Request request = new okhttp3.Request.Builder() - .url(downloadURL) - .addHeader("accept", PROTOCOL_ACCEPT_TYPE) - .get() - .build(); + /** + * Processes the downloaded trajectory data such that it can be replayed + * + * @param responseBody The raw response from the server + * @param id The ID of the trajectory being processed + * @param position The position within the ZIP file's array of the trajectory requested + * @param dateSubmitted The date on which the trajectory was recorded + */ + private void processDownloadedTrajectory( + ResponseBody responseBody, String id, int position, String dateSubmitted) { + try { + new Handler(Looper.getMainLooper()) + .post( + () -> + Toast.makeText( + context, + "Trajectory " + + id + + " received!\n" + + "Now parsing trajectory...", + Toast.LENGTH_SHORT) + .show()); + + // Extract the nth entry from the zip + InputStream inputStream = responseBody.byteStream(); + ZipInputStream zipInputStream = new ZipInputStream(inputStream); + + int zipCount = 0; + while ((zipInputStream.getNextEntry()) != null) { + if (zipCount == position) { + // break if zip entry position matches the desired position + break; + } + zipCount++; + } - // Enqueue the GET request for asynchronous execution - client.newCall(request).enqueue(new okhttp3.Callback() { - @Override - public void onFailure(Call call, IOException e) { - e.printStackTrace(); + // Initialise a byte array output stream + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + // Read the zipped data and write it to the byte array output + // stream + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = zipInputStream.read(buffer)) != -1) { + byteArrayOutputStream.write(buffer, 0, bytesRead); } - @Override - public void onResponse(Call call, Response response) throws IOException { - try (ResponseBody responseBody = response.body()) { - if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); - - // Extract the nth entry from the zip - InputStream inputStream = responseBody.byteStream(); - ZipInputStream zipInputStream = new ZipInputStream(inputStream); - - java.util.zip.ZipEntry zipEntry; - int zipCount = 0; - while ((zipEntry = zipInputStream.getNextEntry()) != null) { - if (zipCount == position) { - // break if zip entry position matches the desired position - break; - } - zipCount++; - } + // Convert the byte array to protobuf + byte[] byteArray = byteArrayOutputStream.toByteArray(); + Log.d(TAG, "byteArray = " + Arrays.toString(byteArray)); + Traj.Trajectory receivedTrajectory = Traj.Trajectory.parseFrom(byteArray); + + // Print a message in the console + long startTimestamp = receivedTrajectory.getStartTimestamp(); + String fileName = "trajectory_" + dateSubmitted + ".txt"; + Log.i(TAG, fileName + " received"); + + // Inspect the size of the received trajectory + logDataSize(receivedTrajectory); + + // Place the file in your app-specific "Downloads" folder + File appSpecificDownloads = + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS); + if (appSpecificDownloads != null && !appSpecificDownloads.exists()) { + Log.d(TAG, "Creating downloads directory..."); + appSpecificDownloads.mkdirs(); + } - // Initialise a byte array output stream - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + File file = new File(appSpecificDownloads, fileName); + + try (FileWriter fileWriter = new FileWriter(file)) { + String receivedTrajectoryString = JsonFormat.printer().print(receivedTrajectory); + fileWriter.write(receivedTrajectoryString); + fileWriter.flush(); + Log.i(TAG, "Received trajectory stored in: " + file.getAbsolutePath()); + + // Save the download record + saveDownloadRecord(startTimestamp, fileName, id, dateSubmitted); + new Handler(Looper.getMainLooper()) + .post( + () -> + Toast.makeText( + context, + "Trajectory " + + id + + " is ready for replay!", + Toast.LENGTH_SHORT) + .show()); + } finally { + // Close all streams and entries to release resources + zipInputStream.closeEntry(); + byteArrayOutputStream.close(); + zipInputStream.close(); + inputStream.close(); + Log.d(TAG, "Files cleaned up"); + } - // Read the zipped data and write it to the byte array output stream - byte[] buffer = new byte[1024]; - int bytesRead; - while ((bytesRead = zipInputStream.read(buffer)) != -1) { - byteArrayOutputStream.write(buffer, 0, bytesRead); - } + } catch (IOException e) { + Log.e(TAG, "Trajectory download failed: " + e.getMessage()); + new Handler(Looper.getMainLooper()) + .post( + () -> + Toast.makeText( + context, + "There was a problem" + + " parsing trajectory " + + id + + "\nPlease try again later", + Toast.LENGTH_SHORT) + .show()); + } + // Refresh the list of download options + loadDownloadRecords(); + } - // Convert the byte array to protobuf - byte[] byteArray = byteArrayOutputStream.toByteArray(); - Traj.Trajectory receivedTrajectory = Traj.Trajectory.parseFrom(byteArray); + /** + * API request for information about submitted trajectories. + * + *

+ * + * @param baseURL The URL of the API GET request + */ + public void requestPathsFromServer(String baseURL) { + String requestURL = baseURL + "/" + loginManager.getUserKey() + "?key=" + API_KEY_MASTER; + sendRequestGET(requestURL, PROTOCOL_APP_JSON, REQUEST.GET_TRAJECTORIES_LIST, null); + } - // Inspect the size of the received trajectory - logDataSize(receivedTrajectory); + /** + * Retrieve floor plans for nearby buildings from the server + * + * @param position Current position during recording + * @param wifiAPs List of nearby wireless access points + */ + public void requestFloorplans(@NonNull LatLng position, @NonNull List wifiAPs) { + // Simple delay window between floor plan API calls + long currentTime = System.currentTimeMillis(); + if (currentTime - lastTime < FLOOR_PLAN_POLL_TIME_MS) { + return; + } else { + lastTime = currentTime; + } - // Print a message in the console - long startTimestamp = receivedTrajectory.getStartTimestamp(); - String fileName = "trajectory_" + dateSubmitted + ".txt"; + String url = + URL_POST_FLOORPLANS + "/" + loginManager.getUserKey() + "?key=" + API_KEY_MASTER; - // Place the file in your app-specific "Downloads" folder - File appSpecificDownloads = context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS); - if (appSpecificDownloads != null && !appSpecificDownloads.exists()) { - appSpecificDownloads.mkdirs(); - } + // Generate list of AP MAC addresses + List aps = new ArrayList<>(); + for (Wifi ap : wifiAPs) { + aps.add(String.valueOf(ap.getBssid())); + } - File file = new File(appSpecificDownloads, fileName); - try (FileWriter fileWriter = new FileWriter(file)) { - String receivedTrajectoryString = JsonFormat.printer().print(receivedTrajectory); - fileWriter.write(receivedTrajectoryString); - fileWriter.flush(); - System.err.println("Received trajectory stored in: " + file.getAbsolutePath()); - } catch (IOException ee) { - System.err.println("Trajectory download failed"); - } finally { - // Close all streams and entries to release resources - zipInputStream.closeEntry(); - byteArrayOutputStream.close(); - zipInputStream.close(); - inputStream.close(); - } + // Construct payload for request + MediaType JSON = MediaType.get(PROTOCOL_APP_JSON + "; charset=utf-8"); + JSONObject payload = new JSONObject(); + try { + payload.put("lat", position.latitude); + payload.put("lon", position.longitude); + payload.put("macs", new JSONArray(aps)); + } catch (JSONException ignore) { + return; + } + RequestBody requestBody = RequestBody.create(payload.toString(), JSON); + + sendRequestPOST( + url, + requestBody, + PROTOCOL_APP_JSON, + PROTOCOL_APP_JSON, + REQUEST.POST_FLOOR_PLANS, + null); + } - // Save the download record - saveDownloadRecord(startTimestamp, fileName, id, dateSubmitted); - loadDownloadRecords(); - } - } - }); + public void registerUserDetails(String username, String email, String password) { + String url = URL_API + API_POST_SIGN_UP; + + // Construct payload for request + MediaType JSON = MediaType.get(PROTOCOL_APP_JSON + "; charset=utf-8"); + JSONObject payload = new JSONObject(); + try { + payload.put("username", username); + payload.put("email", email); + payload.put("password", password); + } catch (JSONException ignore) { + return; + } + RequestBody requestBody = RequestBody.create(payload.toString(), JSON); + sendRequestPOST( + url, requestBody, PROTOCOL_APP_JSON, PROTOCOL_APP_JSON, REQUEST.POST_SIGN_UP, null); } - /** - * API request for information about submitted trajectories. If the response is successful, - * the {@link ServerCommunications#infoResponse} field is updated and observes notified. - * - */ - public void sendInfoRequest() { - // Create a new OkHttpclient - OkHttpClient client = new OkHttpClient(); + public void logInUser(String email, String password) { + String url = URL_API + API_POST_LOGIN; - // Create GET info request with appropriate URL and header - okhttp3.Request request = new okhttp3.Request.Builder() - .url(infoRequestURL) - .addHeader("accept", PROTOCOL_ACCEPT_TYPE) - .get() - .build(); + // Construct payload for request + MediaType JSON = MediaType.get(PROTOCOL_APP_JSON + "; charset=utf-8"); + JSONObject payload = new JSONObject(); + try { + payload.put("email", email); + payload.put("password", password); + } catch (JSONException ignore) { + return; + } - // Enqueue the GET request for asynchronous execution - client.newCall(request).enqueue(new okhttp3.Callback() { - @Override public void onFailure(Call call, IOException e) { - e.printStackTrace(); - } + RequestBody requestBody = RequestBody.create(payload.toString(), JSON); - @Override public void onResponse(Call call, Response response) throws IOException { - try (ResponseBody responseBody = response.body()) { - // Check if the response is successful - if (!response.isSuccessful()) throw new IOException("Unexpected code " + - response); - - // Get the requested information from the response body and save it in a string - // TODO: add printing to the screen somewhere - infoResponse = responseBody.string(); - // Print a message in the console and notify observers - System.out.println("Response received"); - notifyObservers(0); - } - } - }); + sendRequestPOST( + url, requestBody, PROTOCOL_APP_JSON, PROTOCOL_APP_JSON, REQUEST.POST_LOG_IN, null); } /** - * This method checks the device's connection status. It sets boolean variables depending on - * the type of active network connection. + * This method checks the device's connection status. It sets boolean variables depending on the + * type of active network connection. */ private void checkNetworkStatus() { // Get active network information @@ -620,48 +1083,101 @@ private void checkNetworkStatus() { } } + /** + * Create the trajectory upload URL by inserting the building the route is related to + * + * @param campaign The name of the building which the recording is currently associated with + * @return The newly formed URL including the campaign field + */ + private String createTrajectoryUploadURL(String campaign) { + return URL_API + + API_POST_TRAJECTORIES + + "/" + + campaign + + "/" + + loginManager.getUserKey() + + "/?key=" + + API_KEY_MASTER; + } + /** + * Logs all the sensor information in the trajectory + * + * @param trajectory The trajectory being logged + */ private void logDataSize(Traj.Trajectory trajectory) { - Log.i("ServerCommunications", "IMU Data size: " + trajectory.getImuDataCount()); - Log.i("ServerCommunications", "Position Data size: " + trajectory.getPositionDataCount()); - Log.i("ServerCommunications", "Pressure Data size: " + trajectory.getPressureDataCount()); - Log.i("ServerCommunications", "Light Data size: " + trajectory.getLightDataCount()); - Log.i("ServerCommunications", "GNSS Data size: " + trajectory.getGnssDataCount()); - Log.i("ServerCommunications", "WiFi Data size: " + trajectory.getWifiDataCount()); - Log.i("ServerCommunications", "APS Data size: " + trajectory.getApsDataCount()); - Log.i("ServerCommunications", "PDR Data size: " + trajectory.getPdrDataCount()); + Log.i(TAG, "IMU Data size: " + trajectory.getImuDataCount()); + Log.i(TAG, "Position Data size: " + trajectory.getMagnetometerDataCount()); + Log.i(TAG, "Pressure Data size: " + trajectory.getPressureDataCount()); + Log.i(TAG, "Light Data size: " + trajectory.getLightDataCount()); + Log.i(TAG, "GNSS Data size: " + trajectory.getGnssDataCount()); + Log.i(TAG, "WiFi Data size: " + trajectory.getWifiFingerprintsCount()); + Log.i(TAG, "APS Data size: " + trajectory.getApsDataCount()); + Log.i(TAG, "PDR Data size: " + trajectory.getPdrDataCount()); } + ////////////////////////////////////////////////////////////////////////////// + /** * {@inheritDoc} * - * Implement default method from Observable Interface to add new observers to the list of + *

Implement default method from Observable Interface to add new observers to the list of * registered observers. * + *

Note that only one type of each {@link Observer} class may be registered. + * * @param o Classes which implement the Observer interface to receive updates from the class. */ @Override public void registerObserver(Observer o) { - this.observers.add(o); + for (Observer obs : observers) { + if (obs.getClass().getSimpleName().equals(o.getClass().getSimpleName())) { + observers.remove(obs); + } + } + + if (observers.add(o)) { + Log.i(TAG, "Added observer of type " + o.getClass().getSimpleName()); + } else { + Log.w(TAG, "Failed to add Observer of type " + o.getClass().getSimpleName()); + } + Log.d(TAG, "Observers currently in list:"); + observers.forEach(observer -> Log.d(TAG, " " + observer.getClass().getSimpleName())); } /** * {@inheritDoc} * - * Method for notifying all registered observers. The observer is notified based on the index + *

Method for notifying all registered observers. The observer is notified based on the index * passed to the method. * * @param index Index for identifying the observer to be notified. */ @Override public void notifyObservers(int index) { - for(Observer o : observers) { - if(index == 0 && o instanceof FilesFragment) { - o.update(new String[] {infoResponse}); - } - else if (index == 1 && o instanceof MainActivity) { - o.update(new Boolean[] {success}); + if (observers.isEmpty()) { + Log.w(TAG, "No observers registered! Update will be lost."); + return; + } + for (Observer o : observers) { + if (index == OBSERVER_INDEX_FILES && o instanceof FilesFragment) { + o.update(new Object[] {success, infoResponse}); + } else if (index == OBSERVER_INDEX_MAIN && o instanceof MainActivity) { + o.update(new Object[] {success, infoResponse}); + } else if (index == OBSERVER_INDEX_INDOOR_MAPS && o instanceof IndoorMapManager) { + o.update(new Object[] {success, infoResponse}); + } else if (index == OBSERVER_INDEX_LOGIN && o instanceof LoginFragment) { + o.update(new Object[] {success, infoResponse}); + } else if (index == OBSERVER_INDEX_REGISTER && o instanceof RegisterFragment) { + o.update(new Object[] {success, infoResponse}); + } else { + Log.w( + TAG, + "Observer type " + + o.getClass().getSimpleName() + + " does not match observer index " + + index); } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/fusion/Fusion.java b/app/src/main/java/com/openpositioning/PositionMe/fusion/Fusion.java new file mode 100644 index 00000000..93d359bb --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/fusion/Fusion.java @@ -0,0 +1,546 @@ +package com.openpositioning.PositionMe.fusion; + +import static com.openpositioning.PositionMe.fusion.FusionConstants.FLOOR_CHANGE_PERCENTAGE; +import static com.openpositioning.PositionMe.fusion.FusionConstants.FUSION_TYPE_MAX; +import static com.openpositioning.PositionMe.fusion.FusionConstants.OBSERVATION_TYPE_GNSS; +import static com.openpositioning.PositionMe.fusion.FusionConstants.OBSERVATION_TYPE_WIFI; +import static com.openpositioning.PositionMe.fusion.FusionConstants.WIFI_STD_DEV; +import static com.openpositioning.PositionMe.utils.BuildingConstants.BUILDING_ELEMENT_LIFT; +import static com.openpositioning.PositionMe.utils.BuildingConstants.BUILDING_ELEMENT_STAIRS; +import static com.openpositioning.PositionMe.utils.BuildingConstants.BUILDING_ELEMENT_WALL; +import static com.openpositioning.PositionMe.utils.BuildingConstants.BUILDING_NO_FLOOR_NAME; +import static com.openpositioning.PositionMe.utils.BuildingConstants.BUILDING_NO_FLOOR_NUMBER; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; +import androidx.preference.PreferenceManager; +import com.google.android.gms.maps.model.LatLng; +import com.openpositioning.PositionMe.presentation.fragment.SettingsFragment; +import com.openpositioning.PositionMe.sensors.SensorFusion; +import com.openpositioning.PositionMe.utils.Building; +import com.openpositioning.PositionMe.utils.FloorPlan; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * Top-level fusion class that manages corrected position estimation. + * + *

Wraps a {@link ParticleFilter} and exposes a simplified interface for the rest of the + * application. PDR updates are forwarded to the particle filter, and the best position estimate is + * derived from the weighted particle population. + * + * @see ParticleFilter for the underlying sequential Monte Carlo implementation. + * @see SensorFusion for the caller that drives PDR and WiFi updates. + */ +public class Fusion { + private static final String TAG = "Fusion"; + // Current best position estimate in WGS84 + private LatLng bestEstimate; + // Estimated floor level + private int estimatedFloor; + // Whether the fusion system is actively tracking + public boolean isActive; + // Underlying particle filter instance + private final ParticleFilter particleFilter; + // Map matching logic + private final MapMatching mapMatching; + // Building used for map matching + private Building building; + // Keep track of users elevation at the entry of each floor + private float elevationAtFloorEntry; + + // Arbitrary amount to ensure only valid GNSS readings are used for initialisation + private static final float MAX_GNSS_ACCURACY_M = 50f; + + // List of positions from different sensors readings + private final List obsPositions = new ArrayList<>(); + private final List obsTypes = new ArrayList<>(); + private final List obsWiFiFloors = new ArrayList<>(); + + // Timestamps of readings - currently not used + private final List obsTimestamps = new ArrayList<>(); + private final List liveTrajectory = new ArrayList<>(); + + // Set by either GNSS or Wi-Fi + private LatLng startLocation = null; + + private int lastWiFiFloor = BUILDING_NO_FLOOR_NUMBER; + private float sigma; + private int maximumNumberOfObservations; + private boolean debugEnabled; + + private int previousWiFiFloor = BUILDING_NO_FLOOR_NUMBER; + + public Fusion(Context context) { + this.mapMatching = new MapMatching(); + this.particleFilter = new ParticleFilter(context, this.mapMatching); + updateConstants(context); + } + + /** + * Update any constants used based on the user's values from the {@link SettingsFragment} + * + * @param context The current app context (for retrieving the settings) + */ + public void updateConstants(Context context) { + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + if (settings.getBoolean("overwrite_fusion_constants", false)) { + maximumNumberOfObservations = + settings.getInt("fusion_observation_count", FUSION_TYPE_MAX); + } else { + maximumNumberOfObservations = FUSION_TYPE_MAX; + } + debugEnabled = settings.getBoolean("debug_mode", false); + + Log.d(TAG, "Constants updated"); + Log.d(TAG, "maximumNumberOfObservations: " + maximumNumberOfObservations); + Log.d(TAG, "debugEnabled: " + debugEnabled); + particleFilter.updateConstants(context); + } + + public List getParticles() { + return particleFilter.getParticles(); + } + + public LatLng convertENToLatLng(double[] en) { + return particleFilter.enToLatLng(en[0], en[1]); + } + + /** + * Initialises the fusion system and seeds the {@link ParticleFilter} around the given position. + * + * @param initialEstimate is a place holder for the starting position in WGS84 coordinates + * @param initialElevation ??? + * @see SensorFusion#startRecording() + */ + public void start(LatLng initialEstimate, float initialElevation) { + isActive = true; + this.bestEstimate = getStartLocation(initialEstimate); + liveTrajectory.clear(); + obsPositions.clear(); + obsTypes.clear(); + obsWiFiFloors.clear(); + obsTimestamps.clear(); + particleFilter.start(bestEstimate, sigma); + elevationAtFloorEntry = initialElevation; + estimatedFloor = lastWiFiFloor; + mapMatching.setFloor(estimatedFloor); + Log.d( + TAG, + "Fusion started at: " + + initialEstimate + + "; sigma = " + + sigma + + "; Floor " + + estimatedFloor); + } + + /** Stops the fusion system and releases the particle filter resources. */ + public void stop() { + Log.i(TAG, "Fusion stopped"); + this.particleFilter.stop(); + isActive = false; + startLocation = null; + obsPositions.clear(); + obsTypes.clear(); + obsWiFiFloors.clear(); + obsTimestamps.clear(); + // liveTrajectory.clear(); + } + + /** + * Wrapper for {@link Fusion#addObservation(LatLng, String, double) Fusion.addObservation()} to + * allow saving of floor name which the Wi-Fi observation is associated with + * + * @param pos The position of the observation + * @param floorName The floor the Wi-Fi APS observation is associated with + */ + private void addWiFiObservation(LatLng pos, String floorName) { + obsWiFiFloors.add(floorName); + addObservation(pos, OBSERVATION_TYPE_WIFI, WIFI_STD_DEV); + } + + /** + * Get every observation currently available of a given type + * + * @param type The {@link FusionConstants type} of observation requested + * @return A {@link Map} of {@link List Lists} of positions, timestamps, and floors. Note that + * floors will be null if the type is not Wi-Fi + * @see FusionConstants + */ + public Map getObservationsByType(String type) { + Map result = new HashMap<>(); + + List positions = new ArrayList<>(); + List timestamps = new ArrayList<>(); + List floorNames = null; + + if (type.equals(OBSERVATION_TYPE_WIFI)) { + floorNames = new ArrayList<>(); + cleanWiFiObservationFloorNames(); + } + + for (int i = 0; i < obsPositions.size(); i++) { + if (obsTypes.get(i).equals(type)) { + positions.add(obsPositions.get(i)); + timestamps.add(obsTimestamps.get(i)); + } + } + + if (type.equals(OBSERVATION_TYPE_WIFI)) { + floorNames.addAll(obsWiFiFloors); + } + + result.put("positions", positions); + result.put("timestamps", timestamps); + result.put("floor_names", floorNames); + + return result; + } + + /** + * Replace entries in the floor name list that are the floor's index (ie, before the {@link + * Building} has been initialised on the start of a recording) with the floor's name. + * + *

Only replaces entries after the Fusion's {@link Building} has been initialised. + */ + private void cleanWiFiObservationFloorNames() { + if (building != null) { + for (int i = 0; i < obsWiFiFloors.size(); i++) { + String name = obsWiFiFloors.get(i); + if (!Pattern.matches("^[A-Za-z].*", name)) { + int floorNumber = Integer.parseInt(name); + name = building.getFloorNames().get(floorNumber); + } + obsWiFiFloors.set(i, name); + } + } + } + + /** + * Save different types of observations, the position provided, and the timestamp + * + * @param pos The position of the observation + * @param type The {@link FusionConstants type} of observation + */ + private void addObservation(LatLng pos, String type, double sigma) { + obsPositions.add(pos); + obsTypes.add(type); + obsTimestamps.add(System.currentTimeMillis()); + + double[] east_north = particleFilter.latLngToEN(pos.latitude, pos.longitude); + particleFilter.addObservation(east_north[0], east_north[1], sigma); + // Count how many observations of this type exist and remove oldest if too many exist + int typeCount = 0; + for (int i = 0; i < obsTypes.size(); i++) { + if (obsTypes.get(i).equals(type)) typeCount++; + } + + if (typeCount > maximumNumberOfObservations) { + // Remove the oldest observation of this type + for (int i = 0; i < obsTypes.size(); i++) { + if (obsTypes.get(i).equals(type)) { + obsPositions.remove(i); + obsTypes.remove(i); + obsTimestamps.remove(i); + if (type.equals(OBSERVATION_TYPE_WIFI)) { + obsWiFiFloors.remove(0); + } + break; // only remove one — the oldest of this type + } + } + } + if (particleFilter.isActive()) { + particleFilter.updateOnWifiOrGNSS(); + } + } + + /** + * Forwards a PDR displacement to the {@link ParticleFilter} for the prediction step. + * + * @param stepLength ??? + * @param rawHeading ??? + * @param dx Easting displacement in metres. + * @param dy Northing displacement in metres. + */ + public void onPDRUpdate(float stepLength, float rawHeading, double dx, double dy) { + particleFilter.updateWithPDR(stepLength, rawHeading, dx, dy); + LatLng est = particleFilter.getEstimatedPosition(); + // if (est != null) addObservation(est, OBSERVATION_TYPE_PDR); + } + + /** + * Converts GNSS from {@link LatLng} to local EN metres and queues as a particle filter + * observation. + * + * @param pos GNSS position in WGS84 (LatLng) + * @param accuracyMetres reported accuracy from location.getAccuracy() + */ + public void onGnssUpdate(LatLng pos, float accuracyMetres) { + // First acceptable GNSS fix — seed particles around it and start + if (accuracyMetres < MAX_GNSS_ACCURACY_M) { + bestEstimate = pos; + startLocation = pos; + sigma = accuracyMetres; + Log.d(TAG, "New GNSS Observation: " + pos + "; sigma = " + accuracyMetres + "m"); + } + + double[] en = particleFilter.latLngToEN(pos.latitude, pos.longitude); + // particleFilter.addObservation(en[0], en[1], accuracyMetres); + addObservation(pos, OBSERVATION_TYPE_GNSS, accuracyMetres); + } + + /** + * Converts WiFi position from WGS84 to local EN metres and queues as a particle filter + * observation. + * + * @param pos estimated position from WiFi fingerprinting + * @param sigmaMetres position uncertainty (metres) + * @param floor floor index from WiFi positioning (0 = basement) + */ + public void onWifiUpdate(LatLng pos, float sigmaMetres, int floor) { + // WiFi can seed if GNSS hasn't arrived yet + startLocation = pos; + sigma = sigmaMetres; + Log.d( + TAG, + "New Wi-Fi Observation: " + + pos + + "; sigma = " + + sigmaMetres + + "m; Floor = " + + floor); + + // Coursework 2 - Index floors from GF = 0 (26/03/2026) + lastWiFiFloor = floor + 1; + + if (previousWiFiFloor == BUILDING_NO_FLOOR_NUMBER) { + previousWiFiFloor = lastWiFiFloor; + } + + bestEstimate = pos; + + double[] posEastNorth = particleFilter.latLngToEN(pos.latitude, pos.longitude); + // particleFilter.addObservation(posEastNorth[0], posEastNorth[1], sigma); + + // Default to the floor's index if name is unavailable + String floorName; + if (building != null) { + floorName = building.getFloorNames().get(lastWiFiFloor); + } else { + floorName = String.valueOf(lastWiFiFloor); + } + + addWiFiObservation(pos, floorName); + } + + /** + * Called when the barometer detects a change in altitude. Only updates the floor estimate if + * the user is currently in a staircase or elevator. + * + * @param altitudeMetres current altitude from barometer + */ + public void onAltitudeUpdate(float altitudeMetres) { + if (!isActive) return; + + // Check if current position is in stairs/lift + LatLng pos = particleFilter.getEstimatedPosition(); + double[] en = particleFilter.latLngToEN(pos.latitude, pos.longitude); + + // Only proceed if able to change floors + boolean eligible; + + // Allow floor changing anywhere in developer mode + if (debugEnabled) { + eligible = building != null; + } else { + eligible = mapMatching.isEligibleForAltitudeChange(en); + } + if (!eligible) { + // Bug fix if floor is uninitialised + if (estimatedFloor == BUILDING_NO_FLOOR_NUMBER) { + estimatedFloor = lastWiFiFloor; + mapMatching.setFloor(estimatedFloor); + } + return; + } + + // Convert altitude change to floor change + float floorHeight = building.getFloorHeight(); + float delta = altitudeMetres - elevationAtFloorEntry; + if (Math.abs(delta) >= floorHeight * FLOOR_CHANGE_PERCENTAGE) { + int floorChange = (delta > 0) ? 1 : -1; + + int newFloor = estimatedFloor + floorChange; + int maxFloor = building.getFloorNames().size() - 1; + newFloor = Math.max(0, Math.min(newFloor, maxFloor)); + + if (newFloor != estimatedFloor) { + estimatedFloor = newFloor; + mapMatching.setFloor(newFloor); + elevationAtFloorEntry = altitudeMetres; + Log.d( + TAG, + "Floor via barometer changed to " + + estimatedFloor + + " (" + + building.getFloorNames().get(estimatedFloor) + + ")"); + } else if (lastWiFiFloor != previousWiFiFloor) { + previousWiFiFloor = lastWiFiFloor; + estimatedFloor = lastWiFiFloor; + mapMatching.setFloor(lastWiFiFloor); + Log.d( + TAG, + "Floor via Wifi changed to " + + estimatedFloor + + " (" + + building.getFloorNames().get(estimatedFloor) + + ")"); + } else { + Log.d( + TAG, + "Already on floor " + + estimatedFloor + + " (" + + building.getFloorNames().get(estimatedFloor) + + ")"); + } + } else { + Log.d( + TAG, + Math.abs(delta) + + " must be at least " + + (floorHeight * FLOOR_CHANGE_PERCENTAGE) + + " to change floors"); + } + } + + /** + * Converts a {@link Building Building's} GeoJSON floor plan geometries from WGS84 (lat/lng) + * into local East-North (EN) metre coordinates, then passes them to the {@link MapMatching} + * instance for use in constraining particle positions. + * + * @param building The building whose floor plans are being converted + */ + private void initialiseMapGeometries(Building building) { + // Initialise hash maps that map floor indices to a list of floor plan elements + Map>> wallSegments = new HashMap<>(); + Map>> stairPolygons = new HashMap<>(); + Map>> elevatorPolygons = new HashMap<>(); + + List floorPlans = building.getFloorPlans(); + for (FloorPlan floorPlan : floorPlans) { + String floorName = floorPlan.getFloorName(); + + List> floorWalls = floorPlan.getElementsOfType(BUILDING_ELEMENT_WALL); + List> floorStairs = floorPlan.getElementsOfType(BUILDING_ELEMENT_STAIRS); + List> floorLifts = floorPlan.getElementsOfType(BUILDING_ELEMENT_LIFT); + + List> floorWallsEN = convertElementsLatLngToEN(floorWalls); + List> floorStairsEN = convertElementsLatLngToEN(floorStairs); + List> floorLiftsEN = convertElementsLatLngToEN(floorLifts); + + int floorIndex = building.getFloorNames().indexOf(floorName); + wallSegments.put(floorIndex, floorWallsEN); + stairPolygons.put(floorIndex, floorStairsEN); + elevatorPolygons.put(floorIndex, floorLiftsEN); + } + this.mapMatching.setGeometries(wallSegments, stairPolygons, elevatorPolygons); + } + + /** + * Helper function to convert every {@link FloorPlan} element in a {@link List} from {@link + * LatLng} to Easting-Northing + * + * @param elementsLatLng The list of {@link LatLng} elements + * @return A list of Easting-Northing elements + */ + private List> convertElementsLatLngToEN(List> elementsLatLng) { + List> elementsEN = new ArrayList<>(); + + for (List elementLatLng : elementsLatLng) { + List elementEN = new ArrayList<>(); + for (LatLng pointLatLng : elementLatLng) { + double[] pointEN = + particleFilter.latLngToEN(pointLatLng.latitude, pointLatLng.longitude); + elementEN.add(pointEN); + } + elementsEN.add(elementEN); + } + + return elementsEN; + } + + /** + * Updates and returns the current fused position estimate from the particle filter. + * + * @return {@link LatLng} of the best estimated position. + */ + public LatLng getBestEstimate() { + this.bestEstimate = particleFilter.getEstimatedPosition(); + if (this.bestEstimate != null) { + this.liveTrajectory.add(this.bestEstimate); + } + return bestEstimate; + } + + public List getLiveTrajectory() { + return liveTrajectory; + } + + /** + * Returns the best available starting position. + * + * @param initialEstimate of initial start location + * @return start location from GNSS/WiFi, or the fallback + */ + public LatLng getStartLocation(LatLng initialEstimate) { + if (startLocation != null) { + return startLocation; + } else { + return initialEstimate; + } + } + + public boolean isActive() { + return isActive; + } + + /** + * Declare the {@link Building} as the current building for fusion + * + * @param building The building the user is currently inside of + */ + public void setBuilding(Building building) { + // Only proceed if building is different + if (this.building != null && this.building.getName().equals(building.getName())) return; + this.building = building; + initialiseMapGeometries(this.building); + } + + public int getEstimatedFloorNumber() { + if (estimatedFloor != BUILDING_NO_FLOOR_NUMBER) { + return estimatedFloor; + } else { + return building.getGroundFloorIndex(); + } + } + + public String getEstimatedFloorName() { + if (building == null) return BUILDING_NO_FLOOR_NAME; + return building.getFloorNames().get(getEstimatedFloorNumber()); + } + + public double getElevation() { + return elevationAtFloorEntry; + } + + public double getOrientationError() { + return particleFilter.getOrientationError(); + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/fusion/FusionConstants.java b/app/src/main/java/com/openpositioning/PositionMe/fusion/FusionConstants.java new file mode 100644 index 00000000..19acfdfb --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/fusion/FusionConstants.java @@ -0,0 +1,47 @@ +package com.openpositioning.PositionMe.fusion; + +import android.graphics.Color; + +public final class FusionConstants { + // Particle filter + public static final int PARTICLE_COUNT = 20; + public static final int FUSION_TYPE_MAX = 20; + public static final double INITIAL_UNCERTAINTY_M = 5; + + // Valid types of observations + public static final String OBSERVATION_TYPE_PDR = "PDR"; + public static final String OBSERVATION_TYPE_WIFI = "WIFI"; + public static final String OBSERVATION_TYPE_GNSS = "GNSS"; + + public static final float FLOOR_CHANGE_PERCENTAGE = 0.7f; + + // Observation standard deviations (metres) + public static final float WIFI_STD_DEV = 10.0f; + public static final float GNSS_STD_DEV_DEFAULT = 15.0f; + public static final float MAX_STEP_LENGTH = 0.50f; + + // Coordinate conversion (WGS84 approximations at Edinburgh ~55.9°N) + public static final double METRES_PER_DEG_LAT = 110574.0; + public static final double METRES_PER_DEG_LNG_AT_EQUATOR = 111319.5; + public static final double PDR_NOISE_STDDEV = 0.2; + public static final double PARTICLE_FILTER_THRESHOLD = 0.10; + public static final float RESAMPLE_JITTER = 0.5f; + public static final double INITIAL_ORIENTATION_ERROR_STDDEV = 0.175; // ~10 degrees in radians + public static final double ORIENTATION_DRIFT_STDDEV = 0.005; // radians per step - just a guess + public static final double ORIENTATION_RESAMPLE_JITTER = 0.2; + + // Used to display particles on the map + public static final double MAP_PARTICLE_WEIGHTING = 10.0; + public static final float LINE_WEIGHT_PARTICLE = 5f; + public static final int MAP_PARTICLE_COLOUR = Color.MAGENTA; + // Dark green + public static final int MAP_WIFI_COLOUR = Color.rgb(9, 132, 50); + + // Kalman Filter + public static final float NOISE_STD_DEV_PREDICTION = 0.1f; + public static final float NOISE_STD_DEV_BIAS = 0.1f; + public static final float MEASUREMENT_NOISE = 0.25f; + public static final float DELTA_T = 0.25f; + public static final double BIAS_UNCERTAINTY_INITIAL = 0.1; + public static final double GYROSCOPE_UNCERTAINTY_INITIAL = Math.PI; +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/fusion/KalmanFilter.java b/app/src/main/java/com/openpositioning/PositionMe/fusion/KalmanFilter.java new file mode 100644 index 00000000..2aaa7a13 --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/fusion/KalmanFilter.java @@ -0,0 +1,280 @@ +package com.openpositioning.PositionMe.fusion; + +import static com.openpositioning.PositionMe.fusion.FusionConstants.BIAS_UNCERTAINTY_INITIAL; +import static com.openpositioning.PositionMe.fusion.FusionConstants.DELTA_T; +import static com.openpositioning.PositionMe.fusion.FusionConstants.GYROSCOPE_UNCERTAINTY_INITIAL; +import static com.openpositioning.PositionMe.fusion.FusionConstants.MEASUREMENT_NOISE; +import static com.openpositioning.PositionMe.fusion.FusionConstants.NOISE_STD_DEV_BIAS; +import static com.openpositioning.PositionMe.fusion.FusionConstants.NOISE_STD_DEV_PREDICTION; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; +import androidx.preference.PreferenceManager; +import com.openpositioning.PositionMe.presentation.fragment.SettingsFragment; +import org.ejml.dense.row.CommonOps_FDRM; +import org.ejml.simple.SimpleMatrix; + +/** + * This class implements a Kalman filter for calculating an accurate orientation of the phone using + * the accelerometer, magnetometer, and gyroscope. + * + *

See + * here for equations used + * + * @see com.openpositioning.PositionMe.sensors.SensorFusion SensorFusion + */ +public class KalmanFilter { + private static final String TAG = "KalmanFilter"; + private final SimpleMatrix transformation; + private SimpleMatrix prediction; + private final SimpleMatrix timeMatrix; + private SimpleMatrix covariance; + private final SimpleMatrix noiseMatrix; + private final SimpleMatrix measurementVariance; + + private double noiseStdDevPrediction; + private double noiseStdDevBias; + private double noiseMeasurement; + + public KalmanFilter(Context context) { + updateConstants(context); + + transformation = + new SimpleMatrix( + new float[][] { + new float[] {1f, DELTA_T}, + new float[] {0f, 1f} + }); + prediction = new SimpleMatrix(new float[][] {new float[1], new float[1]}); + timeMatrix = new SimpleMatrix(new float[][] {new float[] {DELTA_T}, new float[] {0}}); + noiseMatrix = + new SimpleMatrix( + new double[][] { + new double[] {noiseStdDevPrediction * noiseStdDevPrediction, 0}, + new double[] {0, noiseStdDevBias * noiseStdDevBias} + }); + measurementVariance = new SimpleMatrix(new double[][] {new double[] {noiseMeasurement}}); + Log.d(TAG, "Kalman filter created"); + } + + /** + * Update any constants used based on the user's values from the {@link SettingsFragment} + * + * @param context The current app context (for retrieving the settings) + */ + public void updateConstants(Context context) { + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + if (settings.getBoolean("overwrite_kalman_constants", false)) { + noiseStdDevPrediction = + Float.parseFloat( + settings.getString( + "kalman_pred_noise_std_dev", + String.valueOf(NOISE_STD_DEV_PREDICTION))); + noiseStdDevBias = + Float.parseFloat( + settings.getString( + "kalman_pred_bias_std_dev", + String.valueOf(NOISE_STD_DEV_BIAS))); + noiseMeasurement = + Float.parseFloat( + settings.getString("kalman_noise", String.valueOf(MEASUREMENT_NOISE))); + } else { + noiseStdDevPrediction = NOISE_STD_DEV_PREDICTION; + noiseStdDevBias = NOISE_STD_DEV_BIAS; + noiseMeasurement = MEASUREMENT_NOISE; + } + + Log.d(TAG, "Constants updated"); + Log.d(TAG, "noiseStdDevPrediction: " + noiseStdDevPrediction); + Log.d(TAG, "noiseStdDevBias: " + noiseStdDevBias); + Log.d(TAG, "noiseMeasurement: " + noiseMeasurement); + } + + /** + * Prediction step of the kalman filter algorithm, based on the measurement from the gyroscope + * + * @param angularVelocity The latest reading from the gyroscope, comprised of [x, y, z] values + * in radians + */ + public void predict(float angularVelocity) { + // Initialise last timestamp if required + SimpleMatrix gyroMatrix = new SimpleMatrix(new float[][] {new float[] {angularVelocity}}); + + // Equation 2 + prediction = (transformation.mult(prediction)).plus(timeMatrix.mult(gyroMatrix)); + if (covariance == null) { + // Initialise covariance of rotation such that the initial uncertainly of PI (180 + // degree) and low gyroscope bias + covariance = + new SimpleMatrix( + new double[][] { + new double[] { + GYROSCOPE_UNCERTAINTY_INITIAL * GYROSCOPE_UNCERTAINTY_INITIAL, 0 + }, + new double[] { + 0, BIAS_UNCERTAINTY_INITIAL * BIAS_UNCERTAINTY_INITIAL + } + }); + } + + // Equation 4 + covariance = + transformation.mult(covariance).mult(transformation.transpose()).plus(noiseMatrix); + } + + /** + * Apply the kalman filter to the measurement values from a sensor on the phone (accelerometer, + * or magnetometer) + * + * @param heading orientation given by sensor fusion + */ + public void measure(float heading) { + if (covariance == null || prediction == null) return; + + // float heading = computeHeading(acceleration, magneticField); + + SimpleMatrix rawMatrix = new SimpleMatrix(new float[][] {new float[] {heading}}); + + SimpleMatrix H = new SimpleMatrix(new float[][] {new float[] {1f, 0f}}); + + // Equation 5 + SimpleMatrix predictionInMeasureSpace = H.mult(prediction); + + // Equation 6 + SimpleMatrix varianceInMeasureSpace = H.mult(covariance).mult(H.transpose()); + + // Equation 13 + SimpleMatrix kalmanGain = + covariance + .mult(H.transpose()) + .mult(varianceInMeasureSpace.plus(measurementVariance).pseudoInverse()); + + // calculate innovation + float innovation = (float) (rawMatrix.get(0, 0) - predictionInMeasureSpace.get(0, 0)); + + // wrap the innovation angle to ensure wrapped angles don't give large uncertainty + float wrappedInnovation = wrapAngle(innovation); + + SimpleMatrix innovationMatrix = + new SimpleMatrix(new float[][] {new float[] {wrappedInnovation}}); + + // Equation 11 + SimpleMatrix newMeasurement = prediction.plus(kalmanGain.mult((innovationMatrix))); + + // Equation 12 + SimpleMatrix newCovariance = covariance.minus(kalmanGain.mult(H).mult(covariance)); + + prediction = newMeasurement; + // ensure prediction angle is wrapped + prediction.set(0, 0, wrapAngle((float) prediction.get(0, 0))); + covariance = newCovariance; + Log.d(TAG, "new measurement: " + getMeasurement()); + } + + /** + * Retrieve the latest measurement from the kalman filter + * + * @return The kalman filter's measurement as an array of [x, y, z] floats + */ + public float getMeasurement() { + float[] measurementRow = extractRow(prediction, 0); + return measurementRow[0]; + } + + /** + * Computes the covariance of two matrices which are assumed to be independent + * + *

Note that the matrices passed in as parameters must be of equal dimensions + * + * @param matrixA The first matrix + * @param matrixB The second matrix + * @return A 2x2 matrix [[CovAA, 0], [0, CovBB]] + */ + private SimpleMatrix computeCovariance(SimpleMatrix matrixA, SimpleMatrix matrixB) { + float meanA = (float) matrixA.elementSum() / matrixA.numCols(); + float meanB = (float) matrixB.elementSum() / matrixB.numCols(); + CommonOps_FDRM.add(matrixA.getMatrix(), -meanA); + CommonOps_FDRM.add(matrixB.getMatrix(), -meanB); + + double covAA = matrixA.transpose().mult(matrixA).get(0, 0) / matrixA.numCols(); + double covBB = matrixB.transpose().mult(matrixB).get(0, 0) / matrixB.numCols(); + + return new SimpleMatrix( + new double[][] { + new double[] {covAA, 0}, + new double[] {0, covBB} + }); + } + + /** + * @param acceleration The raw measurement value of acceleration vector + * @param magneticField The raw measurement value of magnetic field vector + * @return heading based on a magnetic field reading corrected using the accelerometer for phone + * tilt + */ + private float computeHeading(float[] acceleration, float[] magneticField) { + float accelerationX = acceleration[0]; + float accelerationY = acceleration[1]; + float accelerationZ = acceleration[2]; + + float magX = magneticField[0]; + float magY = magneticField[1]; + float magZ = magneticField[2]; + + double propInZY = + Math.sqrt((accelerationY * accelerationY) + (accelerationZ * accelerationZ)); + + // Find pitch of the phone using accelerometer vector and make it independent from roll + double pitch = Math.atan2(accelerationX, propInZY); + + // Find roll of the phone using accelerometer data + double roll = Math.atan2(accelerationY, accelerationZ); + + // Find horizontal forward component of magnetic field + double mx = + magX * Math.cos(pitch) + + magY * Math.sin(roll) * Math.sin(pitch) + + magZ * Math.cos(roll) * Math.sin(pitch); + + // Find horizontal sideways component of magnetic field + double my = magY * Math.cos(roll) - magZ * Math.sin(roll); + + // Find heading from corrected magnetic field + float heading = (float) Math.atan2(my, mx); + Log.d(TAG, "heading estimated as: " + heading); + return heading; + } + + /** + * Helper function to extract the values from the row of a matrix + * + * @param matrix The matrix with data for extraction + * @param rowNumber The row being requested + * @return An array of float values from the row of the matrix + */ + private float[] extractRow(SimpleMatrix matrix, int rowNumber) { + float[] row = new float[matrix.numCols()]; + for (int i = 0; i < matrix.numCols(); i++) { + row[i] = (float) matrix.get(rowNumber, i); + } + return row; + } + + /** + * Helper function to extract the values from the row of a matrix + * + * @param angle The matrix with data for extraction + * @return An array of float values from the row of the matrix + */ + private float wrapAngle(float angle) { + while (angle > Math.PI) angle -= 2 * Math.PI; + while (angle < -Math.PI) angle += 2 * Math.PI; + return angle; + } + + public void setInitialHeading(float heading) { + prediction.set(0, 0, heading); // set heading state + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/fusion/MapMatching.java b/app/src/main/java/com/openpositioning/PositionMe/fusion/MapMatching.java new file mode 100644 index 00000000..4d6d3dae --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/fusion/MapMatching.java @@ -0,0 +1,328 @@ +package com.openpositioning.PositionMe.fusion; + +import android.util.Log; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Provides constraints to the movements made in fusion by using known building geometries to + * improve estimation by removing particles that move through walls with PDR updates. This class + * also uses building geometries to determine if elevation changes are eligible. + * + * @see Fusion + */ +public class MapMatching { + private static final String TAG = "MapMatching"; + + // Hashmaps hashing floor index to a list of floor plan elements + private Map>> walls; + private Map>> stairs; + private Map>> elevators; + + // Current floor estimate + private int floor; + + public MapMatching() {} + + /** + * sets the known geometries of the current building. + * + * @param walls maps floor number int to a list of EN points making all walls of that floor + * @param stairs maps floor number int to a list of EN points making all stairs of that floor + * @param elevators maps floor number int to a list of EN points making all elevators of that + * floor + */ + public void setGeometries( + Map>> walls, + Map>> stairs, + Map>> elevators) { + this.walls = walls; + this.stairs = stairs; + this.elevators = elevators; + Log.d( + TAG, + "Geometries set! (" + + walls.size() + + " walls; " + + stairs.size() + + " stairs; " + + elevators.size() + + " elevators)"); + } + + /** + * removes particles in which the next PDR position change estimates that move through a walls. + * + * @param currentParticles particles before a move + * @param bestEstmatePositionEN The current best Fusion estimate + */ + public List removeImpossibleParticles( + List currentParticles, double[] bestEstmatePositionEN) { + if (walls == null || walls.isEmpty()) { + Log.w(TAG, "No walls available; skipping map matching"); + return currentParticles; + } + + double currentX = bestEstmatePositionEN[0]; + double currentY = bestEstmatePositionEN[1]; + ArrayList validParticles = new ArrayList<>(currentParticles); + List> wallSegments = walls.get(floor); + for (Particle particle : currentParticles) { + double newX = particle.easting; + double newY = particle.northing; + + boolean crossedWall = false; + if (wallSegments == null) return currentParticles; + for (List wallSegment : wallSegments) { + for (int i = 0; i < wallSegment.size(); i++) { + double[] wallPointOne = wallSegment.get(i); + int j = i + 1; + if (j >= wallSegment.size()) { + j = 0; + } + double[] wallPointTwo = wallSegment.get(j); + double d1 = + cross( + wallPointOne[0], + wallPointOne[1], + wallPointTwo[0], + wallPointTwo[1], + currentX, + currentY); + double d2 = + cross( + wallPointOne[0], + wallPointOne[1], + wallPointTwo[0], + wallPointTwo[1], + newX, + newY); + double d3 = + cross(currentX, currentY, newX, newY, wallPointOne[0], wallPointOne[1]); + double d4 = + cross(currentX, currentY, newX, newY, wallPointTwo[0], wallPointTwo[1]); + + crossedWall = (d1 > 0 != d2 > 0) && (d3 > 0 != d4 > 0); + if (crossedWall) break; + } + if (crossedWall) break; + } + if (crossedWall) validParticles.remove(particle); + } + Log.d( + TAG, + "Removed " + + (currentParticles.size() - validParticles.size()) + + " invalid particles"); + return validParticles; + } + + /** + * Checks whether the movement from a current position to a new position crosses any wall on the + * current floor. + * + * @param currentEstimate the starting position as {@code [easting, northing]} + * @param newEstimate the proposed new position as {@code [easting, northing]} + * @return {@code true} if the movement crosses a wall segment, {@code false} otherwise + */ + public boolean checkWallCrossed(double[] currentEstimate, double[] newEstimate) { + if (walls == null) return false; + + List> wallSegments = walls.get(floor); + if (wallSegments == null) return false; + + // If already inside a wall, allow crossing walls (to leave wall polygon) + // if (isPointInAnyElement(wallSegments, currentEstimate)) return false; + + double currentX = currentEstimate[0]; + double currentY = currentEstimate[1]; + double newX = newEstimate[0]; + double newY = newEstimate[1]; + + for (List wallSegment : wallSegments) { + for (int i = 0; i < wallSegment.size(); i++) { + double[] wallPointOne = wallSegment.get(i); + int j = i + 1; + if (j >= wallSegment.size()) { + j = 0; + } + double[] wallPointTwo = wallSegment.get(j); + double d1 = + cross( + wallPointOne[0], + wallPointOne[1], + wallPointTwo[0], + wallPointTwo[1], + currentX, + currentY); + double d2 = + cross( + wallPointOne[0], + wallPointOne[1], + wallPointTwo[0], + wallPointTwo[1], + newX, + newY); + double d3 = cross(currentX, currentY, newX, newY, wallPointOne[0], wallPointOne[1]); + double d4 = cross(currentX, currentY, newX, newY, wallPointTwo[0], wallPointTwo[1]); + + if ((d1 > 0 != d2 > 0) && (d3 > 0 != d4 > 0)) { + return true; + } + } + } + return false; + } + + /** + * Determines if a user is in a staircase or elevator and therefore able to change altitude. + * + * @param position position to check if in stairway or elevator + * @return {@code true} if the position is if in stairway or elevator + */ + public boolean isEligibleForAltitudeChange(double[] position) { + if (stairs == null || elevators == null) { + Log.w(TAG, "Stairs or elevators not set; skipping altitude check"); + return false; + } + List> floorStairs = stairs.get(floor); + List> floorElevators = elevators.get(floor); + + // Check if position is inside any staircase + if (floorStairs != null) { + if (isPointInAnyElement(floorStairs, position)) { + Log.d(TAG, "Eligible for floor change: Stairs"); + return true; + } + } else { + Log.w(TAG, "Stairs is null!"); + } + + // Check if position is inside any elevator + if (floorElevators != null) { + if (isPointInAnyElement(floorElevators, position)) { + Log.d(TAG, "Eligible for floor change: Lifts"); + return true; + } + } else { + Log.w(TAG, "Lifts is null!"); + } + + Log.d(TAG, "Ineligible for floor change"); + return false; + } + + /** + * Checks whether a point lies inside any polygon in the given list of elements. + * + * @param elements list of polygons, each defined as an ordered list of {@code [x, y]} vertices + * @param point the test point as {@code [easting, northing]} + * @return {@code true} if the point is inside any of the polygons + */ + private boolean isPointInAnyElement(List> elements, double[] point) { + for (List element : elements) { + if (isPointInPolygon(point, element)) { + return true; + } + } + return false; + } + + /** + * Determines whether a point lies inside a polygon using the ray casting algorithm. + * + * @param pos the test point as {@code [x, y]} + * @param shape the polygon vertices as an ordered list of {@code [x, y]} points + * @return {@code true} if the point is inside the polygon + */ + private boolean isPointInPolygon(double[] pos, List shape) { + int crossings = 0; + for (int i = 0; i < shape.size(); i++) { + double[] firstPoint = shape.get(i); + int j = i + 1; + if (j >= shape.size()) { + j = 0; + } + double[] secondPoint = shape.get(j); + if (crossingSegment(pos, firstPoint, secondPoint)) { + crossings++; + } + } + return crossings % 2 == 1; + } + + /** + * Determines whether a horizontal ray cast rightward from a given point crosses a line segment + * defined by two endpoints, using the ray casting algorithm for point-in-polygon testing. + * + *

The method handles edge cases where the point's y-coordinate aligns exactly with a vertex + * by applying a small epsilon nudge to avoid double-counting shared vertices between adjacent + * segments. + * + * @param point the test point as {@code [x, y]} + * @param a one endpoint of the segment as {@code [x, y]} + * @param b the other endpoint of the segment as {@code [x, y]} + * @return {@code true} if a rightward ray from {@code point} crosses the segment + */ + private boolean crossingSegment(double[] point, double[] a, double[] b) { + double px = point[0], py = point[1]; + double ax = a[0], ay = a[1]; + double bx = b[0], by = b[1]; + + // Ensure a is the lower point + if (ay > by) { + ax = b[0]; + ay = b[1]; + bx = a[0]; + by = a[1]; + } + + // Nudge if point is exactly on a vertex's y + if (py == ay || py == by) py += 0.00000001; + + // Point is above, below, or to the right of segment + if (py > by || py < ay || px > Math.max(ax, bx)) { + return false; + } + // Point is to the left of segment + else if (px < Math.min(ax, bx)) { + return true; + } + // Compare slopes + else { + double slope1 = (ax != bx) ? ((by - ay) / (bx - ax)) : Double.POSITIVE_INFINITY; + double slope2 = (ax != px) ? ((py - ay) / (px - ax)) : Double.POSITIVE_INFINITY; + return (slope2 >= slope1); + } + } + + /** + * Sets the current floor estimate for local logic + * + * @param floor The new floor estimate + */ + public void setFloor(int floor) { + this.floor = floor; + } + + /** + * Computes the z-component of the cross product of vectors AB and AC. + * + *

A positive result indicates C is to the left of AB, a negative result indicates C is to + * the right, and zero indicates the points are collinear. + * + *

+ * + * @param ax x-coordinate of point A + * @param ay y-coordinate of point A + * @param bx x-coordinate of point B + * @param by y-coordinate of point B + * @param cx x-coordinate of point C + * @param cy y-coordinate of point C + * @return the z-component of AB × AC + */ + private double cross(double ax, double ay, double bx, double by, double cx, double cy) { + return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax); + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/fusion/Particle.java b/app/src/main/java/com/openpositioning/PositionMe/fusion/Particle.java new file mode 100644 index 00000000..c012c41c --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/fusion/Particle.java @@ -0,0 +1,43 @@ +package com.openpositioning.PositionMe.fusion; + +/** + * Representation of a particle within the {@link ParticleFilter} used in {@link Fusion} + * + *

As {@link Fusion} requires Easting-Northing coordinates, {@link + * com.google.android.gms.maps.model.LatLng} points must be converted before creating a new Particle + * (see {@link ParticleFilter#latLngToEN(double, double) ParticleFilter.latLngToEN()}) + * + * @see ParticleFilter + * @see Fusion + */ +public class Particle { + double easting; + double northing; + double orientationError; // radians: correction to apply to raw PDR heading + double weight; + + public Particle(double easting, double northing, double orientationError, double weight) { + this.easting = easting; + this.northing = northing; + this.orientationError = orientationError; + this.weight = weight; + } + + /** + * Retrieve the local Easting-Northing coordinates for a give particle + * + * @return The particle's Easting and Northing values in an array + */ + public double[] getEastingNorthing() { + return new double[] {easting, northing}; + } + + /** + * Retrieve the particle's weight + * + * @return The particle's weight + */ + public double getWeight() { + return weight; + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/fusion/ParticleFilter.java b/app/src/main/java/com/openpositioning/PositionMe/fusion/ParticleFilter.java new file mode 100644 index 00000000..a921c3c2 --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/fusion/ParticleFilter.java @@ -0,0 +1,443 @@ +package com.openpositioning.PositionMe.fusion; + +import static com.openpositioning.PositionMe.fusion.FusionConstants.INITIAL_UNCERTAINTY_M; +import static com.openpositioning.PositionMe.fusion.FusionConstants.MAX_STEP_LENGTH; +import static com.openpositioning.PositionMe.fusion.FusionConstants.METRES_PER_DEG_LAT; +import static com.openpositioning.PositionMe.fusion.FusionConstants.METRES_PER_DEG_LNG_AT_EQUATOR; +import static com.openpositioning.PositionMe.fusion.FusionConstants.PARTICLE_COUNT; +import static com.openpositioning.PositionMe.fusion.FusionConstants.PARTICLE_FILTER_THRESHOLD; +import static com.openpositioning.PositionMe.fusion.FusionConstants.RESAMPLE_JITTER; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; +import androidx.preference.PreferenceManager; +import com.google.android.gms.maps.model.LatLng; +import com.openpositioning.PositionMe.presentation.fragment.SettingsFragment; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +/** + * Particle filter for indoor position estimation. + * + *

Maintains a population of weighted particles in a local East-North coordinate frame and uses + * sequential Monte Carlo methods to estimate the user's position. Particles are propagated using + * PDR displacement and resampled using systematic resampling when weight degeneracy is detected. + * + * @see Fusion for the parent fusion class that drives this filter. + * @see FusionConstants for tuning parameters. + */ +public class ParticleFilter { + private static final String TAG = "ParticleFilter"; + // WGS84 reference point for local EN coordinate conversion + private double refLng, refLat; + // Particle population + private List particles; + private int maximumNumberOfParticles; + private boolean active; + private Random rand; + // Current best position estimate + private LatLng estimatedPosition; + // Map matching logic + private final MapMatching mapMatching; + private double orientationError = 0; + private float repopulationJitter = 0f; + private float particleFilterThreshold; + + // Internal representation of a single particle with 2D position and weight. + // + // List of position observations from different sensor readings + // Queued observations from GNSS and WiFi, waiting to be applied on the next PDR step + // Each entry is {easting (m), northing (m), sigma (m)} in the local Easting/Northing frame + private List pendingObs = new ArrayList<>(); + + public ParticleFilter(Context context, MapMatching mapMatching) { + this.mapMatching = mapMatching; + updateConstants(context); + } + + /** + * Update any constants used based on the user's values from the {@link SettingsFragment} + * + * @param context The current app context (for retrieving the settings) + */ + public void updateConstants(Context context) { + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + if (settings.getBoolean("overwrite_fusion_constants", false)) { + particleFilterThreshold = + (float) + settings.getInt( + "particle_threshold", + (int) PARTICLE_FILTER_THRESHOLD * 100) + / 100; + + maximumNumberOfParticles = settings.getInt("particle_count", PARTICLE_COUNT); + repopulationJitter = + (float) settings.getInt("resampling_variance", (int) RESAMPLE_JITTER * 100) + / 100; + } else { + particleFilterThreshold = (float) PARTICLE_FILTER_THRESHOLD; + maximumNumberOfParticles = PARTICLE_COUNT; + repopulationJitter = RESAMPLE_JITTER; + } + + Log.d(TAG, "Constants updated"); + Log.d(TAG, "particleFilterThreshold: " + particleFilterThreshold); + Log.d(TAG, "maximumNumberOfParticles: " + maximumNumberOfParticles); + Log.d(TAG, "repopulationJitter: " + repopulationJitter); + } + + /** + * Set the new maximum number of {@link Particle Particles} per iteration of the filter + * algorithm + * + * @param newMaximum The new maximum number of particles allowed + */ + public void setMaximumNumberOfParticles(int newMaximum) { + maximumNumberOfParticles = newMaximum; + } + + public void updateRepopulationJitter(float newJitter) { + repopulationJitter = newJitter; + } + + public List getParticles() { + return particles; + } + + public LatLng getEstimatedPosition() { + return estimatedPosition; + } + + /** + * Queues a position observation to be fused on the next PDR update. + * + * @param easting observed easting in metres (local EN frame). + * @param northing observed northing in metres (local EN frame). + * @param sigma observation uncertainty in metres. + */ + public void addObservation(double easting, double northing, double sigma) { + pendingObs.add(new double[] {easting, northing, sigma}); + } + + /** + * Initialises the particle filter with a cloud of equally weighted {@link Particle particles} + * around the given {@link LatLng} position. + * + * @param initialPosition starting position in WGS84 coordinates. + * @param sigmaMetres initial position uncertainty in metres. + */ + public void start(LatLng initialPosition, float sigmaMetres) { + pendingObs.clear(); + rand = new Random(); + refLat = initialPosition.latitude; + refLng = initialPosition.longitude; + active = true; + estimatedPosition = initialPosition; + double[] eastNorth = latLngToEN(initialPosition.latitude, initialPosition.longitude); + + // Generate and save maximumNumberOfParticles new particles + populateParticles(eastNorth[0], eastNorth[1]); + Log.d( + TAG, + "ParticleFilter started: " + + initialPosition + + "; sigma = " + + sigmaMetres + + "m; " + + "# of particles = " + + maximumNumberOfParticles); + } + + /** + * Creates a new particle population centred at the given position with Gaussian spread. + * + * @param easting centre easting in metres. + * @param northing centre northing in metres. + */ + private void populateParticles(double easting, double northing) { + ArrayList temp_particles = new ArrayList<>(maximumNumberOfParticles); + for (int i = 0; i < maximumNumberOfParticles; i++) { + temp_particles.add( + new Particle( + easting + rand.nextGaussian() * INITIAL_UNCERTAINTY_M, + northing + rand.nextGaussian() * INITIAL_UNCERTAINTY_M, + rand.nextGaussian() * FusionConstants.INITIAL_ORIENTATION_ERROR_STDDEV, + 1.0 / maximumNumberOfParticles)); + } + double[] bestEstimateEN = + latLngToEN(estimatedPosition.latitude, estimatedPosition.longitude); + particles = mapMatching.removeImpossibleParticles(temp_particles, bestEstimateEN); + } + + /** Stops the filter and releases the particle population. */ + public void stop() { + this.active = false; + if (particles != null) particles.clear(); + } + + /** + * Prediction step: Propagates all particles using a PDR displacement with added process noise. + * + *

After propagation, weights are updated and systematic resampling is triggered if weight + * degeneracy exceeds the threshold. The position estimate is updated each cycle. + * + * @param stepLength PDR step length in metres. + * @param rawHeading uncorrected heading in radians. + * @param dx easting displacement in metres from the PDR step (unused, recalculated internally). + * @param dy northing displacement in metres from the PDR step (unused, recalculated + * internally). + */ + public void updateWithPDR(double stepLength, double rawHeading, double dx, double dy) { + if (active && particles != null) { + + for (Particle p : particles) { + // Apply this particle's orientation error correction + double correctedHeading = rawHeading + p.orientationError; + + // Project step into local EN frame + p.easting += + stepLength * Math.sin(correctedHeading) + + rand.nextGaussian() * FusionConstants.PDR_NOISE_STDDEV; + p.northing += + stepLength * Math.cos(correctedHeading) + + rand.nextGaussian() * FusionConstants.PDR_NOISE_STDDEV; + + // Orientation error drifts slowly + p.orientationError += + rand.nextGaussian() * FusionConstants.ORIENTATION_DRIFT_STDDEV; + } + + double estOrientErr = getEstimatedOrientationError(); + orientationError = estOrientErr; + Log.d( + TAG, + "orientationError estimate=" + + estOrientErr + + " (" + + Math.toDegrees(estOrientErr) + + " deg)" + + " rawHeading=" + + rawHeading + + " correctedHeading=" + + (rawHeading + estOrientErr)); + + double maxWeight = updateWeights(); + if (maxWeight > particleFilterThreshold) { + repopulate(); + } + updateEstimatedPosition(); + } + } + + /** + * Returns the estimated orientation error as a weighted mean across particles. + * + * @return orientation error in radians. + */ + public double getEstimatedOrientationError() { + if (particles == null) return 0.0; + double sumOE = 0, sumW = 0; + for (Particle p : particles) { + sumOE += p.orientationError * p.weight; + sumW += p.weight; + } + return sumOE / sumW; + } + + /** + * Converts {@link LatLng} coordinates to local East-North metres relative to the reference + * point. + * + * @param lat latitude in degrees. + * @param lng longitude in degrees. + * @return double array {easting, northing} in metres. + */ + public double[] latLngToEN(double lat, double lng) { + double e = + (lng - refLng) * Math.cos(Math.toRadians(refLat)) * METRES_PER_DEG_LNG_AT_EQUATOR; + double n = (lat - refLat) * METRES_PER_DEG_LAT; + return new double[] {e, n}; + } + + /** + * Converts local East-North metres back to {@link LatLng} coordinates. + * + * @param easting east displacement in metres from reference. + * @param northing north displacement in metres from reference. + * @return {@link LatLng} position. + */ + public LatLng enToLatLng(double easting, double northing) { + double lat = refLat + northing / METRES_PER_DEG_LAT; + double lng = + refLng + + easting + / (METRES_PER_DEG_LNG_AT_EQUATOR + * Math.cos(Math.toRadians(refLat))); + return new LatLng(lat, lng); + } + + /** + * Update step: Assigns weights to particles based on observation likelihood. + * + * @return the maximum particle weight after normalisation. + */ + public double updateWeights() { + if (pendingObs.isEmpty() || particles == null) return 0.0; + + double weightSum = 0.0; + // Iterates through each particle and calculates difference between PDR data and recorded + // observation data + for (Particle p : particles) { + for (double[] obs : pendingObs) { + // Squared distance between this particle and the observation from sensors + double de = p.easting - obs[0]; + double dn = p.northing - obs[1]; + double distSq = de * de + dn * dn; + + // Particles closer to the observation get larger weights + double twoSigmaSq = 2.0 * obs[2] * obs[2]; + p.weight *= Math.exp(-distSq / twoSigmaSq); + } + weightSum += p.weight; + } + for (double[] obs : pendingObs) { + Log.d(TAG, "obs easting: " + obs[0] + "obs northing: " + obs[1]); + } + + // Clear queue for next PDR cycle + pendingObs.clear(); + + if (weightSum == 0.0) { + Log.w(TAG, "Weight underflow: resetting to uniform"); + double uniform = 1.0 / particles.size(); + for (Particle p : particles) p.weight = uniform; + return uniform; + } + + // Normalise so all weights sum to 1 + double maxWeight = 0.0; + for (Particle p : particles) { + p.weight /= weightSum; + if (p.weight > maxWeight) maxWeight = p.weight; + } + return maxWeight; + } + + /** Computes the weighted mean of the particle population as the current position estimate. */ + public void updateEstimatedPosition() { + double sum_e = 0, sum_n = 0, sum_w = 0; + for (Particle particle : particles) { + sum_e += particle.easting * particle.weight; + sum_n += particle.northing * particle.weight; + sum_w += particle.weight; + } + double new_east = sum_e / sum_w; + double new_north = sum_n / sum_w; + double[] newEstimate = {new_east, new_north}; + Log.d( + TAG, + "new position (no step correction)" + + "new_east: " + + new_east + + "north: " + + new_north); + double[] oldEstimate = latLngToEN(estimatedPosition.latitude, estimatedPosition.longitude); + double east_diff = new_east - oldEstimate[0]; + double north_diff = new_north - oldEstimate[1]; + double distance = Math.sqrt((east_diff * east_diff) + (north_diff * north_diff)); + if (distance >= MAX_STEP_LENGTH) { + double ratio = MAX_STEP_LENGTH / distance; + new_east = oldEstimate[0] + east_diff * ratio; + new_north = oldEstimate[1] + north_diff * ratio; + Log.d( + TAG, + "new position (w/ step correction)" + + "new_east: " + + new_east + + "north: " + + new_north); + } + if (!mapMatching.checkWallCrossed(oldEstimate, newEstimate)) { + estimatedPosition = enToLatLng(new_east, new_north); + } else { + populateParticles(oldEstimate[0], oldEstimate[1]); + } + } + + /** + * Systematic resampling of the particle population. + * + *

Builds a cumulative weight distribution and selects particles at evenly spaced intervals + * with a single random offset. Selected particles are duplicated with a small Gaussian jitter + * to maintain diversity, and weights are reset to uniform. + * + * @see FusionConstants#RESAMPLE_JITTER for the regularisation noise parameter. + */ + public void repopulate() { + ArrayList newParticles = new ArrayList<>(maximumNumberOfParticles); + + // Normalise weights + double totalWeight = 0; + for (Particle p : particles) { + totalWeight += p.weight; + } + for (Particle p : particles) { + p.weight /= totalWeight; + } + + // Build cumulative weight distribution + double[] cumulative = new double[particles.size()]; + cumulative[0] = particles.get(0).weight; + for (int i = 1; i < particles.size(); i++) { + cumulative[i] = cumulative[i - 1] + particles.get(i).weight; + } + + // Evenly spaced pointers with single random offset + double step = 1.0 / maximumNumberOfParticles; + double start = rand.nextDouble() * step; + int idx = 0; + + for (int i = 0; i < maximumNumberOfParticles; i++) { + double pointer = start + i * step; + while (cumulative[idx] < pointer) { + idx++; + } + Particle selected = particles.get(idx); + // Duplicate with jitter to prevent particle collapse + newParticles.add( + new Particle( + selected.easting + rand.nextGaussian() * repopulationJitter, + selected.northing + rand.nextGaussian() * repopulationJitter, + selected.orientationError + + rand.nextGaussian() + * FusionConstants.ORIENTATION_RESAMPLE_JITTER, + 1.0 / maximumNumberOfParticles)); + } + double[] bestEstimateEN = + latLngToEN(estimatedPosition.latitude, estimatedPosition.longitude); + particles = mapMatching.removeImpossibleParticles(newParticles, bestEstimateEN); + Log.i(TAG, "Repopulation of particles complete!"); + } + + public double getOrientationError() { + if (!Double.isNaN(orientationError)) { + return (float) orientationError; + } else { + return 0.00f; + } + } + + public void updateOnWifiOrGNSS() { + double max_weight = updateWeights(); + if (max_weight > PARTICLE_FILTER_THRESHOLD) { + repopulate(); + } + // updateEstimatedPosition(); + } + + public boolean isActive() { + return active; + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/LoginActivity.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/LoginActivity.java new file mode 100644 index 00000000..ba754ab9 --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/LoginActivity.java @@ -0,0 +1,37 @@ +package com.openpositioning.PositionMe.presentation.activity; + +import android.os.Bundle; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.app.AppCompatDelegate; +import androidx.navigation.NavController; +import androidx.navigation.fragment.NavHostFragment; +import com.openpositioning.PositionMe.R; +import java.util.Objects; + +/** + * {@inheritDoc} + * + *

Adds navigation control for the login navigation graph + */ +public class LoginActivity extends AppCompatActivity { + + private NavController navController; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); + setContentView(R.layout.activity_login); + + // Set up navigation and fragments + NavHostFragment navHostFragment = + (NavHostFragment) + getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment); + navController = Objects.requireNonNull(navHostFragment).getNavController(); + } + + @Override + public void onResume() { + super.onResume(); + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/MainActivity.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/MainActivity.java index 995f010d..10d40444 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/MainActivity.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/MainActivity.java @@ -1,23 +1,19 @@ package com.openpositioning.PositionMe.presentation.activity; -import android.Manifest; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.os.Build; +import android.content.Intent; +import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; +import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; - -import androidx.activity.result.ActivityResultLauncher; -import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.widget.Toolbar; - import androidx.core.content.ContextCompat; import androidx.navigation.NavController; import androidx.navigation.NavOptions; @@ -25,7 +21,6 @@ import androidx.navigation.ui.AppBarConfiguration; import androidx.navigation.ui.NavigationUI; import androidx.preference.PreferenceManager; - import com.openpositioning.PositionMe.R; import com.openpositioning.PositionMe.data.remote.ServerCommunications; import com.openpositioning.PositionMe.presentation.fragment.HomeFragment; @@ -33,80 +28,76 @@ import com.openpositioning.PositionMe.sensors.Observer; import com.openpositioning.PositionMe.sensors.SensorFusion; import com.openpositioning.PositionMe.utils.PermissionManager; - - import java.util.Objects; +import org.json.JSONException; +import org.json.JSONObject; /** - * The Main Activity of the application, handling setup, permissions and starting all other fragments - * and processes. - * The Main Activity takes care of most essential tasks before the app can run. Such as setting up - * the views, and enforcing light mode so the colour scheme is consistent. It initialises the - * various fragments and the navigation between them, getting the Navigation controller. It also - * loads the custom action bar with the set theme and icons, and enables back-navigation. The shared - * preferences are also loaded. - *

- * The most important task of the main activity is check and asking for the necessary permissions to - * enable the application to use the required hardware devices. This is done through a number of - * functions that call the OS, as well as pop-up messages warning the user if permissions are denied. - *

- * Once all permissions are granted, the Main Activity obtains the Sensor Fusion instance and sets - * the context, enabling the Fragments to interact with the class without setting it up again. + * The Main Activity of the application, handling setup, permissions and starting all other + * fragments and processes. The Main Activity takes care of most essential tasks before the app can + * run. Such as setting up the views, and enforcing light mode so the colour scheme is consistent. + * It initialises the various fragments and the navigation between them, getting the Navigation + * controller. It also loads the custom action bar with the set theme and icons, and enables + * back-navigation. The shared preferences are also loaded. + * + *

The most important task of the main activity is check and asking for the necessary permissions + * to enable the application to use the required hardware devices. This is done through a number of + * functions that call the OS, as well as pop-up messages warning the user if permissions are + * denied. + * + *

Once all permissions are granted, the Main Activity obtains the Sensor Fusion instance and + * sets the context, enabling the Fragments to interact with the class without setting it up again. * * @see HomeFragment the initial fragment displayed. * @see com.openpositioning.PositionMe.R.navigation the navigation graph. * @see SensorFusion the singletion data processing class. - * * @author Mate Stodulka * @author Virginia Cangelosi */ public class MainActivity extends AppCompatActivity implements Observer { + private static final String TAG = "MainActivity"; - - //region Instance variables private NavController navController; - private ActivityResultLauncher locationPermissionLauncher; - private ActivityResultLauncher multiplePermissionsLauncher; private SharedPreferences settings; private SensorFusion sensorFusion; private Handler httpResponseHandler; + private String httpFailureMessage = ""; private PermissionManager permissionManager; - private static final int PERMISSION_REQUEST_CODE = 100; - - //endregion - - //region Activity Lifecycle - /** - * {@inheritDoc} - * Forces light mode, sets up the navigation graph, initialises the toolbar with back action on - * the nav controller, loads the shared preferences and checks for all permissions necessary. - * Sets up a Handler for displaying messages from other classes. + * {@inheritDoc} Forces light mode, sets up the navigation graph, initialises the toolbar with + * back action on the nav controller, loads the shared preferences and checks for all + * permissions necessary. Sets up a Handler for displaying messages from other classes. */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); + if (AppCompatDelegate.getDefaultNightMode() != AppCompatDelegate.MODE_NIGHT_NO) { + Log.d(TAG, "Forcing light mode"); + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); + } setContentView(R.layout.activity_main); // Set up navigation and fragments - NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager() - .findFragmentById(R.id.nav_host_fragment); + NavHostFragment navHostFragment = + (NavHostFragment) + getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment); navController = Objects.requireNonNull(navHostFragment).getNavController(); // Set action bar Toolbar toolbar = findViewById(R.id.main_toolbar); setSupportActionBar(toolbar); toolbar.showOverflowMenu(); - toolbar.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.md_theme_light_surface)); + toolbar.setBackgroundColor( + ContextCompat.getColor(getApplicationContext(), R.color.md_theme_light_surface)); toolbar.setTitleTextColor(ContextCompat.getColor(getApplicationContext(), R.color.black)); toolbar.setNavigationIcon(R.drawable.ic_baseline_back_arrow); // Set up back action with NavigationUI - AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build(); + AppBarConfiguration appBarConfiguration = + new AppBarConfiguration.Builder(navController.getGraph()).build(); NavigationUI.setupWithNavController(toolbar, navController, appBarConfiguration); // Get handle for settings @@ -117,50 +108,43 @@ protected void onCreate(Bundle savedInstanceState) { this.sensorFusion = SensorFusion.getInstance(); this.sensorFusion.setContext(getApplicationContext()); - // Register multiple permissions launcher - multiplePermissionsLauncher = registerForActivityResult( - new ActivityResultContracts.RequestMultiplePermissions(), - result -> { - boolean locationGranted = result.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false); - boolean activityGranted = result.getOrDefault(Manifest.permission.ACTIVITY_RECOGNITION, false); - - if (locationGranted && activityGranted) { - // Both permissions granted - allPermissionsObtained(); - } else { - // Permission denied - Toast.makeText(this, - "Location or Physical Activity permission denied. Some features may not work.", - Toast.LENGTH_LONG).show(); - } - } - ); + permissionManager = + new PermissionManager( + this, + this, + ((allPermissionsGranted, deniedPermissions) -> { + if (isActivityVisible()) { + if (allPermissionsGranted) { + allPermissionsObtained(); + } else { + Log.d(TAG, "Missing permissions!"); + permissionManager.confirmDeniedPermissions(deniedPermissions); + } + } else { + Log.d(TAG, "Activity not visible; skipping permission check"); + } + })); + permissionManager.checkAndRequestPermissions(); // Handler for global toasts and popups from other classes this.httpResponseHandler = new Handler(); } - - - - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ @Override public void onPause() { super.onPause(); - //Ensure sensorFusion has been initialised before unregistering listeners - if(sensorFusion != null) { -// sensorFusion.stopListening(); + // Ensure sensorFusion has been initialised before unregistering listeners + if (sensorFusion != null) { + // sensorFusion.stopListening(); } } /** - * {@inheritDoc} - * Checks for activities in case the app was closed without granting them, or if they were - * granted through the settings page. Repeats the startup checks done in - * {@link MainActivity#onCreate(Bundle)}. Starts listening in the SensorFusion class. + * {@inheritDoc} Checks for activities in case the app was closed without granting them, or if + * they were granted through the settings page. Repeats the startup checks done in {@link + * MainActivity#onCreate(Bundle)}. Starts listening in the SensorFusion class. * * @see SensorFusion the main data processing class. */ @@ -172,32 +156,7 @@ public void onResume() { getSupportActionBar().show(); } - // Delay permission check slightly to ensure the Activity is in the foreground - new Handler().postDelayed(() -> { - if (isActivityVisible()) { - // Check if both permissions are granted - boolean locationGranted = ContextCompat.checkSelfPermission( - this, Manifest.permission.ACCESS_FINE_LOCATION - ) == PackageManager.PERMISSION_GRANTED; - - boolean activityGranted = ContextCompat.checkSelfPermission( - this, Manifest.permission.ACTIVITY_RECOGNITION - ) == PackageManager.PERMISSION_GRANTED; - - if (!locationGranted || !activityGranted) { - // Request both permissions using ActivityResultLauncher - multiplePermissionsLauncher.launch(new String[]{ - Manifest.permission.ACCESS_FINE_LOCATION - }); - multiplePermissionsLauncher.launch(new String[]{ - Manifest.permission.ACTIVITY_RECOGNITION - }); - } else { - // Both permissions are already granted - allPermissionsObtained(); - } - } - }, 300); // Delay ensures activity is fully visible before requesting permissions + permissionManager.checkMissingPermissions(); if (sensorFusion != null) { sensorFusion.resumeListening(); @@ -208,8 +167,6 @@ private boolean isActivityVisible() { return !isFinishing() && !isDestroyed(); } - - /** * Unregisters sensor listeners when the app closes. Not in {@link MainActivity#onPause()} to * enable recording data with a locked screen. @@ -219,22 +176,19 @@ private boolean isActivityVisible() { @Override protected void onDestroy() { if (sensorFusion != null) { -// sensorFusion.stopListening(); // suspended due to the need to record data with -// a locked screen or cross activity + // sensorFusion.stopListening(); // suspended due to the need to record data + // with + // a locked screen or cross activity } + Log.d(TAG, "MainActivity being destroyed"); super.onDestroy(); } - - //endregion - - //region Permissions - /** - * Prepares global resources when all permissions are granted. - * Resets the permissions tracking boolean in shared preferences, and initialises the - * {@link SensorFusion} class with the application context, and registers the main activity to - * listen for server responses that SensorFusion receives. + * Prepares global resources when all permissions are granted. Resets the permissions tracking + * boolean in shared preferences, and initialises the {@link SensorFusion} class with the + * application context, and registers the main activity to listen for server responses that + * SensorFusion receives. * * @see SensorFusion the main data processing class. * @see ServerCommunications the communication class sending and recieving data from the server. @@ -251,46 +205,36 @@ private void allPermissionsObtained() { sensorFusion.registerForServerUpdate(this); } - - - - //endregion - - //region Navigation - /** - * {@inheritDoc} - * Sets desired animations and navigates to {@link SettingsFragment} - * when the settings wheel in the action bar is clicked. + * {@inheritDoc} Sets desired animations and navigates to {@link SettingsFragment} when the + * settings wheel in the action bar is clicked. */ @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if(Objects.requireNonNull(navController.getCurrentDestination()).getId() == item.getItemId()) - return super.onOptionsItemSelected(item); + if (Objects.requireNonNull(navController.getCurrentDestination()).getId() + == item.getItemId()) return super.onOptionsItemSelected(item); else { - NavOptions options = new NavOptions.Builder() - .setLaunchSingleTop(true) - .setEnterAnim(R.anim.slide_in_bottom) - .setExitAnim(R.anim.slide_out_top) - .setPopEnterAnim(R.anim.slide_in_top) - .setPopExitAnim(R.anim.slide_out_bottom).build(); + NavOptions options = + new NavOptions.Builder() + .setLaunchSingleTop(true) + .setEnterAnim(R.anim.slide_in_bottom) + .setExitAnim(R.anim.slide_out_top) + .setPopEnterAnim(R.anim.slide_in_top) + .setPopExitAnim(R.anim.slide_out_bottom) + .build(); navController.navigate(R.id.action_global_settingsFragment, null, options); return true; } } - /** - * {@inheritDoc} - * Enables navigating back between fragments. - */ + /** {@inheritDoc} Enables navigating back between fragments. */ @Override public boolean onSupportNavigateUp() { return navController.navigateUp() || super.onSupportNavigateUp(); } /** - * {@inheritDoc} - * Inflate the designed menu view. + * {@inheritDoc} Inflate the designed menu view. * * @see com.openpositioning.PositionMe.R.menu for the xml file. */ @@ -301,22 +245,25 @@ public boolean onCreateOptionsMenu(Menu menu) { } /** - * {@inheritDoc} - * Handles the back button press. If the current fragment is the HomeFragment, a dialog is - * displayed to confirm the exit. If not, the default back navigation is performed. + * {@inheritDoc} Handles the back button press. If the current fragment is the LoginFragment, a + * dialog is displayed to confirm the exit. If not, the default back navigation is performed. */ @Override public void onBackPressed() { - // Check if the current destination is HomeFragment (assumed to be the root) - if (navController.getCurrentDestination() != null && - navController.getCurrentDestination().getId() == R.id.homeFragment) { + // Check if the current destination is LoginFragment (assumed to be the root) + if (navController.getCurrentDestination() != null + && navController.getCurrentDestination().getId() == R.id.homeFragment) { new AlertDialog.Builder(this) .setTitle("Confirm Exit") - .setMessage("Are you sure you want to exit the app?") - .setPositiveButton("Yes", (dialog, which) -> { - dialog.dismiss(); - finish(); // Close the activity (exit the app) - }) + .setMessage("Are you sure you want to log out?") + .setPositiveButton( + "Yes", + (dialog, which) -> { + dialog.dismiss(); + Intent intent = new Intent(this, LoginActivity.class); + startActivity(intent); + finish(); + }) .setNegativeButton("No", (dialog, which) -> dialog.dismiss()) .create() .show(); @@ -326,41 +273,86 @@ public void onBackPressed() { } } - - - //endregion - - //region Global toasts - /** * {@inheritDoc} - * Calls the corresponding handler that runs a toast on the Main UI thread. + * + *

Calls the corresponding handler that runs a toast on the Main UI thread. */ @Override public void update(Object[] objList) { - assert objList[0] instanceof Boolean; - if((Boolean) objList[0]) { - this.httpResponseHandler.post(displayToastTaskSuccess); - } - else { - this.httpResponseHandler.post(displayToastTaskFailure); + boolean success = (boolean) objList[0]; + String response = objList[1].toString(); + Log.i(TAG, response); + + if (success) { + httpResponseHandler.post(displayToastTaskSuccess); + } else { + try { + String errorCode = response.split(":", 2)[0]; + if (errorCode.equals(getString(R.string.errorCodeNoServerResponse))) return; + + String errorMessage = response.split(":", 2)[1]; + if (errorMessage.contains("{")) { + JSONObject jsonObject = new JSONObject(errorMessage); + + // Error usually split by :, but not always + String cause = jsonObject.getString("detail"); + String causeSource, causeMessage; + if (!cause.contains(":")) { + causeSource = ""; + causeMessage = cause; + } else { + String[] causeElements = cause.split(":", 2); + causeSource = causeElements[0].strip(); + causeMessage = causeElements[1].strip(); + } + + new Handler(Looper.getMainLooper()) + .post( + () -> + new AlertDialog.Builder(this) + .setTitle("Trajectory Upload Failed") + .setMessage( + "The server has declined this" + + " trajectory. The response is" + + " shown below:\n\n" + + causeSource + + "\n" + + causeMessage) + .setPositiveButton( + "Okay", + (dialog, which) -> { + dialog.dismiss(); + }) + .create() + .show()); + } else { + httpFailureMessage = errorMessage; + httpResponseHandler.post(displayToastTaskFailure); + } + } catch (JSONException e) { + Log.w(TAG, e.getMessage()); + httpFailureMessage = response.split(":", 2)[1]; + httpResponseHandler.post(displayToastTaskFailure); + } } } /** - * Task that displays positive toast on the main UI thread. - * Called when {@link ServerCommunications} successfully uploads a trajectory. + * Task that displays positive toast on the main UI thread. Called when {@link + * ServerCommunications} successfully uploads a trajectory. */ - private final Runnable displayToastTaskSuccess = () -> Toast.makeText(MainActivity.this, - "Trajectory uploaded", Toast.LENGTH_SHORT).show(); + private final Runnable displayToastTaskSuccess = + () -> + Toast.makeText(MainActivity.this, "Trajectory uploaded", Toast.LENGTH_SHORT) + .show(); /** - * Task that displays negative toast on the main UI thread. - * Called when {@link ServerCommunications} fails to upload a trajectory. + * Task that displays negative toast on the main UI thread. Called when {@link + * ServerCommunications} fails to upload a trajectory. */ - private final Runnable displayToastTaskFailure = () -> { -// Toast.makeText(MainActivity.this, "Failed to complete trajectory upload", Toast.LENGTH_SHORT).show(); - }; - - //endregion -} \ No newline at end of file + private final Runnable displayToastTaskFailure = + () -> { + Toast.makeText(MainActivity.this, httpFailureMessage, Toast.LENGTH_SHORT).show(); + }; +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/RecordingActivity.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/RecordingActivity.java index c0d82ae2..cc22fbf8 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/RecordingActivity.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/RecordingActivity.java @@ -2,42 +2,43 @@ import android.os.Bundle; import android.view.WindowManager; - import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.FragmentTransaction; - import com.openpositioning.PositionMe.R; -import com.openpositioning.PositionMe.presentation.fragment.StartLocationFragment; -import com.openpositioning.PositionMe.presentation.fragment.RecordingFragment; import com.openpositioning.PositionMe.presentation.fragment.CorrectionFragment; - +import com.openpositioning.PositionMe.presentation.fragment.RecordingFragment; +import com.openpositioning.PositionMe.presentation.fragment.StartLocationFragment; /** - * The RecordingActivity manages the recording flow of the application, guiding the user through a sequence - * of screens for location selection, recording, and correction before finalizing the process. - *

- * This activity follows a structured workflow: + * The RecordingActivity manages the recording flow of the application, guiding the user through a + * sequence of screens for location selection, recording, and correction before finalizing the + * process. + * + *

This activity follows a structured workflow: + * *

    - *
  1. StartLocationFragment - Allows users to select their starting location.
  2. - *
  3. RecordingFragment - Handles the recording process and contains a TrajectoryMapFragment.
  4. - *
  5. CorrectionFragment - Enables users to review and correct recorded data before completion.
  6. + *
  7. StartLocationFragment - Allows users to select their starting location. + *
  8. RecordingFragment - Handles the recording process and contains a TrajectoryMapFragment. + *
  9. CorrectionFragment - Enables users to review and correct recorded data before completion. *
- *

- * The activity ensures that the screen remains on during the recording process to prevent interruptions. - * It also provides fragment transactions for seamless navigation between different stages of the workflow. - *

- * This class is referenced in various fragments such as HomeFragment, StartLocationFragment, + * + *

The activity ensures that the screen remains on during the recording process to prevent + * interruptions. It also provides fragment transactions for seamless navigation between different + * stages of the workflow. + * + *

This class is referenced in various fragments such as LoginFragment, StartLocationFragment, * RecordingFragment, and CorrectionFragment to control navigation through the recording flow. * - * @see StartLocationFragment The first step in the recording process where users select their starting location. + * @see StartLocationFragment The first step in the recording process where users select their + * starting location. * @see RecordingFragment Handles data recording and map visualization. - * @see CorrectionFragment Allows users to review and make corrections before finalizing the process. - * @see com.openpositioning.PositionMe.R.layout#activity_recording The associated layout for this activity. - * + * @see CorrectionFragment Allows users to review and make corrections before finalizing the + * process. + * @see com.openpositioning.PositionMe.R.layout#activity_recording The associated layout for this + * activity. * @author ShuGu */ - public class RecordingActivity extends AppCompatActivity { @Override @@ -51,20 +52,44 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { // Keep screen on getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + // Back button handler + getOnBackPressedDispatcher() + .addCallback( + this, + new androidx.activity.OnBackPressedCallback(true) { + @Override + public void handleOnBackPressed() { + androidx.fragment.app.Fragment currentFragment = + getSupportFragmentManager() + .findFragmentById(R.id.mainFragmentContainer); + + // If on the Correction screen, exit to Home + if (currentFragment + instanceof + com.openpositioning.PositionMe.presentation + .fragment + .CorrectionFragment) { + finishFlow(); + } else { + // Otherwise, temporarily disable this behaviour and trigger the + // default back behaviour + setEnabled(false); + getOnBackPressedDispatcher().onBackPressed(); + setEnabled(true); + } + } + }); } - /** - * Show the StartLocationFragment (beginning of flow). - */ + /** Show the StartLocationFragment (beginning of flow). */ public void showStartLocationScreen() { FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.mainFragmentContainer, new StartLocationFragment()); ft.commit(); } - /** - * Show the RecordingFragment, which contains the TrajectoryMapFragment internally. - */ + /** Show the RecordingFragment, which contains the TrajectoryMapFragment internally. */ public void showRecordingScreen() { FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.mainFragmentContainer, new RecordingFragment()); @@ -72,9 +97,7 @@ public void showRecordingScreen() { ft.commit(); } - /** - * Show the CorrectionFragment after the user stops recording. - */ + /** Show the CorrectionFragment after the user stops recording. */ public void showCorrectionScreen() { FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.mainFragmentContainer, new CorrectionFragment()); @@ -82,9 +105,7 @@ public void showCorrectionScreen() { ft.commit(); } - /** - * Finish the Activity (or do any final steps) once corrections are done. - */ + /** Finish the Activity (or do any final steps) once corrections are done. */ public void finishFlow() { getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); finish(); diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/ReplayActivity.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/ReplayActivity.java index c6a30472..af597a00 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/ReplayActivity.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/activity/ReplayActivity.java @@ -2,48 +2,46 @@ import android.os.Bundle; import android.util.Log; -import java.io.File; - +import android.view.WindowManager; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; - import com.openpositioning.PositionMe.R; import com.openpositioning.PositionMe.presentation.fragment.ReplayFragment; import com.openpositioning.PositionMe.presentation.fragment.StartLocationFragment; - +import java.io.File; /** - * The ReplayActivity is responsible for managing the replay session of a user's trajectory. - * It handles the process of retrieving the trajectory data, displaying relevant fragments, and + * The ReplayActivity is responsible for managing the replay session of a user's trajectory. It + * handles the process of retrieving the trajectory data, displaying relevant fragments, and * facilitating the interaction with the user to choose the starting location before displaying the * replay of the trajectory. - *

- * The activity starts by extracting the trajectory file path from the intent that launched it. If - * the file path is not provided or is empty, it uses a default file path. It ensures that the trajectory - * file exists before proceeding. Once the file is verified, it shows the StartLocationFragment, which allows - * the user to select their starting location (latitude and longitude). After the user has selected the - * starting point, the activity switches to the ReplayFragment to display the replay of the user's trajectory. - *

- * The activity also provides functionality to finish the replay session and exit the activity once the replay - * process has completed. - *

- * This activity makes use of a few key constants for passing data between fragments, including the trajectory file - * path and the initial latitude and longitude. These constants are defined at the beginning of the class. - *

- * The ReplayActivity manages the interaction between fragments by facilitating communication from the - * StartLocationFragment to the ReplayFragment, where the replay of the trajectory is displayed. * - * @see StartLocationFragment The fragment where the user selects their start location for the trajectory replay. - * @see ReplayFragment The fragment responsible for showing the trajectory replay. + *

The activity starts by extracting the trajectory file path from the intent that launched it. + * If the file path is not provided or is empty, it uses a default file path. It ensures that the + * trajectory file exists before proceeding. Once the file is verified, it shows the + * StartLocationFragment, which allows the user to select their starting location (latitude and + * longitude). After the user has selected the starting point, the activity switches to the + * ReplayFragment to display the replay of the user's trajectory. + * + *

The activity also provides functionality to finish the replay session and exit the activity + * once the replay process has completed. + * + *

This activity makes use of a few key constants for passing data between fragments, including + * the trajectory file path and the initial latitude and longitude. These constants are defined at + * the beginning of the class. * + *

The ReplayActivity manages the interaction between fragments by facilitating communication + * from the StartLocationFragment to the ReplayFragment, where the replay of the trajectory is + * displayed. + * + * @see StartLocationFragment The fragment where the user selects their start location for the + * trajectory replay. + * @see ReplayFragment The fragment responsible for showing the trajectory replay. * @author Shu Gu */ - public class ReplayActivity extends AppCompatActivity { public static final String TAG = "ReplayActivity"; - public static final String EXTRA_INITIAL_LAT = "extra_initial_lat"; - public static final String EXTRA_INITIAL_LON = "extra_initial_lon"; public static final String EXTRA_TRAJECTORY_FILE_PATH = "extra_trajectory_file_path"; private String filePath; @@ -71,46 +69,18 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { Log.i(TAG, "Trajectory file exists: " + filePath); } - // Show StartLocationFragment first to let user pick location - if (savedInstanceState == null) { - showStartLocationFragment(); - } - } - - /** - * Display a StartLocationFragment to let user set their start location. - * Displays the ReplayFragment and passes the trajectory file path as an argument. - */ - private void showStartLocationFragment() { - Log.d(TAG, "Showing StartLocationFragment..."); - StartLocationFragment startLocationFragment = new StartLocationFragment(); - getSupportFragmentManager() - .beginTransaction() - .replace(R.id.replayActivityContainer, startLocationFragment) - .commit(); - } - - /** - * Called by StartLocationFragment when user picks their start location. - */ - public void onStartLocationChosen(float lat, float lon) { - Log.i(TAG, "User selected start location: Lat=" + lat + ", Lon=" + lon); - showReplayFragment(filePath, lat, lon); + getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + showReplayFragment(filePath); } - /** - * Display ReplayFragment, passing file path and starting lat/lon as arguments. - */ - public void showReplayFragment(String filePath, float initialLat, float initialLon) { - Log.d(TAG, "Switching to ReplayFragment with file: " + filePath + - ", Initial Lat: " + initialLat + ", Initial Lon: " + initialLon); + /** Display ReplayFragment, passing file path and starting lat/lon as arguments. */ + public void showReplayFragment(String filePath) { + Log.d(TAG, "Switching to ReplayFragment with file: " + filePath); ReplayFragment replayFragment = new ReplayFragment(); // Pass the file path through a Bundle Bundle args = new Bundle(); args.putString(EXTRA_TRAJECTORY_FILE_PATH, filePath); - args.putFloat(EXTRA_INITIAL_LAT, initialLat); - args.putFloat(EXTRA_INITIAL_LON, initialLon); replayFragment.setArguments(args); getSupportFragmentManager() @@ -119,12 +89,9 @@ public void showReplayFragment(String filePath, float initialLat, float initialL .commit(); } - /** - * Finish replay session - * Called when the replay process is completed. - */ + /** Finish replay session Called when the replay process is completed. */ public void finishFlow() { Log.d(TAG, "Replay session finished."); finish(); } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/CorrectionFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/CorrectionFragment.java index 8f94cb27..bbf4f1c1 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/CorrectionFragment.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/CorrectionFragment.java @@ -1,31 +1,41 @@ package com.openpositioning.PositionMe.presentation.fragment; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_PATH_FUSION; +import static com.openpositioning.PositionMe.utils.UtilConstants.BUILDING_NAME_M_HOUSE; +import static com.openpositioning.PositionMe.utils.UtilConstants.BUILDING_NAME_NUCLEUS; +import static com.openpositioning.PositionMe.utils.UtilConstants.BUILDING_NAME_OUTSIDE; + import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; +import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; +import android.widget.Spinner; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; +import androidx.cardview.widget.CardView; import androidx.fragment.app.Fragment; - -import com.openpositioning.PositionMe.R; -import com.openpositioning.PositionMe.presentation.activity.RecordingActivity; -import com.openpositioning.PositionMe.sensors.SensorFusion; -import com.openpositioning.PositionMe.utils.PathView; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; +import com.google.android.gms.maps.model.PolylineOptions; +import com.openpositioning.PositionMe.R; +import com.openpositioning.PositionMe.presentation.activity.RecordingActivity; +import com.openpositioning.PositionMe.sensors.SensorFusion; +import com.openpositioning.PositionMe.utils.PathView; +import java.util.List; /** * A simple {@link Fragment} subclass. Corrections Fragment is displayed after a recording session @@ -33,11 +43,11 @@ */ public class CorrectionFragment extends Fragment { - //Map variable + // Map variable public GoogleMap mMap; - //Button to go to next + // Button to go to next private Button button; - //Singleton SensorFusion class + // Singleton SensorFusion class private SensorFusion sensorFusion = SensorFusion.getInstance(); private TextView averageStepLengthText; private EditText stepLengthInput; @@ -49,49 +59,83 @@ public class CorrectionFragment extends Fragment { private static LatLng start; private PathView pathView; + private Spinner campaignSelect; + private String selectedCampaign; + + private TextView campaignText; + + private CardView cardView; + public CorrectionFragment() { // Required empty public constructor } @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { AppCompatActivity activity = (AppCompatActivity) getActivity(); if (activity != null && activity.getSupportActionBar() != null) { activity.getSupportActionBar().hide(); } View rootView = inflater.inflate(R.layout.fragment_correction, container, false); - // Send trajectory data to the cloud - sensorFusion.sendTrajectoryToCloud(); - - //Obtain start position + // Obtain start position float[] startPosition = sensorFusion.getGNSSLatitude(true); // Initialize map fragment - SupportMapFragment supportMapFragment=(SupportMapFragment) - getChildFragmentManager().findFragmentById(R.id.map); - - supportMapFragment.getMapAsync(new OnMapReadyCallback() { - @Override - public void onMapReady(GoogleMap map) { - mMap = map; - mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); - mMap.getUiSettings().setCompassEnabled(true); - mMap.getUiSettings().setTiltGesturesEnabled(true); - mMap.getUiSettings().setRotateGesturesEnabled(true); - mMap.getUiSettings().setScrollGesturesEnabled(true); - - // Add a marker at the start position - start = new LatLng(startPosition[0], startPosition[1]); - mMap.addMarker(new MarkerOptions().position(start).title("Start Position")); - - // Calculate zoom for demonstration - double zoom = Math.log(156543.03392f * Math.cos(startPosition[0] * Math.PI / 180) - * scalingRatio) / Math.log(2); - mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(start, (float) zoom)); - } - }); + SupportMapFragment supportMapFragment = + (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map); + + supportMapFragment.getMapAsync( + new OnMapReadyCallback() { + @Override + public void onMapReady(GoogleMap map) { + mMap = map; + mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); + mMap.getUiSettings().setCompassEnabled(true); + mMap.getUiSettings().setTiltGesturesEnabled(true); + mMap.getUiSettings().setRotateGesturesEnabled(true); + mMap.getUiSettings().setScrollGesturesEnabled(true); + + // Add a marker at the start position + start = new LatLng(startPosition[0], startPosition[1]); + mMap.addMarker(new MarkerOptions().position(start).title("Start Position")); + + List fusionPath = sensorFusion.fusion.getLiveTrajectory(); + if (fusionPath != null && !fusionPath.isEmpty()) { + mMap.addPolyline( + new PolylineOptions() + .addAll(fusionPath) + .color(COLOUR_PATH_FUSION) + .width(10f)); + + // Tell map to ignore the top and bottom card/spacing + float density = getResources().getDisplayMetrics().density; + mMap.setPadding(0, (int) (120 * density), 0, (int) (300 * density)); + + // Use LatLngBounds to frame the path on the screen + if (fusionPath.size() > 1) { + com.google.android.gms.maps.model.LatLngBounds.Builder + boundsBuilder = + new com.google.android.gms.maps.model.LatLngBounds + .Builder(); + for (LatLng point : fusionPath) { + boundsBuilder.include(point); + } + // padding in pixels from the edge of the screen + mMap.moveCamera( + CameraUpdateFactory.newLatLngBounds( + boundsBuilder.build(), 100)); + } else { + mMap.moveCamera( + CameraUpdateFactory.newLatLngZoom(fusionPath.get(0), 14f)); + } + } else { + // Default if path is empty + mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(start, 14f)); + } + } + }); return rootView; } @@ -103,59 +147,128 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat this.averageStepLengthText = view.findViewById(R.id.averageStepView); this.stepLengthInput = view.findViewById(R.id.inputStepLength); this.pathView = view.findViewById(R.id.pathView1); + this.pathView.setVisibility(View.GONE); + + this.campaignSelect = view.findViewById(R.id.campaignSelectSpinner); + this.campaignText = view.findViewById(R.id.correctedCampaingTextView); + this.cardView = view.findViewById(R.id.cardView2); + + // Call for user to select campaign if necessary + initCampaignSelect(); averageStepLength = sensorFusion.passAverageStepLength(); - averageStepLengthText.setText(getString(R.string.averageStepLgn) + ": " - + String.format("%.2f", averageStepLength)); + averageStepLengthText.setText( + getString(R.string.averageStepLgn) + + ": " + + String.format("%.2f", averageStepLength)); // Listen for ENTER key - this.stepLengthInput.setOnKeyListener((v, keyCode, event) -> { - if (keyCode == KeyEvent.KEYCODE_ENTER) { - newStepLength = Float.parseFloat(changedText.toString()); - // Rescale path - sensorFusion.redrawPath(newStepLength / averageStepLength); - averageStepLengthText.setText(getString(R.string.averageStepLgn) - + ": " + String.format("%.2f", newStepLength)); - pathView.invalidate(); - - secondPass++; - if (secondPass == 2) { - averageStepLength = newStepLength; - secondPass = 0; - } - } - return false; - }); - - this.stepLengthInput.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count,int after) {} - @Override - public void onTextChanged(CharSequence s, int start, int before,int count) {} - @Override - public void afterTextChanged(Editable s) { - changedText = s; - } - }); + this.stepLengthInput.setOnKeyListener( + (v, keyCode, event) -> { + if (keyCode == KeyEvent.KEYCODE_ENTER) { + newStepLength = Float.parseFloat(changedText.toString()); + // Rescale path + sensorFusion.redrawPath(newStepLength / averageStepLength); + averageStepLengthText.setText( + getString(R.string.averageStepLgn) + + ": " + + String.format("%.2f", newStepLength)); + pathView.invalidate(); + + secondPass++; + if (secondPass == 2) { + averageStepLength = newStepLength; + secondPass = 0; + } + } + return false; + }); + + this.stepLengthInput.addTextChangedListener( + new TextWatcher() { + @Override + public void beforeTextChanged( + CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {} + + @Override + public void afterTextChanged(Editable s) { + changedText = s; + } + }); // Button to finalize corrections this.button = view.findViewById(R.id.correction_done); - this.button.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - // ************* CHANGED CODE HERE ************* - // Before: - // NavDirections action = CorrectionFragmentDirections.actionCorrectionFragmentToHomeFragment(); - // Navigation.findNavController(view).navigate(action); - // ((AppCompatActivity)getActivity()).getSupportActionBar().show(); - - // Now, simply tell the Activity we are done: - ((RecordingActivity) requireActivity()).finishFlow(); - } - }); + this.button.setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View view) { + // Set campaign, and wait until upload is complete + sensorFusion.setCurrentBuilding(selectedCampaign); + boolean result = sensorFusion.sendTrajectoryToCloud(); + while (!result) {} + sensorFusion.setCurrentBuilding(BUILDING_NAME_OUTSIDE); + + // Now, simply tell the Activity we are done: + ((RecordingActivity) requireActivity()).finishFlow(); + } + }); } public void setScalingRatio(float scalingRatio) { this.scalingRatio = scalingRatio; } + + private void initCampaignSelect() { + if (campaignSelect == null) return; + + // Retrieve the current building from SensorFusion + String currentBuilding = SensorFusion.getInstance().getCurrentBuilding(); + + // Check if the building is "outside" + if ("outside".equalsIgnoreCase(currentBuilding)) { + + // Initialize campaigns only if the building is "outside" + String[] campaigns = new String[] {"Murchison House", "Nucleus Building"}; + ArrayAdapter adapter = + new ArrayAdapter<>( + requireContext(), + android.R.layout.simple_spinner_dropdown_item, + campaigns); + campaignSelect.setAdapter(adapter); + campaignSelect.setSelection(0); + + // Set item selected listener + campaignSelect.setOnItemSelectedListener( + new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected( + AdapterView parent, View view, int position, long id) { + switch (position) { + case 0: + selectedCampaign = BUILDING_NAME_M_HOUSE; + break; + case 1: + selectedCampaign = BUILDING_NAME_NUCLEUS; + break; + } + // Log selection + Log.d("CorrectionFragment", "Selected building: " + selectedCampaign); + } + + @Override + public void onNothingSelected(AdapterView parent) { + selectedCampaign = BUILDING_NAME_OUTSIDE; + } + }); + } else { + selectedCampaign = currentBuilding; + // Hide the Spinner if not "outside" + campaignSelect.setVisibility(View.GONE); + cardView.setVisibility(View.GONE); + campaignText.setVisibility(View.GONE); + } + } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/FilesFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/FilesFragment.java index 83bc4ef1..6db1db4c 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/FilesFragment.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/FilesFragment.java @@ -1,36 +1,42 @@ package com.openpositioning.PositionMe.presentation.fragment; +import static com.openpositioning.PositionMe.utils.UtilConstants.DEBUG_MODE_HEADER; +import static com.openpositioning.PositionMe.utils.UtilConstants.URL_GET_USER_TRAJECTORIES; + +import android.content.SharedPreferences; import android.os.Bundle; import android.os.Handler; import android.os.Looper; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Spinner; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.cardview.widget.CardView; import androidx.fragment.app.Fragment; import androidx.navigation.NavDirections; import androidx.navigation.Navigation; +import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; - import com.openpositioning.PositionMe.R; +import com.openpositioning.PositionMe.data.remote.LoginManager; import com.openpositioning.PositionMe.data.remote.ServerCommunications; +import com.openpositioning.PositionMe.presentation.viewitems.TrajDownloadListAdapter; import com.openpositioning.PositionMe.presentation.viewitems.TrajDownloadViewHolder; import com.openpositioning.PositionMe.sensors.Observer; -import com.openpositioning.PositionMe.presentation.viewitems.TrajDownloadListAdapter; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; /** * A simple {@link Fragment} subclass. The files fragments displays a list of trajectories already @@ -40,59 +46,85 @@ * @see UploadFragment sub-menu for uploading recordings that failed during recording. * @see com.openpositioning.PositionMe.Traj the data structure sent and received. * @see ServerCommunications the class handling communication with the server. - * * @author Mate Stodulka */ public class FilesFragment extends Fragment implements Observer { + private static final String TAG = "FilesFragment"; + + private static final String[] sortMethods = new String[] {"Latest First", "Oldest First"}; // UI elements private RecyclerView filesList; private TrajDownloadListAdapter listAdapter; private CardView uploadCard; + private Spinner spinnerSortBy; + private Comparator sortMethod = Comparator.reverseOrder(); // Class handling HTTP communication private ServerCommunications serverCommunications; + private LoginManager loginManager; + private List> entryList = new ArrayList<>(); - /** - * Default public constructor, empty. - */ + /** Default public constructor, empty. */ public FilesFragment() { // Required empty public constructor } /** - * {@inheritDoc} - * Initialise the server communication class and register the FilesFragment as an Observer to - * receive the async http responses. + * {@inheritDoc} Initialise the server communication class and register the FilesFragment as an + * Observer to receive the async http responses. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); serverCommunications = new ServerCommunications(getActivity()); serverCommunications.registerObserver(this); + loginManager = LoginManager.getInstance(); } - /** - * {@inheritDoc} - * Sets the title in the action bar. - */ @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public void onResume() { + super.onResume(); + if (serverCommunications == null) { + serverCommunications = new ServerCommunications(getActivity()); + } + serverCommunications.registerObserver(this); + + if (loginManager == null) { + loginManager = LoginManager.getInstance(); + } + } + + /** {@inheritDoc} Sets the title in the action bar. */ + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View rootView = inflater.inflate(R.layout.fragment_files, container, false); - getActivity().setTitle("Trajectory recordings"); + + // Make debug mode explicit in the header + String debugHeader; + SharedPreferences settings = + PreferenceManager.getDefaultSharedPreferences(requireContext()); + if (settings.getBoolean("debug_mode", false)) { + debugHeader = DEBUG_MODE_HEADER; + } else { + debugHeader = ""; + } + getActivity() + .setTitle(debugHeader + "Trajectory Recordings - " + loginManager.getUsername()); + return rootView; } /** - * {@inheritDoc} - * Initialises UI elements, including a navigation card to the {@link UploadFragment} and a - * RecyclerView displaying online trajectories. + * {@inheritDoc} Initialises UI elements, including a navigation card to the {@link + * UploadFragment} and a RecyclerView displaying online trajectories. * * @see TrajDownloadViewHolder the View Holder for the list. * @see TrajDownloadListAdapter the list adapter for displaying the recycler view. - * @see com.openpositioning.PositionMe.R.layout#item_trajectorycard_view the elements in the list. + * @see com.openpositioning.PositionMe.R.layout#item_trajectorycard_view the elements in the + * list. */ @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { @@ -101,61 +133,100 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat filesList = view.findViewById(R.id.filesList); // Get clickable card view uploadCard = view.findViewById(R.id.uploadCard); - uploadCard.setOnClickListener(new View.OnClickListener() { - /** - * {@inheritDoc} - * Navigates to {@link UploadFragment}. - */ - @Override - public void onClick(View view) { - NavDirections action = FilesFragmentDirections.actionFilesFragmentToUploadFragment(); - Navigation.findNavController(view).navigate(action); - } - }); + uploadCard.setOnClickListener( + new View.OnClickListener() { + /** {@inheritDoc} Navigates to {@link UploadFragment}. */ + @Override + public void onClick(View view) { + NavDirections action = + FilesFragmentDirections.actionFilesFragmentToUploadFragment(); + Navigation.findNavController(view).navigate(action); + } + }); + + spinnerSortBy = view.findViewById(R.id.spinnerSortBy); + initialiseSpinner(); + // Request list of uploaded trajectories from the server. - serverCommunications.sendInfoRequest(); + serverCommunications.requestPathsFromServer(URL_GET_USER_TRAJECTORIES); + // Force RecyclerView refresh to ensure icon states are correct - new Handler(Looper.getMainLooper()).postDelayed(() -> { - if (filesList.getAdapter() != null) { - filesList.getAdapter().notifyDataSetChanged(); - System.out.println("RecyclerView refreshed after page load."); - } - }, 500); + new Handler(Looper.getMainLooper()) + .postDelayed( + () -> { + if (filesList.getAdapter() != null) { + filesList.getAdapter().notifyDataSetChanged(); + Log.i("FilesFragment", "RecyclerView refreshed after page load."); + } + }, + 500); + } + + private void initialiseSpinner() { + if (spinnerSortBy == null) return; + + ArrayAdapter adapter = + new ArrayAdapter<>( + requireContext(), + android.R.layout.simple_spinner_dropdown_item, + sortMethods); + spinnerSortBy.setAdapter(adapter); + spinnerSortBy.setSelection(0); + + spinnerSortBy.setOnItemSelectedListener( + new AdapterView.OnItemSelectedListener() { + + @Override + public void onItemSelected( + AdapterView adapterView, View view, int position, long l) { + switch (position) { + case 0: + sortMethod = Comparator.reverseOrder(); + break; + case 1: + sortMethod = Comparator.naturalOrder(); + break; + default: + sortMethod = Comparator.reverseOrder(); + break; + } + updateEntryList(); + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + sortMethod = Comparator.reverseOrder(); + } + }); } /** - * {@inheritDoc} - * Called by {@link ServerCommunications} when the response to the HTTP info request is received. + * {@inheritDoc} Called by {@link ServerCommunications} when the response to the HTTP info + * request is received. * - * @param singletonStringList a single string wrapped in an object array containing the http - * response from the server. + * @param objList The response from the server, including a {@link Boolean} value of success and + * the server's response as a string. */ @Override - public void update(Object[] singletonStringList) { - // Cast input as a string - String infoString = (String) singletonStringList[0]; + public void update(Object[] objList) { + Boolean success = (boolean) objList[0]; + String infoString = objList[1].toString(); + // Check if the string is non-null and non-empty before processing - if(infoString != null && !infoString.isEmpty()) { + if (infoString != null && !infoString.isEmpty()) { // Process string - List> entryList = processInfoResponse(infoString); - // Start a handler to be able to modify UI elements - new Handler(Looper.getMainLooper()).post(new Runnable() { - @Override - public void run() { - // Update the RecyclerView with data from the server - updateView(entryList); - } - }); + entryList = processInfoResponse(infoString); + updateEntryList(); } } /** - * Parses the info response string from the HTTP communication. - * Process the data using the Json library and return the matching Java data structure as a - * List of Maps of \. Throws a JSONException if the data is not valid. + * Parses the info response string from the HTTP communication. Process the data using the Json + * library and return the matching Java data structure as a List of Maps of \. + * Throws a JSONException if the data is not valid. * - * @param infoString HTTP info request response as a single string - * @return List of Maps of String to String containing ID, owner ID, and date. + * @param infoString HTTP info request response as a single string + * @return List of Maps of String to String containing ID, owner ID, and date. */ private List> processInfoResponse(String infoString) { // Initialise empty list @@ -167,55 +238,72 @@ private List> processInfoResponse(String infoString) { JSONObject trajectoryEntry = jsonArray.getJSONObject(i); Map entryMap = new HashMap<>(); entryMap.put("owner_id", String.valueOf(trajectoryEntry.get("owner_id"))); - entryMap.put("date_submitted", (String) trajectoryEntry.get("date_submitted")); + entryMap.put("date_submitted", trajectoryEntry.get("date_submitted").toString()); entryMap.put("id", String.valueOf(trajectoryEntry.get("id"))); + // Store the original index + entryMap.put("original_index", String.valueOf(i)); // Add decoded map to list of entries entryList.add(entryMap); } } catch (JSONException e) { - System.err.println("JSON reading failed"); - e.printStackTrace(); + Log.e("FilesFragment", "JSON reading failed: " + e.getMessage()); } // Sort the list by the ID fields of the maps - entryList.sort(Comparator.comparing(m -> Integer.parseInt(m.get("id")), Comparator.nullsLast(Comparator.naturalOrder()))); + entryList.sort( + Comparator.comparing( + m -> Integer.parseInt(m.get("id")), Comparator.nullsLast(sortMethod))); return entryList; } + private void updateEntryList() { + entryList.sort( + Comparator.comparing( + m -> Integer.parseInt(m.get("id")), Comparator.nullsLast(sortMethod))); + // Start a handler to be able to modify UI elements + new Handler(Looper.getMainLooper()) + .post( + new Runnable() { + @Override + public void run() { + // Update the RecyclerView with data from the server + updateView(entryList); + } + }); + } + /** - * Update the RecyclerView in the FilesFragment with new data. - * Must be called from a UI thread. Initialises a new Layout Manager, and passes it to the - * RecyclerView. Initialises a {@link TrajDownloadListAdapter} with the input array and setting - * up a listener so that trajectories are downloaded when clicked, and a pop-up message is - * displayed to notify the user. + * Update the RecyclerView in the FilesFragment with new data. Must be called from a UI thread. + * Initialises a new Layout Manager, and passes it to the RecyclerView. Initialises a {@link + * TrajDownloadListAdapter} with the input array and setting up a listener so that trajectories + * are downloaded when clicked. * * @param entryList List of Maps of String to String containing metadata about the uploaded - * trajectories (ID, owner ID, date). + * trajectories (ID, owner ID, date). */ private void updateView(List> entryList) { // Initialise RecyclerView with Manager and Adapter LinearLayoutManager manager = new LinearLayoutManager(getActivity()); filesList.setLayoutManager(manager); filesList.setHasFixedSize(true); - listAdapter = new TrajDownloadListAdapter(getActivity(), entryList, position -> { - Map selectedItem = entryList.get(position); - String id = selectedItem.get("id"); - String dateSubmitted = selectedItem.get("date_submitted"); - - // Pass ID and date_submitted - serverCommunications.downloadTrajectory(position, id, dateSubmitted); - -// new AlertDialog.Builder(getContext()) -// .setTitle("File downloaded") -// .setMessage("Trajectory downloaded to local storage") -// .setPositiveButton(R.string.ok, null) -// .setNegativeButton(R.string.show_storage, (dialogInterface, i) -> { -// startActivity(new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS)); -// }) -// .setIcon(R.drawable.ic_baseline_download_24) -// .show(); - }); + listAdapter = + new TrajDownloadListAdapter( + getActivity(), + entryList, + position -> { + Map selectedItem = entryList.get(position); + String id = selectedItem.get("id"); + String dateSubmitted = selectedItem.get("date_submitted"); + + int originalIndex = + Integer.parseInt(selectedItem.get("original_index")); + + // Pass ID and date_submitted + serverCommunications.downloadTrajectory( + originalIndex, id, dateSubmitted); + }); filesList.setAdapter(listAdapter); + // Force refresh RecyclerView to ensure downloadRecords changes are detected listAdapter.notifyDataSetChanged(); } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/HomeFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/HomeFragment.java index 8371b04e..80036b5b 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/HomeFragment.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/HomeFragment.java @@ -1,17 +1,23 @@ package com.openpositioning.PositionMe.presentation.fragment; +import static com.openpositioning.PositionMe.utils.UtilConstants.DEBUG_MODE_HEADER; +import static com.openpositioning.PositionMe.utils.UtilConstants.POSITION_UOE_LAT; +import static com.openpositioning.PositionMe.utils.UtilConstants.POSITION_UOE_LON; + import android.Manifest; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.location.LocationManager; +import android.net.Uri; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; @@ -20,42 +26,48 @@ import androidx.navigation.NavDirections; import androidx.navigation.Navigation; import androidx.preference.PreferenceManager; - -import com.google.android.material.button.MaterialButton; +import com.google.android.gms.location.FusedLocationProviderClient; +import com.google.android.gms.location.LocationServices; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; +import com.google.android.material.button.MaterialButton; import com.openpositioning.PositionMe.R; +import com.openpositioning.PositionMe.data.remote.LoginManager; +import com.openpositioning.PositionMe.presentation.activity.LoginActivity; import com.openpositioning.PositionMe.presentation.activity.RecordingActivity; /** - * A simple {@link Fragment} subclass. The home fragment is the start screen of the application. - * The home fragment acts as a hub for all other fragments, with buttons and icons for navigation. - * The default screen when opening the application + * A simple {@link Fragment} subclass. The home fragment is the main screen of the application, + * acting as a hub for all other fragments with buttons and icons for navigation. * * @see RecordingFragment * @see FilesFragment * @see MeasurementsFragment * @see SettingsFragment - * * @author Mate Stodulka */ public class HomeFragment extends Fragment implements OnMapReadyCallback { + private final String TAG = "HomeFragment"; // Interactive UI elements to navigate to other fragments private MaterialButton goToInfo; private Button start; private Button measurements; private Button files; + private Button repoButton; private TextView gnssStatusTextView; // For the map private GoogleMap mMap; private SupportMapFragment mapFragment; + // For getting user information + private LoginManager loginManager; + public HomeFragment() { // Required empty public constructor } @@ -63,74 +75,110 @@ public HomeFragment() { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + loginManager = LoginManager.getInstance(); + + // Do not proceed if user is not logged in + if (!loginManager.checkLoginStatus()) { + Log.w(TAG, "User is not logged in! Sending user to LoginActivity"); + Intent intent = new Intent(requireContext(), LoginActivity.class); + startActivity(intent); + requireActivity().finish(); + } } /** - * {@inheritDoc} - * Ensure the action bar is shown at the top of the screen. Set the title visible to Home. + * {@inheritDoc} Ensure the action bar is shown at the top of the screen. Set the title visible + * to Home. */ @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ((AppCompatActivity) getActivity()).getSupportActionBar().show(); View rootView = inflater.inflate(R.layout.fragment_home, container, false); - getActivity().setTitle("Home"); + + // Make debug mode explicit in the header + String debugHeader; + SharedPreferences settings = + PreferenceManager.getDefaultSharedPreferences(requireContext()); + if (settings.getBoolean("debug_mode", false)) { + debugHeader = DEBUG_MODE_HEADER; + } else { + debugHeader = ""; + } + getActivity().setTitle(debugHeader + "Home - " + loginManager.getUsername()); + return rootView; } - /** - * Initialise UI elements and set onClick actions for the buttons. - */ + /** Initialise UI elements and set onClick actions for the buttons. */ @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // Sensor Info button goToInfo = view.findViewById(R.id.sensorInfoButton); - goToInfo.setOnClickListener(v -> { - NavDirections action = HomeFragmentDirections.actionHomeFragmentToInfoFragment(); - Navigation.findNavController(v).navigate(action); - }); + goToInfo.setOnClickListener( + v -> { + NavDirections action = + HomeFragmentDirections.actionHomeFragmentToInfoFragment(); + Navigation.findNavController(v).navigate(action); + }); // Start/Stop Recording button start = view.findViewById(R.id.startStopButton); - start.setEnabled(!PreferenceManager.getDefaultSharedPreferences(getContext()) - .getBoolean("permanentDeny", false)); - start.setOnClickListener(v -> { - Intent intent = new Intent(requireContext(), RecordingActivity.class); - startActivity(intent); - ((AppCompatActivity) getActivity()).getSupportActionBar().hide(); - }); + start.setEnabled( + !PreferenceManager.getDefaultSharedPreferences(getContext()) + .getBoolean("permanentDeny", false)); + start.setOnClickListener( + v -> { + Intent intent = new Intent(requireContext(), RecordingActivity.class); + startActivity(intent); + ((AppCompatActivity) getActivity()).getSupportActionBar().hide(); + }); // Measurements button measurements = view.findViewById(R.id.measurementButton); - measurements.setOnClickListener(v -> { - NavDirections action = HomeFragmentDirections.actionHomeFragmentToMeasurementsFragment(); - Navigation.findNavController(v).navigate(action); - }); + measurements.setOnClickListener( + v -> { + NavDirections action = + HomeFragmentDirections.actionHomeFragmentToMeasurementsFragment(); + Navigation.findNavController(v).navigate(action); + }); // Files button files = view.findViewById(R.id.filesButton); - files.setOnClickListener(v -> { - NavDirections action = HomeFragmentDirections.actionHomeFragmentToFilesFragment(); - Navigation.findNavController(v).navigate(action); - }); + files.setOnClickListener( + v -> { + NavDirections action = + HomeFragmentDirections.actionHomeFragmentToFilesFragment(); + Navigation.findNavController(v).navigate(action); + }); + + // Repository link button + repoButton = view.findViewById(R.id.indoorButton); + repoButton.setOnClickListener( + v -> { + Intent browserIntent = + new Intent( + Intent.ACTION_VIEW, + Uri.parse(requireContext().getString(R.string.url_repo))); + startActivity(browserIntent); + }); // TextView to display GNSS disabled message gnssStatusTextView = view.findViewById(R.id.gnssStatusTextView); // Locate the MapFragment nested in this fragment - mapFragment = (SupportMapFragment) - getChildFragmentManager().findFragmentById(R.id.mapFragmentContainer); + mapFragment = + (SupportMapFragment) + getChildFragmentManager().findFragmentById(R.id.mapFragmentContainer); if (mapFragment != null) { // Asynchronously initialize the map mapFragment.getMapAsync(this); } } - /** - * Callback triggered when the Google Map is ready to be used. - */ + /** Callback triggered when the Google Map is ready to be used. */ @Override public void onMapReady(@NonNull GoogleMap googleMap) { mMap = googleMap; @@ -143,30 +191,34 @@ public void onResume() { checkAndUpdatePermissions(); } - /** - * Checks if GNSS/Location is enabled on the device. - */ + /** Log users out when the fragment is destroyed */ + @Override + public void onDestroy() { + Log.d(TAG, "Logging out onDestroy()"); + loginManager.endLoginSession(); + super.onDestroy(); + } + + /** Checks if GNSS/Location is enabled on the device. */ private boolean isGnssEnabled() { LocationManager locationManager = (LocationManager) requireContext().getSystemService(Context.LOCATION_SERVICE); // Checks both GPS and network provider. Adjust as needed. boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); - boolean networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); + boolean networkEnabled = + locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); return (gpsEnabled || networkEnabled); } - /** - * Move the map to the University of Edinburgh and display a message. - */ + /** Move the map to the University of Edinburgh and display a message. */ private void showEdinburghAndMessage(String message) { gnssStatusTextView.setText(message); gnssStatusTextView.setVisibility(View.VISIBLE); - LatLng edinburghLatLng = new LatLng(55.944425, -3.188396); + LatLng edinburghLatLng = new LatLng(POSITION_UOE_LAT, POSITION_UOE_LON); mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(edinburghLatLng, 15f)); - mMap.addMarker(new MarkerOptions() - .position(edinburghLatLng) - .title("University of Edinburgh")); + mMap.addMarker( + new MarkerOptions().position(edinburghLatLng).title("University of Edinburgh")); } private void checkAndUpdatePermissions() { @@ -182,30 +234,37 @@ private void checkAndUpdatePermissions() { gnssStatusTextView.setVisibility(View.GONE); // Check runtime permissions for location - if (ActivityCompat.checkSelfPermission( - requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) - == PackageManager.PERMISSION_GRANTED || + boolean permissionGrantedLocationFine = + ActivityCompat.checkSelfPermission( + requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED; + + boolean permissionGrantedLocationCoarse = ActivityCompat.checkSelfPermission( - requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) - == PackageManager.PERMISSION_GRANTED) { + requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) + == PackageManager.PERMISSION_GRANTED; + if (permissionGrantedLocationFine || permissionGrantedLocationCoarse) { // Enable the MyLocation layer of Google Map mMap.setMyLocationEnabled(true); - // Optionally move the camera to last known or default location: - // (You could retrieve it from FusedLocationProvider or similar). - // Here, just leaving it on default. - // If you want to center on the user as soon as it loads, do something like: - /* + // Zoom to the user upon map load FusedLocationProviderClient fusedLocationClient = - LocationServices.getFusedLocationProviderClient(requireContext()); - fusedLocationClient.getLastLocation().addOnSuccessListener(location -> { - if (location != null) { - LatLng currentLatLng = new LatLng(location.getLatitude(), location.getLongitude()); - mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 15f)); - } - }); - */ + LocationServices.getFusedLocationProviderClient(requireContext()); + fusedLocationClient + .getLastLocation() + .addOnSuccessListener( + location -> { + if (location != null) { + LatLng currentLatLng = + new LatLng( + location.getLatitude(), + location.getLongitude()); + mMap.moveCamera( + CameraUpdateFactory.newLatLngZoom( + currentLatLng, 15f)); + } + }); } else { // If no permission, simply show a default location or prompt for permissions showEdinburghAndMessage("Permission not granted. Please enable in settings."); diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/IndoorMapFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/IndoorMapFragment.java deleted file mode 100644 index 48c40474..00000000 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/IndoorMapFragment.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.openpositioning.PositionMe.presentation.fragment; - -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.model.BitmapDescriptorFactory; -import com.google.android.gms.maps.model.BitmapDescriptor; - -import com.google.android.gms.maps.model.GroundOverlay; -import com.google.android.gms.maps.model.GroundOverlayOptions; -import com.google.android.gms.maps.model.LatLngBounds; - -public class IndoorMapFragment { - private GoogleMap mMap; - private GroundOverlay[] groundOverlays; // GroundOverlay used to store each layer - private int currentFloor = 0; // Floor by default - - public IndoorMapFragment(GoogleMap map, int floorNumber) { - this.mMap = map; // Pass in Google Maps - this.groundOverlays = new GroundOverlay[floorNumber]; // Set the number of floors - } - - // Used to add floors - public void addFloor(int floorIndex, int drawableResId, LatLngBounds bounds) { - BitmapDescriptor image = BitmapDescriptorFactory.fromResource(drawableResId); - GroundOverlayOptions groundOverlayOptions = new GroundOverlayOptions() - .image(image) - .positionFromBounds(bounds) - .visible(floorIndex == currentFloor) - .transparency(0.2f); - - groundOverlays[floorIndex] = mMap.addGroundOverlay(groundOverlayOptions); - } - - // Switch floors and make sure only one floor is displayed - public void switchFloor(int floorIndex) { - if (floorIndex < 0 || floorIndex >= groundOverlays.length) { - return; // Prevent index out of bounds - } - // Hide all floors - for (GroundOverlay overlay : groundOverlays) { - if (overlay != null) { - overlay.setVisible(false); - } - } - // Show selected floor - GroundOverlay selectedOverlay = groundOverlays[floorIndex]; - if (selectedOverlay != null) { - selectedOverlay.setVisible(true); - } - currentFloor = floorIndex; - } - - // Hide all floors - public void hideMap() { - //Hide all floors - for (GroundOverlay overlay : groundOverlays) { - if (overlay != null) { - overlay.setVisible(false); - } - } - } -} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/InfoFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/InfoFragment.java index f0cc78de..32865463 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/InfoFragment.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/InfoFragment.java @@ -4,19 +4,16 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; - import com.openpositioning.PositionMe.R; +import com.openpositioning.PositionMe.presentation.viewitems.SensorInfoListAdapter; import com.openpositioning.PositionMe.presentation.viewitems.SensorInfoViewHolder; import com.openpositioning.PositionMe.sensors.SensorFusion; import com.openpositioning.PositionMe.sensors.SensorInfo; -import com.openpositioning.PositionMe.presentation.viewitems.SensorInfoListAdapter; - import java.util.List; /** @@ -26,7 +23,6 @@ * @see HomeFragment the previous fragment in the nav graph. * @see com.openpositioning.PositionMe.sensors.SensorFusion the class containing all sensors. * @see SensorInfo the class used for each sensor instance's metadata - * * @author Mate Stodulka */ public class InfoFragment extends Fragment { @@ -36,28 +32,21 @@ public class InfoFragment extends Fragment { // UI element recyclerview to display sensor information private RecyclerView sensorInfoView; - /** - * Public default constructor, empty. - */ + /** Public default constructor, empty. */ public InfoFragment() { // Required empty public constructor } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } - /** - * {@inheritDoc} - * Set title in the action bar to Sensor Information. - */ + /** {@inheritDoc} Set title in the action bar to Sensor Information. */ @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View rootView = inflater.inflate(R.layout.fragment_info, container, false); getActivity().setTitle("Sensor Information"); @@ -65,10 +54,9 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, } /** - * {@inheritDoc} - * Initialise the RecyclerView by creating and registering a Layout Manager, getting the - * {@link SensorFusion} instance and obtaining the Sensor Info data, and passing it to the - * {@link SensorInfoListAdapter}. + * {@inheritDoc} Initialise the RecyclerView by creating and registering a Layout Manager, + * getting the {@link SensorFusion} instance and obtaining the Sensor Info data, and passing it + * to the {@link SensorInfoListAdapter}. * * @see SensorInfoListAdapter List adapter for the Sensor Info Recycler View. * @see SensorInfoViewHolder View holder for the Sensor Infor RV. @@ -87,4 +75,4 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat // Set adapter for the recycler view. sensorInfoView.setAdapter(new SensorInfoListAdapter(getActivity(), sensorInfoList)); } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/LoginFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/LoginFragment.java new file mode 100644 index 00000000..617181b2 --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/LoginFragment.java @@ -0,0 +1,239 @@ +package com.openpositioning.PositionMe.presentation.fragment; + +import static com.openpositioning.PositionMe.utils.UtilConstants.CREDENTIALS_KEY_EMAIL; +import static com.openpositioning.PositionMe.utils.UtilConstants.CREDENTIALS_KEY_PASSWORD; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.navigation.NavDirections; +import androidx.navigation.Navigation; +import com.openpositioning.PositionMe.R; +import com.openpositioning.PositionMe.data.remote.LoginManager; +import com.openpositioning.PositionMe.data.remote.ServerCommunications; +import com.openpositioning.PositionMe.presentation.activity.MainActivity; +import com.openpositioning.PositionMe.sensors.Observer; +import java.util.HashMap; +import java.util.Map; +import org.json.JSONException; +import org.json.JSONObject; + +/** + * An extension of {@link Fragment} to manage signing in to OpenPosition and retrieving the user's + * API key. Users can enter their credentials and (optionally) save them to their device. + * + *

If the user doesn't have an account, they can access the {@link RegisterFragment} to sign up + * to OpenPosition's API. + * + * @see RegisterFragment + * @see ServerCommunications + * @see LoginManager + */ +public class LoginFragment extends Fragment implements Observer { + private final String TAG = "LoginFragment"; + + private Button loginButton; + private TextView textRegisterHere; + private EditText emailEditText; + private EditText passwordEditText; + private CheckBox checkboxSavePassword; + private LoginManager loginManager; + private ServerCommunications serverCommunications; + + public LoginFragment() { + // Required empty public constructor + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_login, container, false); + } + + /** + * {@inheritDoc} + * + *

Initialise the UI elements, and the {@link LoginManager} for handling credentials + */ + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + loginManager = LoginManager.getInstance(); + loginManager.initialise(this.getContext()); + serverCommunications = new ServerCommunications(this.getContext()); + serverCommunications.registerObserver(this); + + loginButton = view.findViewById(R.id.buttonLogin); + checkboxSavePassword = view.findViewById(R.id.checkBoxSavePassword); + + textRegisterHere = view.findViewById(R.id.textLoginFragmentToRegister); + emailEditText = view.findViewById(R.id.editTextLoginEmail); + passwordEditText = view.findViewById(R.id.editTextLoginPassword); + + // Populate login screen with saved credentials, if present + Map savedCredentials = loginManager.getSavedLoginDetails(); + if (savedCredentials != null) { + String email = savedCredentials.get(CREDENTIALS_KEY_EMAIL); + String password = savedCredentials.get(CREDENTIALS_KEY_PASSWORD); + emailEditText.setText(email); + passwordEditText.setText(password); + checkboxSavePassword.setChecked(true); + Log.i(TAG, "Credentials loaded from device"); + } + + // Move to the registration screen + textRegisterHere.setOnClickListener( + v -> { + NavDirections action = + LoginFragmentDirections.actionLoginFragmentToRegisterFragment(); + Navigation.findNavController(v).navigate(action); + }); + + loginButton.setOnClickListener(v -> attemptLogIn()); + } + + /** + * Retrieve the user's input from the UI, and send a login request to the OpenPosition API. + * + *

If the user wishes to save their login details, the {@link LoginManager} will save these + * on their device. + */ + private void attemptLogIn() { + String email = emailEditText.getText().toString(); + String password = passwordEditText.getText().toString(); + + if (email.isEmpty() || password.isEmpty()) { + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + this.getContext(), + "Please fill all login fields and try again.", + Toast.LENGTH_SHORT) + .show(); + }); + return; + } + + if (checkboxSavePassword.isChecked()) { + loginManager.saveLoginToDevice(email, password); + } + + // Disable UI to prevent multiple login attempts + enableUIElements(false); + + serverCommunications.logInUser(email, password); + } + + /** + * Saves the user's username and API key in the {@link LoginManager} for future reference, and + * hands off to {@link MainActivity}. + */ + private void finaliseLogin(String username, String key) { + // Save for future reference + loginManager.startLoginSession(username, key); + + new Handler(Looper.getMainLooper()) + .post( + () -> + Toast.makeText( + this.getContext(), + "Login Successful - Welcome " + username + "!", + Toast.LENGTH_SHORT) + .show()); + + Intent intent = new Intent(requireContext(), MainActivity.class); + startActivity(intent); + requireActivity().finish(); + } + + /** + * Enable or disable all login UI elements to prevent users from modifying data while the server + * and/or app is processing it + * + *

This must be called from the main thread. + * + * @param state True to enable UI elements; False to disable + */ + private void enableUIElements(boolean state) { + loginButton.setEnabled(state); + checkboxSavePassword.setEnabled(state); + emailEditText.setEnabled(state); + passwordEditText.setEnabled(state); + textRegisterHere.setClickable(state); + } + + /** + * {@inheritDoc} + * + *

Calls for the user's username and API key to be extracted from the server's response + * before completing the log in process. + */ + @Override + public void update(Object[] objList) { + boolean success = (boolean) objList[0]; + String infoString = objList[1].toString(); + + // Re-enable login button on failure + if (!success) { + new Handler(Looper.getMainLooper()).post(() -> enableUIElements(true)); + return; + } + + try { + Map userData = extractDataFromResponse(infoString); + + String username = userData.get("username"); + String key = userData.get("key"); + Log.i(TAG, "username: " + username); + Log.i(TAG, "key: " + key); + + finaliseLogin(username, key); + } catch (Exception e) { + String message = "Bad response from server. Login halted"; + new Handler(Looper.getMainLooper()) + .post( + () -> + Toast.makeText(this.getContext(), message, Toast.LENGTH_SHORT) + .show()); + Log.w(TAG, message); + } + } + + /** + * Parses the server's response for the user's username and API key. + * + * @return The user's username and API key in a Map. + * @throws JSONException If the response parsing fails. + */ + private Map extractDataFromResponse(String response) throws JSONException { + Map userData = new HashMap<>(); + try { + JSONObject jsonObject = new JSONObject(response); + userData.put("username", String.valueOf(jsonObject.get("username"))); + userData.put("key", String.valueOf(jsonObject.get("api_key"))); + return userData; + } catch (JSONException e) { + Log.w(TAG, "Error parsing server response: " + e.getCause()); + throw e; + } + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/MeasurementsFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/MeasurementsFragment.java index 20c43987..dd9539d2 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/MeasurementsFragment.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/MeasurementsFragment.java @@ -5,8 +5,8 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.cardview.widget.CardView; @@ -14,24 +14,23 @@ import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; - import com.openpositioning.PositionMe.R; +import com.openpositioning.PositionMe.presentation.viewitems.BleListAdapter; +import com.openpositioning.PositionMe.presentation.viewitems.WifiListAdapter; +import com.openpositioning.PositionMe.sensors.BleDevice; import com.openpositioning.PositionMe.sensors.SensorFusion; import com.openpositioning.PositionMe.sensors.SensorTypes; import com.openpositioning.PositionMe.sensors.Wifi; -import com.openpositioning.PositionMe.presentation.viewitems.WifiListAdapter; - import java.util.List; import java.util.Map; /** * A simple {@link Fragment} subclass. The measurement fragment displays the set of current sensor - * readings. The values are refreshed periodically, but slower than their internal refresh rate. - * The refresh time is set by a static constant. + * readings. The values are refreshed periodically, but slower than their internal refresh rate. The + * refresh time is set by a static constant. * * @see HomeFragment the previous fragment in the nav graph. * @see SensorFusion the source of all sensor readings. - * * @author Mate Stodulka */ public class MeasurementsFragment extends Fragment { @@ -47,22 +46,24 @@ public class MeasurementsFragment extends Fragment { // UI elements private ConstraintLayout sensorMeasurementList; private RecyclerView wifiListView; + private RecyclerView bleListView; // List of string resource IDs private int[] prefaces; private int[] gnssPrefaces; + private WifiListAdapter wifiAdapter; + private BleListAdapter bleAdapter; + private ImageView wifiExpandIcon; + private ImageView bleExpandIcon; - /** - * Public default constructor, empty. - */ + /** Public default constructor, empty. */ public MeasurementsFragment() { // Required empty public constructor } /** - * {@inheritDoc} - * Obtains the singleton Sensor Fusion instance and initialises the string prefaces for display. - * Creates a new handler to periodically refresh data. + * {@inheritDoc} Obtains the singleton Sensor Fusion instance and initialises the string + * prefaces for display. Creates a new handler to periodically refresh data. * * @see SensorFusion handles all sensor data. */ @@ -72,21 +73,20 @@ public void onCreate(Bundle savedInstanceState) { // Get sensor fusion instance sensorFusion = SensorFusion.getInstance(); // Initialise string prefaces for display - prefaces = new int[]{R.string.x, R.string.y, R.string.z}; - gnssPrefaces = new int[]{R.string.lati, R.string.longi}; + prefaces = new int[] {R.string.x, R.string.y, R.string.z}; + gnssPrefaces = new int[] {R.string.lati, R.string.longi}; // Create new handler to refresh the UI. this.refreshDataHandler = new Handler(); } /** - * {@inheritDoc} - * Sets title in the action bar to Sensor Measurements. - * Posts the {@link MeasurementsFragment#refreshTableTask} using the Handler. + * {@inheritDoc} Sets title in the action bar to Sensor Measurements. Posts the {@link + * MeasurementsFragment#refreshTableTask} using the Handler. */ @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View rootView = inflater.inflate(R.layout.fragment_measurements, container, false); getActivity().setTitle("Sensor Measurements"); @@ -94,20 +94,14 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, return rootView; } - /** - * {@inheritDoc} - * Pauses the data refreshing when the fragment is not in focus. - */ + /** {@inheritDoc} Pauses the data refreshing when the fragment is not in focus. */ @Override public void onPause() { refreshDataHandler.removeCallbacks(refreshTableTask); super.onPause(); } - /** - * {@inheritDoc} - * Restarts the data refresh when the fragment returns to focus. - */ + /** {@inheritDoc} Restarts the data refresh when the fragment returns to focus. */ @Override public void onResume() { refreshDataHandler.postDelayed(refreshTableTask, REFRESH_TIME); @@ -115,63 +109,125 @@ public void onResume() { } /** - * {@inheritDoc} - * Obtains the constraint layout holding the sensor measurement values. Initialises the Recycler - * View for holding WiFi data and registers its Layout Manager. + * {@inheritDoc} Obtains the constraint layout holding the sensor measurement values. + * Initialises the Recycler View for holding WiFi data and registers its Layout Manager. */ @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - sensorMeasurementList = (ConstraintLayout) getView().findViewById(R.id.sensorMeasurementList); + sensorMeasurementList = + (ConstraintLayout) getView().findViewById(R.id.sensorMeasurementList); wifiListView = (RecyclerView) getView().findViewById(R.id.wifiList); wifiListView.setLayoutManager(new LinearLayoutManager(getActivity())); + wifiAdapter = new WifiListAdapter(getActivity(), new java.util.ArrayList<>()); + wifiListView.setAdapter(wifiAdapter); + + bleListView = (RecyclerView) getView().findViewById(R.id.bleList); + bleListView.setLayoutManager(new LinearLayoutManager(getActivity())); + bleAdapter = new BleListAdapter(getActivity(), new java.util.ArrayList<>()); + bleListView.setAdapter(bleAdapter); + + CardView wifiTitleCard = getView().findViewById(R.id.dividerLine); + TextView wifiTitleText = getView().findViewById(R.id.wifiTitle); + wifiExpandIcon = getView().findViewById(R.id.wifiExpandIcon); + + CardView bleTitleCard = getView().findViewById(R.id.bleTitle); + TextView bleTitleText = getView().findViewById(R.id.bleTitleText); + bleExpandIcon = getView().findViewById(R.id.bleExpandIcon); + + // Initially hide both lists + wifiListView.setVisibility(View.GONE); + bleListView.setVisibility(View.GONE); + + wifiTitleCard.setOnClickListener( + v -> { + if (wifiListView.getVisibility() == View.VISIBLE) { + wifiListView.setVisibility(View.GONE); + wifiExpandIcon.setRotation(0); + } else { + wifiListView.setVisibility(View.VISIBLE); + bleListView.setVisibility(View.GONE); + wifiExpandIcon.setRotation(180); + bleExpandIcon.setRotation(0); + } + }); + + bleTitleCard.setOnClickListener( + v -> { + if (bleListView.getVisibility() == View.VISIBLE) { + bleListView.setVisibility(View.GONE); + bleExpandIcon.setRotation(0); + } else { + bleListView.setVisibility(View.VISIBLE); + wifiListView.setVisibility(View.GONE); + bleExpandIcon.setRotation(180); + wifiExpandIcon.setRotation(0); + } + }); + + wifiTitleText.setOnClickListener(v -> wifiTitleCard.performClick()); + bleTitleText.setOnClickListener(v -> bleTitleCard.performClick()); } /** - * Runnable task containing functionality to update the UI with the relevant sensor data. - * Must be run on the UI thread via a Handler. Obtains movement sensor values and the current - * WiFi networks from the {@link SensorFusion} instance and updates the UI with the new data - * and the string wrappers provided. + * Runnable task containing functionality to update the UI with the relevant sensor data. Must + * be run on the UI thread via a Handler. Obtains movement sensor values and the current WiFi + * networks from the {@link SensorFusion} instance and updates the UI with the new data and the + * string wrappers provided. * * @see SensorFusion class handling all sensors and data processing. * @see Wifi class holding network data. */ - private final Runnable refreshTableTask = new Runnable() { - @Override - public void run() { - // Get all the values from SensorFusion - Map sensorValueMap = sensorFusion.getSensorValueMap(); - // Loop through UI elements and update the values - for(SensorTypes st : SensorTypes.values()) { - CardView cardView = (CardView) sensorMeasurementList.getChildAt(st.ordinal()); - ConstraintLayout currentRow = (ConstraintLayout) cardView.getChildAt(0); - float[] values = sensorValueMap.get(st); - for (int i = 0; i < values.length; i++) { - String valueString; - // Set string wrapper based on data type. - if(values.length == 1) { - valueString = getString(R.string.level, String.format("%.2f", values[0])); + private final Runnable refreshTableTask = + new Runnable() { + @Override + public void run() { + // Get all the values from SensorFusion + Map sensorValueMap = sensorFusion.getSensorValueMap(); + // Loop through UI elements and update the values + for (SensorTypes st : SensorTypes.values()) { + CardView cardView = + (CardView) sensorMeasurementList.getChildAt(st.ordinal()); + ConstraintLayout currentRow = (ConstraintLayout) cardView.getChildAt(0); + float[] values = sensorValueMap.get(st); + for (int i = 0; i < values.length; i++) { + String valueString; + // Set string wrapper based on data type. + if (values.length == 1) { + valueString = + getString(R.string.level, String.format("%.2f", values[0])); + } else if (values.length == 2) { + if (st == SensorTypes.GNSSLATLONG) + valueString = + getString( + gnssPrefaces[i], + String.format("%.2f", values[i])); + else + valueString = + getString( + prefaces[i], String.format("%.2f", values[i])); + } else { + valueString = + getString(prefaces[i], String.format("%.2f", values[i])); + } + ((TextView) currentRow.getChildAt(i + 1)).setText(valueString); + } } - else if(values.length == 2){ - if(st == SensorTypes.GNSSLATLONG) - valueString = getString(gnssPrefaces[i], String.format("%.2f", values[i])); - else - valueString = getString(prefaces[i], String.format("%.2f", values[i])); + // Get all WiFi values - convert to list of strings + List wifiObjects = sensorFusion.getWifiList(); + // If there are WiFi networks visible, update the recycler view with the data. + if (wifiObjects != null) { + wifiAdapter.updateData(wifiObjects); } - else{ - valueString = getString(prefaces[i], String.format("%.2f", values[i])); + // Get all Bluetooth values - convert to list of strings + List bleObjects = sensorFusion.getBleList(); + // If there are Bluetooth devices visible, update the recycler view with the + // data. + if (bleObjects != null && !bleObjects.isEmpty()) { + bleAdapter.updateData(bleObjects); } - ((TextView) currentRow.getChildAt(i + 1)).setText(valueString); + // Restart the data updater task in REFRESH_TIME milliseconds. + refreshDataHandler.postDelayed(refreshTableTask, REFRESH_TIME); } - } - // Get all WiFi values - convert to list of strings - List wifiObjects = sensorFusion.getWifiList(); - // If there are WiFi networks visible, update the recycler view with the data. - if(wifiObjects != null) { - wifiListView.setAdapter(new WifiListAdapter(getActivity(), wifiObjects)); - } - // Restart the data updater task in REFRESH_TIME milliseconds. - refreshDataHandler.postDelayed(refreshTableTask, REFRESH_TIME); - } - }; -} \ No newline at end of file + }; +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/RecordingFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/RecordingFragment.java index 6362a971..ad0613e9 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/RecordingFragment.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/RecordingFragment.java @@ -7,10 +7,10 @@ import android.os.Bundle; import android.os.CountDownTimer; import android.os.Handler; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; - import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.LinearInterpolator; @@ -18,51 +18,47 @@ import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; -import com.google.android.material.button.MaterialButton; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.preference.PreferenceManager; - +import com.google.android.gms.maps.model.LatLng; +import com.google.android.material.button.MaterialButton; +import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.openpositioning.PositionMe.R; import com.openpositioning.PositionMe.presentation.activity.RecordingActivity; import com.openpositioning.PositionMe.sensors.SensorFusion; import com.openpositioning.PositionMe.sensors.SensorTypes; import com.openpositioning.PositionMe.utils.UtilFunctions; -import com.google.android.gms.maps.model.LatLng; - /** * Fragment responsible for managing the recording process of trajectory data. - *

- * The RecordingFragment serves as the interface for users to initiate, monitor, and - * complete trajectory recording. It integrates sensor fusion data to track user movement - * and updates a map view in real time. Additionally, it provides UI controls to cancel, - * stop, and monitor recording progress. - *

- * Features: - * - Starts and stops trajectory recording. - * - Displays real-time sensor data such as elevation and distance traveled. - * - Provides UI controls to cancel or complete recording. - * - Uses {@link TrajectoryMapFragment} to visualize recorded paths. - * - Manages GNSS tracking and error display. + * + *

The RecordingFragment serves as the interface for users to initiate, monitor, and complete + * trajectory recording. It integrates sensor fusion data to track user movement and updates a map + * view in real time. Additionally, it provides UI controls to cancel, stop, and monitor recording + * progress. + * + *

Features: - Starts and stops trajectory recording. - Displays real-time sensor data such as + * elevation and distance traveled. - Provides UI controls to cancel or complete recording. - Uses + * {@link TrajectoryMapFragment} to visualize recorded paths. - Manages GNSS tracking and error + * display. * * @see TrajectoryMapFragment The map fragment displaying the recorded trajectory. * @see RecordingActivity The activity managing the recording workflow. * @see SensorFusion Handles sensor data collection. * @see SensorTypes Enumeration of available sensor types. - * * @author Shu Gu */ - public class RecordingFragment extends Fragment { // UI elements private MaterialButton completeButton, cancelButton; + private FloatingActionButton timedMarker; private ImageView recIcon; private ProgressBar timeRemaining; private TextView elevation, distanceTravelled, gnssError; + private TextView textCampaignName, textFloorNumberTitle, textFloorNumber; // App settings private SharedPreferences settings; @@ -79,15 +75,17 @@ public class RecordingFragment extends Fragment { // References to the child map fragment private TrajectoryMapFragment trajectoryMapFragment; + private int timed_marker_counter = 1; - private final Runnable refreshDataTask = new Runnable() { - @Override - public void run() { - updateUIandPosition(); - // Loop again - refreshDataHandler.postDelayed(refreshDataTask, 200); - } - }; + private final Runnable refreshDataTask = + new Runnable() { + @Override + public void run() { + updateUIandPosition(); + // Loop again + refreshDataHandler.postDelayed(refreshDataTask, 200); + } + }; public RecordingFragment() { // Required empty public constructor @@ -99,27 +97,34 @@ public void onCreate(Bundle savedInstanceState) { this.sensorFusion = SensorFusion.getInstance(); Context context = requireActivity(); this.settings = PreferenceManager.getDefaultSharedPreferences(context); + sensorFusion.updateConstants(); this.refreshDataHandler = new Handler(); } @Nullable @Override - public View onCreateView(@NonNull LayoutInflater inflater, - @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + public View onCreateView( + @NonNull LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { // Inflate only the "recording" UI parts (no map) return inflater.inflate(R.layout.fragment_recording, container, false); } @Override - public void onViewCreated(@NonNull View view, - @Nullable Bundle savedInstanceState) { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // Child Fragment: the container in fragment_recording.xml // where TrajectoryMapFragment is placed - trajectoryMapFragment = (TrajectoryMapFragment) - getChildFragmentManager().findFragmentById(R.id.trajectoryMapFragmentContainer); + trajectoryMapFragment = + (TrajectoryMapFragment) + getChildFragmentManager() + .findFragmentById(R.id.trajectoryMapFragmentContainer); + + textCampaignName = view.findViewById(R.id.textViewCampaignField); + textFloorNumber = view.findViewById(R.id.textFloorNumber); + textFloorNumberTitle = view.findViewById(R.id.textViewFloorTitle); // If not present, create it if (trajectoryMapFragment == null) { @@ -137,49 +142,78 @@ public void onViewCreated(@NonNull View view, completeButton = view.findViewById(R.id.stopButton); cancelButton = view.findViewById(R.id.cancelButton); + timedMarker = view.findViewById(R.id.dropMarkerButton); recIcon = view.findViewById(R.id.redDot); timeRemaining = view.findViewById(R.id.timeRemainingBar); // Hide or initialize default values gnssError.setVisibility(View.GONE); + textFloorNumberTitle.setVisibility(View.GONE); + textFloorNumber.setVisibility(View.GONE); elevation.setText(getString(R.string.elevation, "0")); distanceTravelled.setText(getString(R.string.meter, "0")); // Buttons - completeButton.setOnClickListener(v -> { - // Stop recording & go to correction - if (autoStop != null) autoStop.cancel(); - sensorFusion.stopRecording(); - // Show Correction screen - ((RecordingActivity) requireActivity()).showCorrectionScreen(); - }); - + completeButton.setOnClickListener( + v -> { + // Stop recording & go to correction + if (autoStop != null) autoStop.cancel(); + sensorFusion.stopRecording(); + ((RecordingActivity) requireActivity()).showCorrectionScreen(); + }); // Cancel button with confirmation dialog - cancelButton.setOnClickListener(v -> { - AlertDialog dialog = new AlertDialog.Builder(requireActivity()) - .setTitle("Confirm Cancel") - .setMessage("Are you sure you want to cancel the recording? Your progress will be lost permanently!") - .setNegativeButton("Yes", (dialogInterface, which) -> { - // User confirmed cancellation - sensorFusion.stopRecording(); - if (autoStop != null) autoStop.cancel(); - requireActivity().onBackPressed(); - }) - .setPositiveButton("No", (dialogInterface, which) -> { - // User cancelled the dialog. Do nothing. - dialogInterface.dismiss(); - }) - .create(); // Create the dialog but do not show it yet - - // Show the dialog and change the button color - dialog.setOnShowListener(dialogInterface -> { - Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE); - negativeButton.setTextColor(Color.RED); // Set "Yes" button color to red - }); - - dialog.show(); // Finally, show the dialog - }); + cancelButton.setOnClickListener( + v -> { + AlertDialog dialog = + new AlertDialog.Builder(requireActivity()) + .setTitle("Confirm Cancel") + .setMessage( + "Are you sure you want to cancel the recording? " + + "Your progress will be lost permanently!") + .setNegativeButton( + "Yes", + (dialogInterface, which) -> { + // User confirmed cancellation + sensorFusion.stopRecording(); + if (autoStop != null) autoStop.cancel(); + requireActivity().onBackPressed(); + }) + .setPositiveButton( + "No", + (dialogInterface, which) -> { + // User cancelled the dialog. Do nothing. + dialogInterface.dismiss(); + }) + .create(); // Create the dialog but do not show it yet + + // Show the dialog and change the button color + dialog.setOnShowListener( + dialogInterface -> { + Button negativeButton = + dialog.getButton(AlertDialog.BUTTON_NEGATIVE); + negativeButton.setTextColor( + Color.RED); // Set "Yes" button color to red + }); + + dialog.show(); // Finally, show the dialog + }); + + timedMarker.setOnClickListener( + v -> { + if (trajectoryMapFragment == null) return; + LatLng marker_location = trajectoryMapFragment.getCurrentLocation(); + if (marker_location == null) return; + long tMs = sensorFusion.getRecordingElapsedMs(); + String timeLabel = + android.text.format.DateFormat.format("HH:mm:ss", tMs).toString(); + trajectoryMapFragment.addTimeMarker( + marker_location, timeLabel, timed_marker_counter); + double GNNSAltitude = sensorFusion.getGNSSAltitude(); + sensorFusion.addTestPoint( + marker_location.latitude, marker_location.longitude, GNNSAltitude); + timed_marker_counter++; + }); // The blinking effect for recIcon blinkingRecordingIcon(); @@ -192,35 +226,38 @@ public void onViewCreated(@NonNull View view, timeRemaining.setProgress(0); timeRemaining.setScaleY(3f); - autoStop = new CountDownTimer(limit, 1000) { - @Override - public void onTick(long millisUntilFinished) { - timeRemaining.incrementProgressBy(1); - updateUIandPosition(); - } - - @Override - public void onFinish() { - sensorFusion.stopRecording(); - ((RecordingActivity) requireActivity()).showCorrectionScreen(); - } - }.start(); + autoStop = + new CountDownTimer(limit, 1000) { + @Override + public void onTick(long millisUntilFinished) { + timeRemaining.incrementProgressBy(1); + updateUIandPosition(); + } + + @Override + public void onFinish() { + sensorFusion.stopRecording(); + ((RecordingActivity) requireActivity()).showCorrectionScreen(); + } + }.start(); + Log.i("RecordingFragment", "Timer started for " + (int) (limit / 1000) + " minutes"); } else { // No set time limit, just keep refreshing refreshDataHandler.post(refreshDataTask); } } - /** - * Update the UI with sensor data and pass map updates to TrajectoryMapFragment. - */ + /** Update the UI with sensor data and pass map updates to TrajectoryMapFragment. */ private void updateUIandPosition() { float[] pdrValues = sensorFusion.getSensorValueMap().get(SensorTypes.PDR); if (pdrValues == null) return; // Distance - distance += Math.sqrt(Math.pow(pdrValues[0] - previousPosX, 2) - + Math.pow(pdrValues[1] - previousPosY, 2)); + distance += + (float) + Math.sqrt( + Math.pow(pdrValues[0] - previousPosX, 2) + + Math.pow(pdrValues[1] - previousPosY, 2)); distanceTravelled.setText(getString(R.string.meter, String.format("%.2f", distance))); // Elevation @@ -234,15 +271,17 @@ private void updateUIandPosition() { float[] latLngArray = sensorFusion.getGNSSLatitude(true); if (latLngArray != null) { LatLng oldLocation = trajectoryMapFragment.getCurrentLocation(); // or store locally - LatLng newLocation = UtilFunctions.calculateNewPos( - oldLocation == null ? new LatLng(latLngArray[0], latLngArray[1]) : oldLocation, - new float[]{ pdrValues[0] - previousPosX, pdrValues[1] - previousPosY } - ); + LatLng newLocation = + UtilFunctions.calculateNewPos( + oldLocation == null + ? new LatLng(latLngArray[0], latLngArray[1]) + : oldLocation, + new float[] {pdrValues[0] - previousPosX, pdrValues[1] - previousPosY}); // Pass the location + orientation to the map if (trajectoryMapFragment != null) { - trajectoryMapFragment.updateUserLocation(newLocation, - (float) Math.toDegrees(sensorFusion.passOrientation())); + trajectoryMapFragment.updatePDRLocation( + newLocation, (float) Math.toDegrees(sensorFusion.getOrientation())); } } @@ -254,25 +293,51 @@ private void updateUIandPosition() { LatLng gnssLocation = new LatLng(gnss[0], gnss[1]); LatLng currentLoc = trajectoryMapFragment.getCurrentLocation(); if (currentLoc != null) { - double errorDist = UtilFunctions.distanceBetweenPoints(currentLoc, gnssLocation); + double errorDist = + UtilFunctions.distanceBetweenPoints(currentLoc, gnssLocation); gnssError.setVisibility(View.VISIBLE); - gnssError.setText(String.format(getString(R.string.gnss_error) + "%.2fm", errorDist)); + gnssError.setText( + String.format(getString(R.string.gnss_error) + "%.2fm", errorDist)); } - trajectoryMapFragment.updateGNSS(gnssLocation); + trajectoryMapFragment.updateGNSSLocation(gnssLocation); } else { gnssError.setVisibility(View.GONE); trajectoryMapFragment.clearGNSS(); } } + LatLng fusedPos = sensorFusion.getFusionEstimate(); + // Fused position overlay + if (fusedPos != null && trajectoryMapFragment != null) { + trajectoryMapFragment.updateFusionLocation( + fusedPos, (float) Math.toDegrees(sensorFusion.getKalmanFilterOrientation())); + } + + // Retrieve floor plans for nearby buildings only while outside of a building + if (fusedPos != null + && trajectoryMapFragment != null + && !trajectoryMapFragment.getIsInsideBuilding()) { + sensorFusion.requestFloorPlans(fusedPos); + } + // Update previous previousPosX = pdrValues[0]; previousPosY = pdrValues[1]; + + // Building UI + String buildingName = sensorFusion.getCurrentBuilding().replace("_", " "); + textCampaignName.setText(buildingName); + if (trajectoryMapFragment != null && trajectoryMapFragment.getIsInsideBuilding()) { + textFloorNumberTitle.setVisibility(View.VISIBLE); + textFloorNumber.setVisibility(View.VISIBLE); + textFloorNumber.setText(trajectoryMapFragment.getFloorName()); + } else { + textFloorNumberTitle.setVisibility(View.GONE); + textFloorNumber.setVisibility(View.GONE); + } } - /** - * Start the blinking effect for the recording icon. - */ + /** Start the blinking effect for the recording icon. */ private void blinkingRecordingIcon() { Animation blinking = new AlphaAnimation(1, 0); blinking.setDuration(800); @@ -291,7 +356,7 @@ public void onPause() { @Override public void onResume() { super.onResume(); - if(!this.settings.getBoolean("split_trajectory", false)) { + if (!this.settings.getBoolean("split_trajectory", false)) { refreshDataHandler.postDelayed(refreshDataTask, 500); } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/RegisterFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/RegisterFragment.java new file mode 100644 index 00000000..ea257a07 --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/RegisterFragment.java @@ -0,0 +1,167 @@ +package com.openpositioning.PositionMe.presentation.fragment; + +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.navigation.NavDirections; +import androidx.navigation.Navigation; +import com.openpositioning.PositionMe.R; +import com.openpositioning.PositionMe.data.remote.ServerCommunications; +import com.openpositioning.PositionMe.sensors.Observer; + +public class RegisterFragment extends Fragment implements Observer { + private final String TAG = "RegisterFragment"; + private Button registerButton; + private TextView textLogInHere; + + private EditText usernameEditText; + private EditText emailEditText; + private EditText passwordEditText; + private EditText passwordCheckEditText; + private ServerCommunications serverCommunications; + + public RegisterFragment() { + // Required empty public constructor + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_register, container, false); + } + + /** Initialise UI elements and set onClick actions for the buttons. */ + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + serverCommunications = new ServerCommunications(this.getContext()); + serverCommunications.registerObserver(this); + + registerButton = view.findViewById(R.id.buttonRegister); + + textLogInHere = view.findViewById(R.id.textRegisterFragmentToLogin); + usernameEditText = view.findViewById(R.id.editTextRegisterUsername); + emailEditText = view.findViewById(R.id.editTextRegisterEmail); + passwordEditText = view.findViewById(R.id.editTextRegisterPassword); + passwordCheckEditText = view.findViewById(R.id.editTextRegisterPasswordAgain); + + textLogInHere.setOnClickListener( + v -> { + NavDirections action = + LoginFragmentDirections.actionRegisterFragmentToLoginFragment(); + Navigation.findNavController(v).navigate(action); + }); + + registerButton.setOnClickListener(v -> attemptRegistration()); + } + + private void attemptRegistration() { + String username = usernameEditText.getText().toString(); + String email = emailEditText.getText().toString(); + String password = passwordEditText.getText().toString(); + String passwordCheck = passwordCheckEditText.getText().toString(); + + if (username.isEmpty() + || email.isEmpty() + || password.isEmpty() + || passwordCheck.isEmpty()) { + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + this.getContext(), + "Please fill all login fields, and try again.", + Toast.LENGTH_SHORT) + .show(); + }); + return; + } else if (!password.equals(passwordCheck)) { + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + this.getContext(), + "Please check your passwords are the same, and try" + + " again.", + Toast.LENGTH_SHORT) + .show(); + }); + passwordEditText.setText(""); + passwordCheckEditText.setText(""); + return; + } + + // Disable UI to prevent multiple registration attempts + enableUIElements(false); + + serverCommunications.registerUserDetails(username, email, password); + } + + /** + * Enable or disable all registration UI elements to prevent users from modifying data while the + * server and/or app is processing it + * + *

This must be called from the main thread. + * + * @param state True to enable UI elements; False to disable + */ + private void enableUIElements(boolean state) { + registerButton.setEnabled(state); + usernameEditText.setEnabled(state); + emailEditText.setEnabled(state); + passwordEditText.setEnabled(state); + passwordCheckEditText.setEnabled(state); + textLogInHere.setClickable(state); + } + + @Override + public void update(Object[] objList) { + boolean success = (boolean) objList[0]; + if (!success) { + new Handler(Looper.getMainLooper()).post(() -> enableUIElements(true)); + return; + } + + try { + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + this.getContext(), + "Registration Successful!\nPlease now sign in", + Toast.LENGTH_SHORT) + .show(); + }); + + NavDirections action = LoginFragmentDirections.actionRegisterFragmentToLoginFragment(); + Navigation.findNavController(this.getView()).navigate(action); + } catch (IllegalStateException e) { + Log.w(TAG, e.getMessage()); + } catch (Exception e) { + String message = "Bad response from server. Registration halted"; + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText(this.getContext(), message, Toast.LENGTH_SHORT) + .show(); + }); + Log.w(TAG, message); + } + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/ReplayFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/ReplayFragment.java index d15a4a83..6a4df08b 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/ReplayFragment.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/ReplayFragment.java @@ -8,48 +8,44 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.SeekBar; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; - import com.google.android.gms.maps.model.LatLng; import com.openpositioning.PositionMe.R; -import com.openpositioning.PositionMe.presentation.activity.ReplayActivity; import com.openpositioning.PositionMe.data.local.TrajParser; - +import com.openpositioning.PositionMe.presentation.activity.ReplayActivity; +import com.openpositioning.PositionMe.sensors.SensorFusion; import java.io.File; import java.util.ArrayList; import java.util.List; /** * Sub fragment of Replay Activity. Fragment that replays trajectory data on a map. - *

- * The ReplayFragment is responsible for visualizing and replaying trajectory data captured during - * previous recordings. It loads trajectory data from a JSON file, updates the map with user movement, - * and provides UI controls for playback, pause, and seek functionalities. - *

- * Features: - * - Loads trajectory data from a file and displays it on a map. - * - Provides playback controls including play, pause, restart, and go to end. - * - Updates the trajectory dynamically as playback progresses. - * - Allows users to manually seek through the recorded trajectory. - * - Integrates with {@link TrajectoryMapFragment} for map visualization. + * + *

The ReplayFragment is responsible for visualizing and replaying trajectory data captured + * during previous recordings. It loads trajectory data from a JSON file, updates the map with user + * movement, and provides UI controls for playback, pause, and seek functionalities. + * + *

Features: - Loads trajectory data from a file and displays it on a map. - Provides playback + * controls including play, pause, restart, and go to end. - Updates the trajectory dynamically as + * playback progresses. - Allows users to manually seek through the recorded trajectory. - + * Integrates with {@link TrajectoryMapFragment} for map visualization. * * @see TrajectoryMapFragment The map fragment displaying the trajectory. * @see ReplayActivity The activity managing the replay workflow. * @see TrajParser Utility class for parsing trajectory data. - * * @author Shu Gu */ public class ReplayFragment extends Fragment { private static final String TAG = "ReplayFragment"; - // GPS start location (received from ReplayActivity) - private float initialLat = 0f; - private float initialLon = 0f; + // GPS start location + private float initialLat; + private float initialLon; + private SensorFusion sensorFusion = SensorFusion.getInstance(); private String filePath = ""; private int lastIndex = -1; @@ -72,15 +68,16 @@ public void onCreate(@Nullable Bundle savedInstanceState) { // Retrieve transferred data from ReplayActivity if (getArguments() != null) { filePath = getArguments().getString(ReplayActivity.EXTRA_TRAJECTORY_FILE_PATH, ""); - initialLat = getArguments().getFloat(ReplayActivity.EXTRA_INITIAL_LAT, 0f); - initialLon = getArguments().getFloat(ReplayActivity.EXTRA_INITIAL_LON, 0f); } // Log the received data Log.i(TAG, "ReplayFragment received data:"); Log.i(TAG, "Trajectory file path: " + filePath); - Log.i(TAG, "Initial latitude: " + initialLat); - Log.i(TAG, "Initial longitude: " + initialLon); + + // Get fallback location start using current GNSS + float[] startPosition = sensorFusion.getGNSSLatitude(false); + initialLat = startPosition[0]; + initialLon = startPosition[1]; // Check if file exists before parsing File trajectoryFile = new File(filePath); @@ -96,7 +93,8 @@ public void onCreate(@Nullable Bundle savedInstanceState) { Log.i(TAG, "Trajectory file confirmed to exist and is readable."); // Parse the JSON file and prepare replayData using TrajParser - replayData = TrajParser.parseTrajectoryData(filePath, requireContext(), initialLat, initialLon); + replayData = + TrajParser.parseTrajectoryData(filePath, requireContext(), initialLat, initialLon); // Log the number of parsed points if (replayData != null && !replayData.isEmpty()) { @@ -106,23 +104,23 @@ public void onCreate(@Nullable Bundle savedInstanceState) { } } - @Nullable @Override - public View onCreateView(@NonNull LayoutInflater inflater, - @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + public View onCreateView( + @NonNull LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_replay, container, false); } @Override - public void onViewCreated(@NonNull View view, - @Nullable Bundle savedInstanceState) { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // Initialize map fragment - trajectoryMapFragment = (TrajectoryMapFragment) - getChildFragmentManager().findFragmentById(R.id.replayMapFragmentContainer); + trajectoryMapFragment = + (TrajectoryMapFragment) + getChildFragmentManager().findFragmentById(R.id.replayMapFragmentContainer); if (trajectoryMapFragment == null) { trajectoryMapFragment = new TrajectoryMapFragment(); getChildFragmentManager() @@ -131,109 +129,108 @@ public void onViewCreated(@NonNull View view, .commit(); } - + // Initialize UI controls + playPauseButton = view.findViewById(R.id.playPauseButton); + restartButton = view.findViewById(R.id.restartButton); + exitButton = view.findViewById(R.id.exitButton); + goEndButton = view.findViewById(R.id.goEndButton); + playbackSeekBar = view.findViewById(R.id.playbackSeekBar); // 1) Check if the file contains any GNSS data - boolean gnssExists = hasAnyGnssData(replayData); + boolean gnssExistsInFile = hasAnyGnssData(replayData); - if (gnssExists) { + if (gnssExistsInFile) { showGnssChoiceDialog(); } else { - // No GNSS data -> automatically use param lat/lon - if (initialLat != 0f || initialLon != 0f) { - LatLng startPoint = new LatLng(initialLat, initialLon); - Log.i(TAG, "Setting initial map position: " + startPoint.toString()); - trajectoryMapFragment.setInitialCameraPosition(startPoint); + // Setup map + setupInitialMapPosition(initialLat, initialLon); + if (!replayData.isEmpty()) { + playbackSeekBar.setMax(replayData.size() - 1); + updateMapForIndex(0); } } - // Initialize UI controls - playPauseButton = view.findViewById(R.id.playPauseButton); - restartButton = view.findViewById(R.id.restartButton); - exitButton = view.findViewById(R.id.exitButton); - goEndButton = view.findViewById(R.id.goEndButton); - playbackSeekBar = view.findViewById(R.id.playbackSeekBar); - - // Set SeekBar max value based on replay data - if (!replayData.isEmpty()) { - playbackSeekBar.setMax(replayData.size() - 1); - } - // Button Listeners - playPauseButton.setOnClickListener(v -> { - if (replayData.isEmpty()) { - Log.w(TAG, "Play/Pause button pressed but replayData is empty."); - return; - } - if (isPlaying) { - isPlaying = false; - playPauseButton.setText("Play"); - Log.i(TAG, "Playback paused at index: " + currentIndex); - } else { - isPlaying = true; - playPauseButton.setText("Pause"); - Log.i(TAG, "Playback started from index: " + currentIndex); - if (currentIndex >= replayData.size()) { - currentIndex = 0; - } - playbackHandler.post(playbackRunnable); - } - }); + playPauseButton.setOnClickListener( + v -> { + if (replayData.isEmpty()) { + Log.w(TAG, "Play/Pause button pressed but replayData is empty."); + return; + } + if (isPlaying) { + isPlaying = false; + playPauseButton.setText("Play"); + Log.i(TAG, "Playback paused at index: " + currentIndex); + } else { + isPlaying = true; + playPauseButton.setText("Pause"); + Log.i(TAG, "Playback started from index: " + currentIndex); + if (currentIndex >= replayData.size()) { + currentIndex = 0; + } + playbackHandler.post(playbackRunnable); + } + }); // Restart button listener - restartButton.setOnClickListener(v -> { - if (replayData.isEmpty()) return; - currentIndex = 0; - playbackSeekBar.setProgress(0); - Log.i(TAG, "Restart button pressed. Resetting playback to index 0."); - updateMapForIndex(0); - }); + restartButton.setOnClickListener( + v -> { + if (replayData.isEmpty()) return; + currentIndex = 0; + playbackSeekBar.setProgress(0); + Log.i(TAG, "Restart button pressed. Resetting playback to index 0."); + trajectoryMapFragment.removeAllTimedMarkers(); + updateMapForIndex(0); + }); // Go to End button listener - goEndButton.setOnClickListener(v -> { - if (replayData.isEmpty()) return; - currentIndex = replayData.size() - 1; - playbackSeekBar.setProgress(currentIndex); - Log.i(TAG, "Go to End button pressed. Moving to last index: " + currentIndex); - updateMapForIndex(currentIndex); - isPlaying = false; - playPauseButton.setText("Play"); - }); + goEndButton.setOnClickListener( + v -> { + if (replayData.isEmpty()) return; + currentIndex = replayData.size() - 1; + playbackSeekBar.setProgress(currentIndex); + Log.i(TAG, "Go to End button pressed. Moving to last index: " + currentIndex); + updateMapForIndex(currentIndex); + isPlaying = false; + playPauseButton.setText("Play"); + }); // Exit button listener - exitButton.setOnClickListener(v -> { - Log.i(TAG, "Exit button pressed. Exiting replay."); - if (getActivity() instanceof ReplayActivity) { - ((ReplayActivity) getActivity()).finishFlow(); - } else { - requireActivity().onBackPressed(); - } - }); + exitButton.setOnClickListener( + v -> { + Log.i(TAG, "Exit button pressed. Exiting replay."); + if (getActivity() instanceof ReplayActivity) { + ((ReplayActivity) getActivity()).finishFlow(); + } else { + requireActivity().onBackPressed(); + } + }); // SeekBar listener - playbackSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (fromUser) { - Log.i(TAG, "SeekBar moved by user. New index: " + progress); - currentIndex = progress; - updateMapForIndex(currentIndex); - } - } - @Override public void onStartTrackingTouch(SeekBar seekBar) {} - @Override public void onStopTrackingTouch(SeekBar seekBar) {} - }); + playbackSeekBar.setOnSeekBarChangeListener( + new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + Log.i(TAG, "SeekBar moved by user. New index: " + progress); + currentIndex = progress; + updateMapForIndex(currentIndex); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} + }); if (!replayData.isEmpty()) { updateMapForIndex(0); } } - - - /** - * Checks if any ReplayPoint contains a non-null gnssLocation. - */ + /** Checks if any ReplayPoint contains a non-null gnssLocation. */ private boolean hasAnyGnssData(List data) { for (TrajParser.ReplayPoint point : data) { if (point.gnssLocation != null) { @@ -243,77 +240,104 @@ private boolean hasAnyGnssData(List data) { return false; } - /** - * Show a simple dialog asking user to pick: - * 1) GNSS from file - * 2) Lat/Lon from ReplayActivity arguments + * Show a simple dialog asking user to pick: 1) GNSS from file 2) Lat/Lon from ReplayActivity + * arguments */ private void showGnssChoiceDialog() { + LatLng firstGnss = getFirstGnssLocation(replayData); + new AlertDialog.Builder(requireContext()) .setTitle("Choose Starting Location") - .setMessage("GNSS data is found in the file. Would you like to use the file's GNSS as the start, or the one you manually picked?") - .setPositiveButton("Use File's GNSS", (dialog, which) -> { - LatLng firstGnss = getFirstGnssLocation(replayData); - if (firstGnss != null) { - setupInitialMapPosition((float) firstGnss.latitude, (float) firstGnss.longitude); - } else { - // Fallback if no valid GNSS found - setupInitialMapPosition(initialLat, initialLon); - } - dialog.dismiss(); - }) - .setNegativeButton("Use Manual Set", (dialog, which) -> { - setupInitialMapPosition(initialLat, initialLon); - dialog.dismiss(); - }) + .setMessage( + "GNSS data found in the trajectory.\n" + + "Which GNSS position would you like to use?") + .setPositiveButton( + "Use File's GNSS", + (dialog, which) -> { + if (firstGnss != null) { + // Re-parse with file's GNSS coords + replayData = + TrajParser.parseTrajectoryData( + filePath, + requireContext(), + firstGnss.latitude, + firstGnss.longitude); + setupInitialMapPosition( + (float) firstGnss.latitude, (float) firstGnss.longitude); + } else { + // Fallback if no valid GNSS found + setupInitialMapPosition(initialLat, initialLon); + } + playbackSeekBar.setMax(replayData.size() - 1); + updateMapForIndex(0); + dialog.dismiss(); + }) + .setNegativeButton( + "Use Current GNSS", + (dialog, which) -> { + // Re-parse with manual coords (or just use existing) + replayData = + TrajParser.parseTrajectoryData( + filePath, requireContext(), initialLat, initialLon); + setupInitialMapPosition(initialLat, initialLon); + playbackSeekBar.setMax(replayData.size() - 1); + updateMapForIndex(0); + dialog.dismiss(); + }) .setCancelable(false) .show(); } private void setupInitialMapPosition(float latitude, float longitude) { - LatLng startPoint = new LatLng(initialLat, initialLon); + LatLng startPoint = new LatLng(latitude, longitude); Log.i(TAG, "Setting initial map position: " + startPoint.toString()); trajectoryMapFragment.setInitialCameraPosition(startPoint); + + // Set initial orientation if data exists + if (!replayData.isEmpty()) { + float initialOrientation = replayData.get(0).orientation; + trajectoryMapFragment.updatePDRLocation(startPoint, initialOrientation); + Log.i(TAG, "Setting initial orientation: " + initialOrientation); + } } - /** - * Retrieve the first available GNSS location from the replay data. - */ + /** Retrieve the first available GNSS location from the replay data. */ private LatLng getFirstGnssLocation(List data) { for (TrajParser.ReplayPoint point : data) { if (point.gnssLocation != null) { - return new LatLng(replayData.get(0).gnssLocation.latitude, replayData.get(0).gnssLocation.longitude); + return new LatLng( + replayData.get(0).gnssLocation.latitude, + replayData.get(0).gnssLocation.longitude); } } return null; // None found } - /** - * Runnable for playback of trajectory data. - * This runnable is called repeatedly to update the map with the next point in the replayData list. + * Runnable for playback of trajectory data. This runnable is called repeatedly to update the + * map with the next point in the replayData list. */ - private final Runnable playbackRunnable = new Runnable() { - @Override - public void run() { - if (!isPlaying || replayData.isEmpty()) return; - - Log.i(TAG, "Playing index: " + currentIndex); - updateMapForIndex(currentIndex); - currentIndex++; - playbackSeekBar.setProgress(currentIndex); - - if (currentIndex < replayData.size()) { - playbackHandler.postDelayed(this, PLAYBACK_INTERVAL_MS); - } else { - Log.i(TAG, "Playback completed. Reached end of data."); - isPlaying = false; - playPauseButton.setText("Play"); - } - } - }; + private final Runnable playbackRunnable = + new Runnable() { + @Override + public void run() { + if (!isPlaying || replayData.isEmpty()) return; + Log.i(TAG, "Playing index: " + currentIndex); + updateMapForIndex(currentIndex); + currentIndex++; + playbackSeekBar.setProgress(currentIndex); + + if (currentIndex < replayData.size()) { + playbackHandler.postDelayed(this, PLAYBACK_INTERVAL_MS); + } else { + Log.i(TAG, "Playback completed. Reached end of data."); + isPlaying = false; + playPauseButton.setText("Play"); + } + } + }; /** * Update the map with the user location and GNSS location (if available) for the given index. @@ -333,17 +357,27 @@ private void updateMapForIndex(int newIndex) { trajectoryMapFragment.clearMapAndReset(); for (int i = 0; i <= newIndex; i++) { TrajParser.ReplayPoint p = replayData.get(i); - trajectoryMapFragment.updateUserLocation(p.pdrLocation, p.orientation); + trajectoryMapFragment.updatePDRLocation(p.pdrLocation, p.orientation); if (p.gnssLocation != null) { - trajectoryMapFragment.updateGNSS(p.gnssLocation); + trajectoryMapFragment.updateGNSSLocation(p.gnssLocation); + } + if (p.fusionLocation != null) { + trajectoryMapFragment.updateFusionLocation(p.fusionLocation, p.orientation); } } } else { // Normal sequential forward step: add just the new point TrajParser.ReplayPoint p = replayData.get(newIndex); - trajectoryMapFragment.updateUserLocation(p.pdrLocation, p.orientation); + trajectoryMapFragment.updatePDRLocation(p.pdrLocation, p.orientation); if (p.gnssLocation != null) { - trajectoryMapFragment.updateGNSS(p.gnssLocation); + trajectoryMapFragment.updateGNSSLocation(p.gnssLocation); + } + if (p.fusionLocation != null) { + trajectoryMapFragment.updateFusionLocation(p.fusionLocation, p.orientation); + } + if (p.testPoint != null) { + trajectoryMapFragment.addTimeMarker( + p.testPoint, p.testPointTime, p.testPointNumber); } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/SettingsFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/SettingsFragment.java index c1f6501c..b430cf2a 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/SettingsFragment.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/SettingsFragment.java @@ -2,18 +2,16 @@ import android.os.Bundle; import android.text.InputType; - import androidx.preference.EditTextPreference; import androidx.preference.PreferenceFragmentCompat; - import com.openpositioning.PositionMe.R; +import com.openpositioning.PositionMe.data.remote.LoginManager; /** - * SettingsFragment that inflates and displays the preferences (settings). - * Sets type for numeric only fields. + * SettingsFragment that inflates and displays the preferences (settings). Sets type for numeric + * only fields. * * @see HomeFragment the return fragment when leaving the settings. - * * @author Mate Stodulka */ public class SettingsFragment extends PreferenceFragmentCompat { @@ -23,35 +21,62 @@ public class SettingsFragment extends PreferenceFragmentCompat { private EditTextPreference elevationSeconds; private EditTextPreference accelSamples; private EditTextPreference epsilon; - private EditTextPreference accelFilter; + private EditTextPreference kalmanPredictedNoise; + private EditTextPreference kalmanBiasNoise; + private EditTextPreference kalmanMeasurementNoise; private EditTextPreference wifiInterval; + private LoginManager loginManager; /** - * {@inheritDoc} - * Sets the relevant numeric type for the preferences that should not take string values. + * {@inheritDoc} Sets the relevant numeric type for the preferences that should not take string + * values. */ @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.root_preferences, rootKey); - getActivity().setTitle("Settings"); + loginManager = LoginManager.getInstance(); + getActivity().setTitle("Settings - " + loginManager.getUsername()); + weibergK = findPreference("weiberg_k"); - weibergK.setOnBindEditTextListener(editText -> editText.setInputType( - InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL)); + weibergK.setOnBindEditTextListener( + editText -> + editText.setInputType( + InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL)); + elevationSeconds = findPreference("elevation_seconds"); - elevationSeconds.setOnBindEditTextListener(editText -> editText.setInputType( - InputType.TYPE_CLASS_NUMBER)); + elevationSeconds.setOnBindEditTextListener( + editText -> editText.setInputType(InputType.TYPE_CLASS_NUMBER)); + accelSamples = findPreference("accel_samples"); - accelSamples.setOnBindEditTextListener(editText -> editText.setInputType( - InputType.TYPE_CLASS_NUMBER)); + accelSamples.setOnBindEditTextListener( + editText -> editText.setInputType(InputType.TYPE_CLASS_NUMBER)); + epsilon = findPreference("epsilon"); - epsilon.setOnBindEditTextListener(editText -> editText.setInputType( - InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL)); - accelFilter = findPreference("accel_filter"); - accelFilter.setOnBindEditTextListener(editText -> editText.setInputType( - InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL)); + epsilon.setOnBindEditTextListener( + editText -> + editText.setInputType( + InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL)); + wifiInterval = findPreference("wifi_interval"); - wifiInterval.setOnBindEditTextListener(editText -> editText.setInputType( - InputType.TYPE_CLASS_NUMBER)); + wifiInterval.setOnBindEditTextListener( + editText -> editText.setInputType(InputType.TYPE_CLASS_NUMBER)); + + kalmanPredictedNoise = findPreference("kalman_pred_noise_std_dev"); + kalmanPredictedNoise.setOnBindEditTextListener( + editText -> + editText.setInputType( + InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL)); + + kalmanBiasNoise = findPreference("kalman_pred_bias_std_dev"); + kalmanBiasNoise.setOnBindEditTextListener( + editText -> + editText.setInputType( + InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL)); + kalmanMeasurementNoise = findPreference("kalman_noise"); + kalmanMeasurementNoise.setOnBindEditTextListener( + editText -> + editText.setInputType( + InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL)); } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/StartLocationFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/StartLocationFragment.java index ee14f69f..e4cb1b77 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/StartLocationFragment.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/StartLocationFragment.java @@ -1,16 +1,25 @@ package com.openpositioning.PositionMe.presentation.fragment; +import static com.openpositioning.PositionMe.utils.UtilConstants.POSITION_UOE_LAT; +import static com.openpositioning.PositionMe.utils.UtilConstants.POSITION_UOE_LON; +import static com.openpositioning.PositionMe.utils.UtilConstants.ZOOM_LEVEL_DEFAULT; + +import android.content.SharedPreferences; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; - +import android.widget.TextView; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; - +import androidx.preference.PreferenceManager; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; @@ -20,9 +29,7 @@ import com.google.android.gms.maps.model.MarkerOptions; import com.openpositioning.PositionMe.R; import com.openpositioning.PositionMe.presentation.activity.RecordingActivity; -import com.openpositioning.PositionMe.presentation.activity.ReplayActivity; import com.openpositioning.PositionMe.sensors.SensorFusion; -import com.openpositioning.PositionMe.utils.NucleusBuildingManager; /** * A simple {@link Fragment} subclass. The startLocation fragment is displayed before the trajectory @@ -35,172 +42,214 @@ * @see SensorFusion the class containing sensors and recording. */ public class StartLocationFragment extends Fragment { + private static final String TAG = "StartLocationFragment"; // Button to go to next fragment and save the location - private Button button; + private Button buttonStart; // Singleton SensorFusion class which stores data from all sensors - private SensorFusion sensorFusion = SensorFusion.getInstance(); + private SensorFusion sensorFusion; + private boolean positionFound; + private LatLng positionWiFi; + private float[] positionGNSS; + // Google maps LatLng object to pass location to the map private LatLng position; // Start position of the user to be stored private float[] startPosition = new float[2]; - // Zoom level for the Google map - private float zoom = 19f; - // Instance for managing indoor building overlays (if any) - private NucleusBuildingManager nucleusBuildingManager; - // Dummy variable for floor index - private int FloorNK; + private TextView startLocationHeader; + private GoogleMap gMap; - /** - * Public Constructor for the class. - * Left empty as not required - */ + private Marker startMarker; + private SharedPreferences settings; + boolean debugEnabled; + + /** Public Constructor for the class. Left empty as not required */ public StartLocationFragment() { // Required empty public constructor } /** - * {@inheritDoc} - * The map is loaded and configured so that it displays a draggable marker for the start location + * {@inheritDoc} The map is loaded and configured so that it displays a draggable marker for the + * start location */ @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { + public View onCreateView( + @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { AppCompatActivity activity = (AppCompatActivity) getActivity(); if (activity != null && activity.getSupportActionBar() != null) { activity.getSupportActionBar().hide(); } View rootView = inflater.inflate(R.layout.fragment_startlocation, container, false); - // Obtain the start position from the GPS data from the SensorFusion class - startPosition = sensorFusion.getGNSSLatitude(false); - // If no location found, zoom the map out - if (startPosition[0] == 0 && startPosition[1] == 0) { - zoom = 1f; - } else { - zoom = 19f; - } + startLocationHeader = rootView.findViewById(R.id.startLocationHeader); + sensorFusion = SensorFusion.getInstance(); + positionFound = false; + settings = PreferenceManager.getDefaultSharedPreferences(requireContext()); + debugEnabled = settings.getBoolean("debug_mode", false); // Initialize map fragment - SupportMapFragment supportMapFragment = (SupportMapFragment) - getChildFragmentManager().findFragmentById(R.id.startMap); - - supportMapFragment.getMapAsync(new OnMapReadyCallback() { - /** - * {@inheritDoc} - * Controls to allow scrolling, tilting, rotating and a compass view of the - * map are enabled. A marker is added to the map with the start position and a marker - * drag listener is generated to detect when the marker has moved to obtain the new - * location. - */ - @Override - public void onMapReady(GoogleMap mMap) { - // Set map type and UI settings - mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); - mMap.getUiSettings().setCompassEnabled(true); - mMap.getUiSettings().setTiltGesturesEnabled(true); - mMap.getUiSettings().setRotateGesturesEnabled(true); - mMap.getUiSettings().setScrollGesturesEnabled(true); - - // *** FIX: Clear any existing markers so the start marker isn’t duplicated *** - mMap.clear(); - - // Create NucleusBuildingManager instance (if needed) - nucleusBuildingManager = new NucleusBuildingManager(mMap); - nucleusBuildingManager.getIndoorMapManager().hideMap(); - - // Add a marker at the current GPS location and move the camera - position = new LatLng(startPosition[0], startPosition[1]); - Marker startMarker = mMap.addMarker(new MarkerOptions() - .position(position) - .title("Start Position") - .draggable(true)); - mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(position, zoom)); - - // Drag listener for the marker to update the start position when dragged - mMap.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener() { - /** - * {@inheritDoc} - */ - @Override - public void onMarkerDragStart(Marker marker) {} + SupportMapFragment supportMapFragment = + (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.startMap); + supportMapFragment.getMapAsync( + new OnMapReadyCallback() { /** - * {@inheritDoc} - * Updates the start position of the user. + * {@inheritDoc} Controls to allow scrolling, tilting, rotating and a compass + * view of the map are enabled. + * + *

A marker is added to the map with the start position, and a marker drag + * listener is generated to detect when the marker has moved to obtain the new + * location. */ @Override - public void onMarkerDragEnd(Marker marker) { - startPosition[0] = (float) marker.getPosition().latitude; - startPosition[1] = (float) marker.getPosition().longitude; + public void onMapReady(GoogleMap mMap) { + // Set map type and UI settings + mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); + mMap.getUiSettings().setCompassEnabled(true); + mMap.getUiSettings().setTiltGesturesEnabled(true); + mMap.getUiSettings().setRotateGesturesEnabled(true); + mMap.getUiSettings().setScrollGesturesEnabled(true); + + // Save for future reference + gMap = mMap; + positionFound = checkForPosition(); } + }); + return rootView; + } + + /** + * {@inheritDoc} Button onClick listener enabled to detect when to go to next fragment and start + * PDR recording. + */ + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + buttonStart = view.findViewById(R.id.startLocationDone); + buttonStart.setOnClickListener( + new View.OnClickListener() { /** * {@inheritDoc} + * + *

Start a recording if the position is available, or rescan for positions if + * not */ @Override - public void onMarkerDrag(Marker marker) {} + public void onClick(View view) { + if (positionFound) { + startRecording(); + } else { + positionFound = checkForPosition(); + } + } }); - } - }); + } - return rootView; + /** + * Check {@link SensorFusion} for any available Wi-Fi and GNSS locations, prioritising Wi-Fi, + * and updates the UI elements as required. + * + * @return True if a location was found; false otherwise + */ + private boolean checkForPosition() { + if (gMap == null) { + setUINoLocation(); + return false; + } + positionWiFi = sensorFusion.getLatLngWifiPositioning(); + if (positionWiFi != null) { + createStartMarker(positionWiFi); + setUIFoundLocation("Wi-Fi"); + return true; + } + + positionGNSS = sensorFusion.getGNSSLatitude(false); + if (positionGNSS[0] != 0 && positionGNSS[1] != 0) { + LatLng position = new LatLng(positionGNSS[0], positionGNSS[1]); + createStartMarker(position); + setUIFoundLocation("GNSS"); + return true; + } + + new Handler(Looper.getMainLooper()) + .post( + () -> + Toast.makeText( + getContext(), + "No location found", + Toast.LENGTH_SHORT) + .show()); + setUINoLocation(); + return false; } /** - * {@inheritDoc} - * Button onClick listener enabled to detect when to go to next fragment and start PDR recording. + * Update the UI to display that a location has been found + * + * @param type The type (Wi-Fi, or GNSS) of location found */ - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); + private void setUIFoundLocation(String type) { + startLocationHeader.setText( + "Start location found (" + type + ")\nPress \"Start\" to begin your recording"); + buttonStart.setText("Start"); + } + + /** + * Update the UI to state that no location is available, and zoom the map to a default location + */ + private void setUINoLocation() { + if (gMap != null) { + // Clear any existing markers so the start marker isn’t duplicated + gMap.clear(); + + // Add a marker at the current GPS location and move the camera + position = new LatLng(POSITION_UOE_LAT, POSITION_UOE_LON); + gMap.animateCamera(CameraUpdateFactory.newLatLngZoom(position, 16.5f)); + } + + startLocationHeader.setText("Waiting for starting location"); + buttonStart.setText("Scan for Location"); + } + + /** Pass control over to the {@link RecordingFragment} to being a recording */ + private void startRecording() { + float markerLat = (float) startMarker.getPosition().latitude; + float markerLon = (float) startMarker.getPosition().longitude; + startPosition = new float[] {markerLat, markerLon}; + + // If the Activity is RecordingActivity + if (requireActivity() instanceof RecordingActivity) { + // Start sensor recording + set the start location + sensorFusion.setStartLocation(startPosition); + sensorFusion.startRecording(); - this.button = view.findViewById(R.id.startLocationDone); - this.button.setOnClickListener(new View.OnClickListener() { - /** - * {@inheritDoc} - * When button clicked the PDR recording can start and the start position is stored for - * the {@link CorrectionFragment} to display. The {@link RecordingFragment} is loaded. - */ - @Override - public void onClick(View view) { - float chosenLat = startPosition[0]; - float chosenLon = startPosition[1]; - - // If the Activity is RecordingActivity - if (requireActivity() instanceof RecordingActivity) { - // Start sensor recording + set the start location - sensorFusion.startRecording(); - sensorFusion.setStartGNSSLatitude(startPosition); - - // Now switch to the recording screen - ((RecordingActivity) requireActivity()).showRecordingScreen(); - - // If the Activity is ReplayActivity - } else if (requireActivity() instanceof ReplayActivity) { - // *Do not* cast to RecordingActivity here - // Just call the Replay method - ((ReplayActivity) requireActivity()).onStartLocationChosen(chosenLat, chosenLon); - - // Otherwise (unexpected host) - } else { - // Optional: log or handle error - // Log.e("StartLocationFragment", "Unknown host Activity: " + requireActivity()); - } - } - }); + // Now switch to the recording screen + ((RecordingActivity) requireActivity()).showRecordingScreen(); + + // Otherwise (unexpected host) + } else { + // Optional: log or handle error + Log.w(TAG, "Unknown host Activity: " + requireActivity()); + } } /** - * Switches the indoor map to the specified floor. + * Draw a marker showing the start position on the map * - * @param floorIndex the index of the floor to switch to + * @param position The location the marker should be drawn to */ - private void switchFloorNU(int floorIndex) { - FloorNK = floorIndex; // Set the current floor index - if (nucleusBuildingManager != null) { - // Call the switchFloor method of the IndoorMapManager to switch to the specified floor - nucleusBuildingManager.getIndoorMapManager().switchFloor(floorIndex); + private void createStartMarker(LatLng position) { + if (startMarker != null) { + startMarker.remove(); + startMarker = null; } + startMarker = + gMap.addMarker( + new MarkerOptions() + .position(position) + .draggable(debugEnabled) + .title("Start Position")); + gMap.animateCamera(CameraUpdateFactory.newLatLngZoom(position, ZOOM_LEVEL_DEFAULT)); } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/TrajectoryMapFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/TrajectoryMapFragment.java index eb0bad65..27ecddee 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/TrajectoryMapFragment.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/TrajectoryMapFragment.java @@ -1,6 +1,20 @@ package com.openpositioning.PositionMe.presentation.fragment; -import android.graphics.Color; +import static com.openpositioning.PositionMe.fusion.FusionConstants.LINE_WEIGHT_PARTICLE; +import static com.openpositioning.PositionMe.fusion.FusionConstants.MAP_PARTICLE_COLOUR; +import static com.openpositioning.PositionMe.fusion.FusionConstants.MAP_PARTICLE_WEIGHTING; +import static com.openpositioning.PositionMe.fusion.FusionConstants.MAP_WIFI_COLOUR; +import static com.openpositioning.PositionMe.fusion.FusionConstants.OBSERVATION_TYPE_WIFI; +import static com.openpositioning.PositionMe.fusion.FusionConstants.WIFI_STD_DEV; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_FLOOR_PLAN_FILL_PREVIEW; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_FLOOR_PLAN_FILL_TRANSPARENT; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_PATH_COLOUR; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_PATH_FUSION; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_PATH_GNSS; +import static com.openpositioning.PositionMe.utils.BuildingConstants.MAP_DRAWING_PRIORITY_MAX; +import static com.openpositioning.PositionMe.utils.UtilConstants.LINE_WEIGHT_PATH; +import static com.openpositioning.PositionMe.utils.UtilConstants.ZOOM_LEVEL_DEFAULT; + import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; @@ -8,61 +22,71 @@ import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; -import android.widget.Button; import android.widget.Spinner; -import com.google.android.material.switchmaterial.SwitchMaterial; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; - +import com.google.android.gms.maps.CameraUpdateFactory; +import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; +import com.google.android.gms.maps.SupportMapFragment; +import com.google.android.gms.maps.model.BitmapDescriptorFactory; +import com.google.android.gms.maps.model.Circle; +import com.google.android.gms.maps.model.CircleOptions; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.Marker; +import com.google.android.gms.maps.model.MarkerOptions; +import com.google.android.gms.maps.model.Polygon; +import com.google.android.gms.maps.model.Polyline; +import com.google.android.gms.maps.model.PolylineOptions; +import com.google.android.material.switchmaterial.SwitchMaterial; import com.openpositioning.PositionMe.R; +import com.openpositioning.PositionMe.fusion.Particle; import com.openpositioning.PositionMe.sensors.SensorFusion; +import com.openpositioning.PositionMe.utils.Building; import com.openpositioning.PositionMe.utils.IndoorMapManager; import com.openpositioning.PositionMe.utils.UtilFunctions; -import com.google.android.gms.maps.CameraUpdateFactory; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.SupportMapFragment; -import com.google.android.gms.maps.model.*; - import java.util.ArrayList; import java.util.List; - +import java.util.Map; /** * A fragment responsible for displaying a trajectory map using Google Maps. - *

- * The TrajectoryMapFragment provides a map interface for visualizing movement trajectories, - * GNSS tracking, and indoor mapping. It manages map settings, user interactions, and real-time - * updates to user location and GNSS markers. - *

- * Key Features: - * - Displays a Google Map with support for different map types (Hybrid, Normal, Satellite). - * - Tracks and visualizes user movement using polylines. - * - Supports GNSS position updates and visual representation. - * - Includes indoor mapping with floor selection and auto-floor adjustments. - * - Allows user interaction through map controls and UI elements. * - * @see com.openpositioning.PositionMe.presentation.activity.RecordingActivity The activity hosting this fragment. - * @see com.openpositioning.PositionMe.utils.IndoorMapManager Utility for managing indoor map overlays. - * @see com.openpositioning.PositionMe.utils.UtilFunctions Utility functions for UI and graphics handling. + *

The TrajectoryMapFragment provides a map interface for visualizing movement trajectories, GNSS + * tracking, and indoor mapping. It manages map settings, user interactions, and real-time updates + * to user location and GNSS timedMarkers. * + *

Key Features: - Displays a Google Map with support for different map types (Hybrid, Normal, + * Satellite). - Tracks and visualizes user movement using polylines. - Supports GNSS position + * updates and visual representation. - Includes indoor mapping with floor selection and auto-floor + * adjustments. - Allows user interaction through map controls and UI elements. + * + * @see com.openpositioning.PositionMe.presentation.activity.RecordingActivity The activity hosting + * this fragment. + * @see com.openpositioning.PositionMe.utils.IndoorMapManager Utility for managing indoor map + * overlays. + * @see com.openpositioning.PositionMe.utils.UtilFunctions Utility functions for UI and graphics + * handling. * @author Mate Stodulka */ - public class TrajectoryMapFragment extends Fragment { + private static final String TAG = "TrajectoryMapFragment"; - private GoogleMap gMap; // Google Maps instance - private LatLng currentLocation; // Stores the user's current location - private Marker orientationMarker; // Marker representing user's heading - private Marker gnssMarker; // GNSS position marker - private Polyline polyline; // Polyline representing user's movement path - private boolean isRed = true; // Tracks whether the polyline color is red - private boolean isGnssOn = false; // Tracks if GNSS tracking is enabled + // Google Maps instance + private GoogleMap gMap; + + // Lines and headers for each type of positioning + private Polyline pdrPolyline; + private Marker pdrMarker; + private Marker gnssMarker; + private Polyline gnssPolyline; + private Marker fusionMarker; + private Polyline fusionPolyline; - private Polyline gnssPolyline; // Polyline for GNSS path + private LatLng currentLocation; // Stores the user's current location private LatLng lastGnssLocation = null; // Stores the last GNSS location + private LatLng lastFusedLocation = null; // private LatLng pendingCameraPosition = null; // Stores pending camera movement private boolean hasPendingCameraMove = false; // Tracks if camera needs to move @@ -70,138 +94,246 @@ public class TrajectoryMapFragment extends Fragment { private IndoorMapManager indoorMapManager; // Manages indoor mapping private SensorFusion sensorFusion; - // UI private Spinner switchMapSpinner; - private SwitchMaterial gnssSwitch; + private SwitchMaterial pdrSwitch; + private SwitchMaterial wifiAPSSwitch; private SwitchMaterial autoFloorSwitch; + private SwitchMaterial autopanSwitch; + private SwitchMaterial showParticlesSwitch; + private boolean isInsideBuilding = false; + private String currentFloorName = "no_floor"; - private com.google.android.material.floatingactionbutton.FloatingActionButton floorUpButton, floorDownButton; - private Button switchColorButton; - private Polygon buildingPolygon; - + private com.google.android.material.floatingactionbutton.FloatingActionButton floorUpButton, + floorDownButton; + private List timedMarkers = new ArrayList<>(); + private List particleCircles = new ArrayList<>(); + private List wifiAPSCircles = new ArrayList<>(); public TrajectoryMapFragment() { // Required empty public constructor } + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + sensorFusion = SensorFusion.getInstance(); + } + @Nullable @Override - public View onCreateView(@NonNull LayoutInflater inflater, - @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { + public View onCreateView( + @NonNull LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { // Inflate the separate layout containing map + map-related UI return inflater.inflate(R.layout.fragment_trajectory_map, container, false); } @Override - public void onViewCreated(@NonNull View view, - @Nullable Bundle savedInstanceState) { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // Grab references to UI controls switchMapSpinner = view.findViewById(R.id.mapSwitchSpinner); - gnssSwitch = view.findViewById(R.id.gnssSwitch); + autopanSwitch = view.findViewById(R.id.switchAutopan); + + gnssSwitch = view.findViewById(R.id.gnssSwitch); + pdrSwitch = view.findViewById(R.id.pdrSwitch); + wifiAPSSwitch = view.findViewById(R.id.wifiAPSSwitch); + autoFloorSwitch = view.findViewById(R.id.autoFloor); - floorUpButton = view.findViewById(R.id.floorUpButton); + showParticlesSwitch = view.findViewById(R.id.showParticles); + floorUpButton = view.findViewById(R.id.floorUpButton); floorDownButton = view.findViewById(R.id.floorDownButton); - switchColorButton = view.findViewById(R.id.lineColorButton); + + sensorFusion = SensorFusion.getInstance(); // Setup floor up/down UI hidden initially until we know there's an indoor map - setFloorControlsVisibility(View.GONE); + setFloorUIVisibility(View.GONE); // Initialize the map asynchronously - SupportMapFragment mapFragment = (SupportMapFragment) - getChildFragmentManager().findFragmentById(R.id.trajectoryMap); + SupportMapFragment mapFragment = + (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.trajectoryMap); if (mapFragment != null) { - mapFragment.getMapAsync(new OnMapReadyCallback() { - @Override - public void onMapReady(@NonNull GoogleMap googleMap) { - // Assign the provided googleMap to your field variable - gMap = googleMap; - // Initialize map settings with the now non-null gMap - initMapSettings(gMap); - - // If we had a pending camera move, apply it now - if (hasPendingCameraMove && pendingCameraPosition != null) { - gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(pendingCameraPosition, 19f)); - hasPendingCameraMove = false; - pendingCameraPosition = null; - } - - drawBuildingPolygon(); - - Log.d("TrajectoryMapFragment", "onMapReady: Map is ready!"); - - - } - }); + mapFragment.getMapAsync( + new OnMapReadyCallback() { + @Override + public void onMapReady(@NonNull GoogleMap googleMap) { + // Assign the provided googleMap to your field variable + gMap = googleMap; + // Initialize map settings with the now non-null gMap + initMapSettings(gMap); + + // If we had a pending camera move, apply it now + if (hasPendingCameraMove && pendingCameraPosition != null) { + gMap.moveCamera( + CameraUpdateFactory.newLatLngZoom( + pendingCameraPosition, ZOOM_LEVEL_DEFAULT)); + hasPendingCameraMove = false; + pendingCameraPosition = null; + } + + Log.d(TAG, "onMapReady: Map is ready!"); + } + }); } // Map type spinner setup initMapTypeSpinner(); // GNSS Switch - gnssSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> { - isGnssOn = isChecked; - if (!isChecked && gnssMarker != null) { - gnssMarker.remove(); - gnssMarker = null; - } - }); - - // Color switch - switchColorButton.setOnClickListener(v -> { - if (polyline != null) { - if (isRed) { - switchColorButton.setBackgroundColor(Color.BLACK); - polyline.setColor(Color.BLACK); - isRed = false; - } else { - switchColorButton.setBackgroundColor(Color.RED); - polyline.setColor(Color.RED); - isRed = true; + gnssSwitch.setOnCheckedChangeListener( + (buttonView, isChecked) -> { + setLineVisibility(gnssPolyline, gnssMarker, isChecked); + }); + + // PDR Switch + pdrSwitch.setOnCheckedChangeListener( + (buttonView, isChecked) -> { + setLineVisibility(pdrPolyline, pdrMarker, isChecked); + }); + + // Wi-Fi APS switch + wifiAPSSwitch.setOnCheckedChangeListener( + (buttonView, isChecked) -> { + if (!isChecked) removeAllWiFiAPS(); + }); + + // Auto-Pan switch + autopanSwitch.setOnCheckedChangeListener( + (buttonView, isChecked) -> checkAutoPan(isChecked, currentLocation)); + + floorUpButton.setOnClickListener( + v -> { + // If user manually changes floor, turn off auto floor + autoFloorSwitch.setChecked(false); + if (indoorMapManager != null) { + Building building = indoorMapManager.getCurrentBuilding(currentLocation); + if (building != null) { + building.setCurrentFloor(building.getFloorNumber() + 1, gMap); + } else { + Log.w(TAG, "Floor Up Button: No building!"); + } + } + }); + + floorDownButton.setOnClickListener( + v -> { + autoFloorSwitch.setChecked(false); + if (indoorMapManager != null) { + Building building = indoorMapManager.getCurrentBuilding(currentLocation); + if (building != null) { + building.setCurrentFloor(building.getFloorNumber() - 1, gMap); + } else { + Log.w(TAG, "Floor Down Button: No building!"); + } + } + }); + } + + @Override + public void onDestroy() { + Log.d(TAG, "Destroying " + getClass().getSimpleName()); + super.onDestroy(); + } + + /** + * Draw the API response's estimated positions based on Wi-Fi fingerprinting + * + * @see com.openpositioning.PositionMe.fusion.Fusion Fusion + */ + private void updateWiFiAPSDisplay() { + if (wifiAPSSwitch.isChecked()) { + + Map wifiObservationsMap = + sensorFusion.fusion.getObservationsByType(OBSERVATION_TYPE_WIFI); + List positions = (List) wifiObservationsMap.get("positions"); + List floorNames = (List) wifiObservationsMap.get("floor_names"); + + for (int i = 0; i < positions.size(); i++) { + LatLng position = positions.get(i); + String floorName = floorNames.get(i); + + // Do not redraw circles which already exist + boolean circleKnown = false; + for (Circle circle : wifiAPSCircles) { + if (circle.getCenter().equals(position)) { + circleKnown = true; + circle.setVisible(floorName.equals(currentFloorName)); + break; + } + } + if (circleKnown) continue; + + if (floorName.equals(currentFloorName)) { + Circle wifiAPSCircle = + gMap.addCircle( + new CircleOptions() + .center(position) + .zIndex(4) + .radius(WIFI_STD_DEV / 2) + .strokeColor(MAP_WIFI_COLOUR) + .fillColor(COLOUR_FLOOR_PLAN_FILL_TRANSPARENT)); + wifiAPSCircles.add(wifiAPSCircle); } } - }); - - // Floor up/down logic - autoFloorSwitch.setOnCheckedChangeListener((compoundButton, isChecked) -> { - - //TODO - fix the sensor fusion method to get the elevation (cannot get it from the current method) -// float elevationVal = sensorFusion.getElevation(); -// indoorMapManager.setCurrentFloor((int)(elevationVal/indoorMapManager.getFloorHeight()) -// ,true); - }); - - floorUpButton.setOnClickListener(v -> { - // If user manually changes floor, turn off auto floor - autoFloorSwitch.setChecked(false); - if (indoorMapManager != null) { - indoorMapManager.increaseFloor(); + + // Remove old observations + while (wifiAPSCircles.size() > positions.size()) { + Circle oldCircle = wifiAPSCircles.get(0); + if (oldCircle != null) { + oldCircle.remove(); + } + wifiAPSCircles.remove(0); } - }); + } + } - floorDownButton.setOnClickListener(v -> { - autoFloorSwitch.setChecked(false); - if (indoorMapManager != null) { - indoorMapManager.decreaseFloor(); + private void removeAllWiFiAPS() { + for (Circle circle : wifiAPSCircles) { + if (circle != null) { + circle.remove(); } - }); + } + wifiAPSCircles.clear(); } /** - * Initialize the map settings with the provided GoogleMap instance. - *

- * The method sets basic map settings, initializes the indoor map manager, - * and creates an empty polyline for user movement tracking. - * The method also initializes the GNSS polyline for tracking GNSS path. - * The method sets the map type to Hybrid and initializes the map with these settings. + * Helper function to show or hide a tracking method's line on the map * - * @param map + * @param polyline The line of the tracking method + * @param marker The head of the tracking method's line + * @param visibility True to show the line; false to hide the line */ + private void setLineVisibility(Polyline polyline, Marker marker, boolean visibility) { + if (polyline != null) polyline.setVisible(visibility); + if (marker != null) marker.setVisible(visibility); + } + /** + * Helper function for auto-pan support + * + * @param status True for auto-pan enabled; false for disabled + * @param position The position to zoom to + */ + private void checkAutoPan(boolean status, LatLng position) { + if (status && position != null) { + gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(position, ZOOM_LEVEL_DEFAULT)); + } + } + + /** + * Initialize the map settings with the provided GoogleMap instance. + * + *

The method sets basic map settings, initializes the indoor map manager, and creates an + * empty polyline for user movement tracking. The method also initializes the GNSS polyline for + * tracking GNSS path. The method sets the map type to Hybrid and initializes the map with these + * settings. + * + * @param map Google Map object + */ private void initMapSettings(GoogleMap map) { // Basic map settings map.getUiSettings().setCompassEnabled(true); @@ -214,80 +346,93 @@ private void initMapSettings(GoogleMap map) { indoorMapManager = new IndoorMapManager(map); // Initialize an empty polyline - polyline = map.addPolyline(new PolylineOptions() - .color(Color.RED) - .width(5f) - .add() // start empty - ); - - // GNSS path in blue - gnssPolyline = map.addPolyline(new PolylineOptions() - .color(Color.BLUE) - .width(5f) - .add() // start empty - ); + pdrPolyline = + map.addPolyline( + new PolylineOptions() + .color(COLOUR_PATH_COLOUR) + .width(LINE_WEIGHT_PATH) + .zIndex(MAP_DRAWING_PRIORITY_MAX) + .add() // start empty + ); + + // GNSS path + gnssPolyline = + map.addPolyline( + new PolylineOptions() + .color(COLOUR_PATH_GNSS) + .width(LINE_WEIGHT_PATH) + .zIndex(MAP_DRAWING_PRIORITY_MAX) + .add() // start empty + ); + + // Fused path + fusionPolyline = + map.addPolyline( + new PolylineOptions() + .color(COLOUR_PATH_FUSION) + .width(LINE_WEIGHT_PATH) + .zIndex(MAP_DRAWING_PRIORITY_MAX) + .add()); // start empty } - /** * Initialize the map type spinner with the available map types. - *

- * The spinner allows the user to switch between different map types - * (e.g. Hybrid, Normal, Satellite) to customize their map view. - * The spinner is populated with the available map types and listens - * for user selection to update the map accordingly. - * The map type is updated directly on the GoogleMap instance. - *

- * Note: The spinner is initialized with the default map type (Hybrid). - * The map type is updated on user selection. - *

- *

- * @see com.google.android.gms.maps.GoogleMap The GoogleMap instance to update map type. + * + *

The spinner allows the user to switch between different map types (e.g. Hybrid, Normal, + * Satellite) to customize their map view. The spinner is populated with the available map types + * and listens for user selection to update the map accordingly. The map type is updated + * directly on the GoogleMap instance. + * + *

Note: The spinner is initialized with the default map type (Hybrid). The map type is + * updated on user selection. + * + * @see com.google.android.gms.maps.GoogleMap The GoogleMap instance to update map type. */ private void initMapTypeSpinner() { if (switchMapSpinner == null) return; - String[] maps = new String[]{ - getString(R.string.hybrid), - getString(R.string.normal), - getString(R.string.satellite) - }; - ArrayAdapter adapter = new ArrayAdapter<>( - requireContext(), - android.R.layout.simple_spinner_dropdown_item, - maps - ); + String[] maps = + new String[] { + getString(R.string.hybrid), + getString(R.string.normal), + getString(R.string.satellite) + }; + ArrayAdapter adapter = + new ArrayAdapter<>( + requireContext(), android.R.layout.simple_spinner_dropdown_item, maps); switchMapSpinner.setAdapter(adapter); - switchMapSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, - int position, long id) { - if (gMap == null) return; - switch (position){ - case 0: - gMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); - break; - case 1: - gMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); - break; - case 2: - gMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE); - break; - } - } - @Override - public void onNothingSelected(AdapterView parent) {} - }); + switchMapSpinner.setOnItemSelectedListener( + new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected( + AdapterView parent, View view, int position, long id) { + if (gMap == null) return; + switch (position) { + case 0: + gMap.setMapType(GoogleMap.MAP_TYPE_HYBRID); + break; + case 1: + gMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); + break; + case 2: + gMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE); + break; + } + } + + @Override + public void onNothingSelected(AdapterView parent) {} + }); } /** - * Update the user's current location on the map, create or move orientation marker, - * and append to polyline if the user actually moved. + * Update the user's current location on the map, create or move orientation marker, and append + * to polyline if the user actually moved. * * @param newLocation The new location to plot. * @param orientation The user’s heading (e.g. from sensor fusion). */ - public void updateUserLocation(@NonNull LatLng newLocation, float orientation) { + public void updatePDRLocation(@NonNull LatLng newLocation, float orientation) { if (gMap == null) return; // Keep track of current location @@ -295,54 +440,277 @@ public void updateUserLocation(@NonNull LatLng newLocation, float orientation) { this.currentLocation = newLocation; // If no marker, create it - if (orientationMarker == null) { - orientationMarker = gMap.addMarker(new MarkerOptions() - .position(newLocation) - .flat(true) - .title("Current Position") - .icon(BitmapDescriptorFactory.fromBitmap( - UtilFunctions.getBitmapFromVector(requireContext(), - R.drawable.ic_baseline_navigation_24))) - ); - gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(newLocation, 19f)); + if (pdrMarker == null) { + pdrMarker = + gMap.addMarker( + new MarkerOptions() + .position(newLocation) + .flat(true) + .title("Current Position") + .icon( + BitmapDescriptorFactory.fromBitmap( + UtilFunctions.getBitmapFromVector( + requireContext(), + R.drawable + .ic_baseline_navigation_24)))); + gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(newLocation, ZOOM_LEVEL_DEFAULT)); } else { // Update marker position + orientation - orientationMarker.setPosition(newLocation); - orientationMarker.setRotation(orientation); - // Move camera a bit - gMap.moveCamera(CameraUpdateFactory.newLatLng(newLocation)); + pdrMarker.setPosition(newLocation); + pdrMarker.setRotation(orientation); } // Extend polyline if movement occurred - if (oldLocation != null && !oldLocation.equals(newLocation) && polyline != null) { - List points = new ArrayList<>(polyline.getPoints()); + if (oldLocation != null && !oldLocation.equals(newLocation) && pdrPolyline != null) { + List points = new ArrayList<>(pdrPolyline.getPoints()); points.add(newLocation); - polyline.setPoints(points); + pdrPolyline.setPoints(points); } - // Update indoor map overlay - if (indoorMapManager != null) { - indoorMapManager.setCurrentLocation(newLocation); - setFloorControlsVisibility(indoorMapManager.getIsIndoorMapSet() ? View.VISIBLE : View.GONE); + setLineVisibility(pdrPolyline, pdrMarker, pdrSwitch.isChecked()); + } + + /** + * Called when we want to set or update the GNSS marker position + * + * @param gnssLocation The new GNSS location + */ + public void updateGNSSLocation(@NonNull LatLng gnssLocation) { + if (gMap == null) return; + + if (gnssMarker == null) { + // Create the GNSS marker for the first time + gnssMarker = + gMap.addMarker( + new MarkerOptions() + .position(gnssLocation) + .title("GNSS Position") + .icon( + BitmapDescriptorFactory.defaultMarker( + BitmapDescriptorFactory.HUE_AZURE))); + lastGnssLocation = gnssLocation; + } else { + // Move existing GNSS marker + gnssMarker.setPosition(gnssLocation); + + // Add a segment to the blue GNSS line, if this is a new location + if (lastGnssLocation != null && !lastGnssLocation.equals(gnssLocation)) { + List gnssPoints = new ArrayList<>(gnssPolyline.getPoints()); + gnssPoints.add(gnssLocation); + gnssPolyline.setPoints(gnssPoints); + } + lastGnssLocation = gnssLocation; } + + setLineVisibility(gnssPolyline, gnssMarker, gnssSwitch.isChecked()); } + /** + * Update the user's current location on the map based on the {@link + * com.openpositioning.PositionMe.fusion.Fusion Fusion} algorithm + * + * @param fusedLocation The latest {@link com.openpositioning.PositionMe.fusion.Fusion Fusion} + * positioning estimate to plot + * @param orientation The user’s heading in degrees + */ + public void updateFusionLocation(@NonNull LatLng fusedLocation, float orientation) { + if (gMap == null) return; + if (!sensorFusion.fusion.isActive()) { + wifiAPSSwitch.setChecked(false); + wifiAPSSwitch.setEnabled(false); + // return; + } else { + wifiAPSSwitch.setEnabled(true); + } + + // Initialisation + if (fusionMarker == null) { + fusionMarker = + gMap.addMarker( + new MarkerOptions() + .position(fusedLocation) + .title("Fused Position") + .flat(true) + .icon( + BitmapDescriptorFactory.fromBitmap( + UtilFunctions.getBitmapFromVector( + requireContext(), + R.drawable + .ic_baseline_navigation_25)))); + List points = new ArrayList<>(fusionPolyline.getPoints()); + points.add(fusedLocation); + fusionPolyline.setPoints(points); + lastFusedLocation = fusedLocation; + } else { + // Updating trace on screen + fusionMarker.setPosition(fusedLocation); + if (!Float.isNaN(orientation)) fusionMarker.setRotation(orientation); + + if (lastFusedLocation != null && !lastFusedLocation.equals(fusedLocation)) { + List points = new ArrayList<>(fusionPolyline.getPoints()); + points.add(fusedLocation); + try { + fusionPolyline.setPoints(points); + } catch (IllegalArgumentException e) { + Log.w(TAG, "Invalid point; ignoring (" + e.getMessage() + ")"); + points.remove(fusedLocation); + fusionPolyline.setPoints(points); + } + } + lastFusedLocation = fusedLocation; + + // Auto-Pan will follow fusion path + checkAutoPan(autopanSwitch.isChecked(), fusedLocation); + + // Update building to display correct floor + indoorMapManager.drawBuildingPolygons(); + updateBuildingUI(fusedLocation); + makeClickableBuildings(); + + if (showParticlesSwitch.isChecked()) { + drawParticles(); + } else { + removeAllParticles(); + } + } + } + + /** + * Display all particles currently being used for positioning + * + * @see com.openpositioning.PositionMe.fusion.Fusion Fusion + * @see com.openpositioning.PositionMe.fusion.ParticleFilter ParticleFilter + * @see Particle + */ + private void drawParticles() { + // Clear all old particles + removeAllParticles(); + List particles = sensorFusion.getFusionParticles(); + + for (Particle particle : particles) { + double weight = particle.getWeight(); + double[] en = particle.getEastingNorthing(); + LatLng particleLatLng = sensorFusion.convertENToLatLng(en); + Circle particleCircle = + gMap.addCircle( + new CircleOptions() + .center(particleLatLng) + .radius(MAP_PARTICLE_WEIGHTING * weight) + .strokeWidth(LINE_WEIGHT_PARTICLE) + .fillColor(MAP_PARTICLE_COLOUR) + .zIndex(50)); + particleCircles.add(particleCircle); + } + } + + /** + * Update {@link IndoorMapManager indoor map} overlay to draw all possible {@link Building} + * outlines, and set the current floor in AutoFloor mode + * + *

Should be called when using {@link com.openpositioning.PositionMe.fusion.Fusion Fusion} + * + * @param location Current location of user on map + */ + private void updateBuildingUI(LatLng location) { + if (indoorMapManager != null) { + indoorMapManager.setCurrentLocation(location); + for (Building building : indoorMapManager.getAllBuildings()) { + building.drawBuildingOutline(gMap); + if (building.getIsInsideBuilding()) { + sensorFusion.setCurrentBuilding(building.getName()); + sensorFusion.onBuildingAvailable(building); + setFloorUIVisibility(View.VISIBLE); + isInsideBuilding = true; + wifiAPSSwitch.setEnabled(true); + + // AutoFloor elevation check + if (autoFloorSwitch.isChecked()) { + building.setCurrentFloor(sensorFusion.getEstimatedFloorNumber(), gMap); + } + currentFloorName = building.getFloorName(); + + if (wifiAPSSwitch.isChecked()) { + updateWiFiAPSDisplay(); + } + } else { + setFloorUIVisibility(View.GONE); + removeAllParticles(); + removeAllWiFiAPS(); + wifiAPSSwitch.setChecked(false); + wifiAPSSwitch.setEnabled(false); + isInsideBuilding = false; + } + } + } + } + + /** + * Make the {@link Building} {@link Polygon Polygons} clickable on the map to display floorplan + * previews + */ + private void makeClickableBuildings() { + if (indoorMapManager != null) { + for (Building building : indoorMapManager.getAllBuildings()) { + // Preview floor plan by clicking on building, and associate route + gMap.setOnPolygonClickListener( + polygon -> { + sensorFusion.setCurrentBuilding(building.getName()); + + // Only show a preview of the building if not inside + if (building.getIsInsideBuilding()) { + return; + } + // Only show preview if floor plans are available + if (building.getFloorNames().isEmpty()) { + Log.w( + TAG, + "Cannot show preview of " + + building.getName() + + " as there are no floor plans."); + return; + } + polygon = building.getBuildingOutline(); + int currentColour = polygon.getFillColor(); + switch (currentColour) { + case COLOUR_FLOOR_PLAN_FILL_TRANSPARENT -> + polygon.setFillColor(COLOUR_FLOOR_PLAN_FILL_PREVIEW); + case COLOUR_FLOOR_PLAN_FILL_PREVIEW -> + polygon.setFillColor(COLOUR_FLOOR_PLAN_FILL_TRANSPARENT); + } + // Display floor plan of ground floor + int groundFloorIndex = building.getGroundFloorIndex(); + List elements = + building.getFloorPlanElements( + building.getFloorNames().get(groundFloorIndex)); + if (elements == null) { + building.editFloorPlan(gMap, groundFloorIndex, true); + } else { + for (Polyline element : elements) { + element.setVisible(!element.isVisible()); + } + } + // Flag to not overwrite preview + building.setIsPreviewingFloorPlan(!building.getIsPreviewingFloorPlan()); + }); + } + } + } /** * Set the initial camera position for the map. - *

- * The method sets the initial camera position for the map when it is first loaded. - * If the map is already ready, the camera is moved immediately. - * If the map is not ready, the camera position is stored until the map is ready. - * The method also tracks if there is a pending camera move. - *

+ * + *

The method sets the initial camera position for the map when it is first loaded. If the + * map is already ready, the camera is moved immediately. If the map is not ready, the camera + * position is stored until the map is ready. The method also tracks if there is a pending + * camera move. + * * @param startLocation The initial camera position to set. */ public void setInitialCameraPosition(@NonNull LatLng startLocation) { // If the map is already ready, move camera immediately if (gMap != null) { - gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(startLocation, 19f)); + gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(startLocation, ZOOM_LEVEL_DEFAULT)); } else { // Otherwise, store it until onMapReady pendingCameraPosition = startLocation; @@ -350,48 +718,58 @@ public void setInitialCameraPosition(@NonNull LatLng startLocation) { } } - /** - * Get the current user location on the map. - * @return The current user location as a LatLng object. + * Adds a timed marker to the map + * + * @param pos Position of the marker + * @param timeLabel Label associated with the marker + * @param number The marker's number */ - public LatLng getCurrentLocation() { - return currentLocation; + public void addTimeMarker(LatLng pos, String timeLabel, int number) { + if (gMap == null || pos == null) return; + + Marker marker = + gMap.addMarker( + new MarkerOptions() + .position(pos) + .title("Test Point #" + number) + .snippet("Time: " + timeLabel) + .icon( + BitmapDescriptorFactory.defaultMarker( + BitmapDescriptorFactory.HUE_GREEN))); + timedMarkers.add(marker); } - /** - * Called when we want to set or update the GNSS marker position - */ - public void updateGNSS(@NonNull LatLng gnssLocation) { - if (gMap == null) return; - if (!isGnssOn) return; - - if (gnssMarker == null) { - // Create the GNSS marker for the first time - gnssMarker = gMap.addMarker(new MarkerOptions() - .position(gnssLocation) - .title("GNSS Position") - .icon(BitmapDescriptorFactory - .defaultMarker(BitmapDescriptorFactory.HUE_AZURE))); - lastGnssLocation = gnssLocation; - } else { - // Move existing GNSS marker - gnssMarker.setPosition(gnssLocation); - - // Add a segment to the blue GNSS line, if this is a new location - if (lastGnssLocation != null && !lastGnssLocation.equals(gnssLocation)) { - List gnssPoints = new ArrayList<>(gnssPolyline.getPoints()); - gnssPoints.add(gnssLocation); - gnssPolyline.setPoints(gnssPoints); + /** Clears timedMarkers from maps */ + public void removeAllTimedMarkers() { + for (Marker marker : timedMarkers) { + if (marker != null) { + marker.remove(); } - lastGnssLocation = gnssLocation; } + timedMarkers.clear(); } + /** Clear all particles from the map */ + public void removeAllParticles() { + for (Circle particleCircle : particleCircles) { + if (particleCircle != null) { + particleCircle.remove(); + } + } + particleCircles.clear(); + } /** - * Remove GNSS marker if user toggles it off + * Get the current user location on the map. + * + * @return The current user location as a LatLng object. */ + public LatLng getCurrentLocation() { + return currentLocation; + } + + /** Remove GNSS marker if user toggles it off */ public void clearGNSS() { if (gnssMarker != null) { gnssMarker.remove(); @@ -399,143 +777,92 @@ public void clearGNSS() { } } - /** - * Whether user is currently showing GNSS or not - */ + /** Whether user is currently showing GNSS or not */ public boolean isGnssEnabled() { - return isGnssOn; + return gnssSwitch.isChecked(); } - private void setFloorControlsVisibility(int visibility) { + public boolean getIsInsideBuilding() { + return isInsideBuilding; + } + + public String getFloorName() { + return currentFloorName; + } + + private void setFloorUIVisibility(int visibility) { floorUpButton.setVisibility(visibility); floorDownButton.setVisibility(visibility); + + // When entering building for first time, default to auto floor enabled + if (autoFloorSwitch.getVisibility() == View.GONE) { + autoFloorSwitch.setChecked(true); + } autoFloorSwitch.setVisibility(visibility); + + // Disable particle display switch when hiding + if (visibility == View.GONE && showParticlesSwitch.isChecked()) { + showParticlesSwitch.setChecked(false); + } + showParticlesSwitch.setVisibility(visibility); } public void clearMapAndReset() { - if (polyline != null) { - polyline.remove(); - polyline = null; + if (pdrPolyline != null) { + pdrPolyline.remove(); + pdrPolyline = null; } if (gnssPolyline != null) { gnssPolyline.remove(); gnssPolyline = null; } - if (orientationMarker != null) { - orientationMarker.remove(); - orientationMarker = null; + if (fusionPolyline != null) { + fusionPolyline.remove(); + fusionPolyline = null; + } + if (pdrMarker != null) { + pdrMarker.remove(); + pdrMarker = null; + } + if (fusionMarker != null) { + fusionMarker.remove(); + fusionMarker = null; } if (gnssMarker != null) { gnssMarker.remove(); gnssMarker = null; } + + removeAllParticles(); + removeAllWiFiAPS(); + + lastFusedLocation = null; lastGnssLocation = null; - currentLocation = null; + currentLocation = null; // Re-create empty polylines with your chosen colors if (gMap != null) { - polyline = gMap.addPolyline(new PolylineOptions() - .color(Color.RED) - .width(5f) - .add()); - gnssPolyline = gMap.addPolyline(new PolylineOptions() - .color(Color.BLUE) - .width(5f) - .add()); + pdrPolyline = + gMap.addPolyline( + new PolylineOptions() + .color(COLOUR_PATH_COLOUR) + .width(LINE_WEIGHT_PATH) + .zIndex(MAP_DRAWING_PRIORITY_MAX) + .add()); + gnssPolyline = + gMap.addPolyline( + new PolylineOptions() + .color(COLOUR_PATH_GNSS) + .width(LINE_WEIGHT_PATH) + .zIndex(MAP_DRAWING_PRIORITY_MAX) + .add()); + fusionPolyline = + gMap.addPolyline( + new PolylineOptions() + .color(COLOUR_PATH_FUSION) + .width(LINE_WEIGHT_PATH) + .zIndex(MAP_DRAWING_PRIORITY_MAX) + .add()); } } - - /** - * Draw the building polygon on the map - *

- * The method draws a polygon representing the building on the map. - * The polygon is drawn with specific vertices and colors to represent - * different buildings or areas on the map. - * The method removes the old polygon if it exists and adds the new polygon - * to the map with the specified options. - * The method logs the number of vertices in the polygon for debugging. - *

- * - * Note: The method uses hard-coded vertices for the building polygon. - * - *

- * - * See: {@link com.google.android.gms.maps.model.PolygonOptions} The options for the new polygon. - */ - private void drawBuildingPolygon() { - if (gMap == null) { - Log.e("TrajectoryMapFragment", "GoogleMap is not ready"); - return; - } - - // nuclear building polygon vertices - LatLng nucleus1 = new LatLng(55.92279538827796, -3.174612147506538); - LatLng nucleus2 = new LatLng(55.92278121423647, -3.174107900816096); - LatLng nucleus3 = new LatLng(55.92288405733954, -3.173843694667146); - LatLng nucleus4 = new LatLng(55.92331786793876, -3.173832892645086); - LatLng nucleus5 = new LatLng(55.923337194112555, -3.1746284301397387); - - - // nkml building polygon vertices - LatLng nkml1 = new LatLng(55.9230343434213, -3.1751847990731954); - LatLng nkml2 = new LatLng(55.923032840563366, -3.174777103346131); - LatLng nkml4 = new LatLng(55.92280139974615, -3.175195527934348); - LatLng nkml3 = new LatLng(55.922793885410734, -3.1747958788136867); - - LatLng fjb1 = new LatLng(55.92269205199916, -3.1729563477188774);//left top - LatLng fjb2 = new LatLng(55.922822801570994, -3.172594249522305); - LatLng fjb3 = new LatLng(55.92223512226413, -3.171921917547244); - LatLng fjb4 = new LatLng(55.9221071265519, -3.1722813131202097); - - LatLng faraday1 = new LatLng(55.92242866264128, -3.1719553662011815); - LatLng faraday2 = new LatLng(55.9224966752294, -3.1717846714743474); - LatLng faraday3 = new LatLng(55.922271383074154, -3.1715191463437162); - LatLng faraday4 = new LatLng(55.92220124468304, -3.171705013935158); - - - - PolygonOptions buildingPolygonOptions = new PolygonOptions() - .add(nucleus1, nucleus2, nucleus3, nucleus4, nucleus5) - .strokeColor(Color.RED) // Red border - .strokeWidth(10f) // Border width - //.fillColor(Color.argb(50, 255, 0, 0)) // Semi-transparent red fill - .zIndex(1); // Set a higher zIndex to ensure it appears above other overlays - - // Options for the new polygon - PolygonOptions buildingPolygonOptions2 = new PolygonOptions() - .add(nkml1, nkml2, nkml3, nkml4, nkml1) - .strokeColor(Color.BLUE) // Blue border - .strokeWidth(10f) // Border width - // .fillColor(Color.argb(50, 0, 0, 255)) // Semi-transparent blue fill - .zIndex(1); // Set a higher zIndex to ensure it appears above other overlays - - PolygonOptions buildingPolygonOptions3 = new PolygonOptions() - .add(fjb1, fjb2, fjb3, fjb4, fjb1) - .strokeColor(Color.GREEN) // Green border - .strokeWidth(10f) // Border width - //.fillColor(Color.argb(50, 0, 255, 0)) // Semi-transparent green fill - .zIndex(1); // Set a higher zIndex to ensure it appears above other overlays - - PolygonOptions buildingPolygonOptions4 = new PolygonOptions() - .add(faraday1, faraday2, faraday3, faraday4, faraday1) - .strokeColor(Color.YELLOW) // Yellow border - .strokeWidth(10f) // Border width - //.fillColor(Color.argb(50, 255, 255, 0)) // Semi-transparent yellow fill - .zIndex(1); // Set a higher zIndex to ensure it appears above other overlays - - - // Remove the old polygon if it exists - if (buildingPolygon != null) { - buildingPolygon.remove(); - } - - // Add the polygon to the map - buildingPolygon = gMap.addPolygon(buildingPolygonOptions); - gMap.addPolygon(buildingPolygonOptions2); - gMap.addPolygon(buildingPolygonOptions3); - gMap.addPolygon(buildingPolygonOptions4); - Log.d("TrajectoryMapFragment", "Building polygon added, vertex count: " + buildingPolygon.getPoints().size()); - } - - } diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/UploadFragment.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/UploadFragment.java index 9d435812..26feff13 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/UploadFragment.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/fragment/UploadFragment.java @@ -1,31 +1,34 @@ package com.openpositioning.PositionMe.presentation.fragment; +import static com.openpositioning.PositionMe.utils.UtilConstants.BUILDING_NAME_M_HOUSE; +import static com.openpositioning.PositionMe.utils.UtilConstants.DEBUG_MODE_HEADER; + +import android.content.SharedPreferences; +import android.os.Build; import android.os.Bundle; +import android.os.Environment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import android.os.Environment; -import android.os.Build; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; +import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; - import com.openpositioning.PositionMe.R; +import com.openpositioning.PositionMe.data.remote.LoginManager; import com.openpositioning.PositionMe.data.remote.ServerCommunications; -import com.openpositioning.PositionMe.presentation.viewitems.UploadViewHolder; +import com.openpositioning.PositionMe.presentation.activity.MainActivity; import com.openpositioning.PositionMe.presentation.viewitems.DownloadClickListener; import com.openpositioning.PositionMe.presentation.viewitems.UploadListAdapter; - +import com.openpositioning.PositionMe.presentation.viewitems.UploadViewHolder; import java.io.File; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; - /** * A simple {@link Fragment} subclass. Displays trajectories that were saved locally because no * acceptable network was available to upload it when the recording finished. Trajectories can be @@ -34,6 +37,7 @@ * @author Mate Stodulka */ public class UploadFragment extends Fragment { + private static final String TAG = "UploadFragment"; // UI elements private TextView emptyNotice; @@ -45,26 +49,24 @@ public class UploadFragment extends Fragment { // List of files saved locally private List localTrajectories; + private LoginManager loginManager; - /** - * Public default constructor, empty. - */ + /** Public default constructor, empty. */ public UploadFragment() { // Required empty public constructor } - /** - * {@inheritDoc} - * Initialises new Server Communication instance with the context, and finds all the files that - * match the trajectory naming scheme in local storage. + * {@inheritDoc} Initialises new Server Communication instance with the context, and finds all + * the files that match the trajectory naming scheme in local storage. */ - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Get communication class serverCommunications = new ServerCommunications(getActivity()); + serverCommunications.registerObserver((MainActivity) getActivity()); + loginManager = LoginManager.getInstance(); // Determine the directory to load trajectory files from. File trajectoriesDir = null; @@ -79,36 +81,48 @@ public void onCreate(Bundle savedInstanceState) { trajectoriesDir = getActivity().getFilesDir(); } - localTrajectories = Stream.of(trajectoriesDir.listFiles((file, name) -> - name.contains("trajectory_") && name.endsWith(".txt"))) - .filter(file -> !file.isDirectory()) - .collect(Collectors.toList()); + localTrajectories = + Stream.of( + trajectoriesDir.listFiles( + (file, name) -> + name.contains("trajectory_") + && name.endsWith(".txt"))) + .filter(file -> !file.isDirectory()) + .collect(Collectors.toList()); } - /** - * {@inheritDoc} - * Sets the title in the action bar to "Upload" - */ + /** {@inheritDoc} Sets the title in the action bar to "Upload" */ @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - getActivity().setTitle("Upload"); + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + // Make debug mode explicit in the header + String debugHeader; + SharedPreferences settings = + PreferenceManager.getDefaultSharedPreferences(requireContext()); + if (settings.getBoolean("debug_mode", false)) { + debugHeader = DEBUG_MODE_HEADER; + } else { + debugHeader = ""; + } + getActivity().setTitle(debugHeader + "Upload - " + loginManager.getUsername()); + + // getActivity().setTitle("Upload - " + loginManager.getUsername()); // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_upload, container, false); } /** - * {@inheritDoc} - * Checks if there are locally saved trajectories. If there are none, it displays a text message - * notifying the user. If there are local files, the text is hidden, and instead a Recycler View - * is displayed showing all the trajectories. - *

- * A Layout Manager is registered, and the adapter and list of files passed. An onClick listener - * is set up to upload the file when clicked and remove it from local storage. + * {@inheritDoc} Checks if there are locally saved trajectories. If there are none, it displays + * a text message notifying the user. If there are local files, the text is hidden, and instead + * a Recycler View is displayed showing all the trajectories. + * + *

A Layout Manager is registered, and the adapter and list of files passed. An onClick + * listener is set up to upload the file when clicked and remove it from local storage. * * @see UploadListAdapter list adapter for the recycler view. * @see UploadViewHolder view holder for the recycler view. - * @see com.openpositioning.PositionMe.R.layout#item_upload_card_view xml view for list elements. + * @see com.openpositioning.PositionMe.R.layout#item_upload_card_view xml view for list + * elements. */ @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { @@ -117,11 +131,10 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat this.emptyNotice = view.findViewById(R.id.emptyUpload); this.uploadList = view.findViewById(R.id.uploadTrajectories); // Check if there are locally saved trajectories - if(localTrajectories.isEmpty()) { + if (localTrajectories.isEmpty()) { uploadList.setVisibility(View.GONE); emptyNotice.setVisibility(View.VISIBLE); - } - else { + } else { uploadList.setVisibility(View.VISIBLE); emptyNotice.setVisibility(View.GONE); @@ -129,20 +142,27 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat LinearLayoutManager manager = new LinearLayoutManager(getActivity()); uploadList.setLayoutManager(manager); uploadList.setHasFixedSize(true); - listAdapter = new UploadListAdapter(getActivity(), localTrajectories, new DownloadClickListener() { - /** - * {@inheritDoc} - * Upload the trajectory at the clicked position, remove it from the recycler view - * and the local list. - */ - @Override - public void onPositionClicked(int position) { - serverCommunications.uploadLocalTrajectory(localTrajectories.get(position)); -// localTrajectories.remove(position); -// listAdapter.notifyItemRemoved(position); - } - }); + listAdapter = + new UploadListAdapter( + getActivity(), + localTrajectories, + new DownloadClickListener() { + /** + * {@inheritDoc} Upload the trajectory at the clicked position, + * remove it from the recycler view and the local list. + */ + @Override + public void onPositionClicked(int position) { + File trajectory = localTrajectories.get(position); + + // TODO - Replace static test value with dynamic building name + serverCommunications.uploadLocalTrajectory( + trajectory, BUILDING_NAME_M_HOUSE); + localTrajectories.remove(position); + listAdapter.notifyItemRemoved(position); + } + }); uploadList.setAdapter(listAdapter); } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/BleListAdapter.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/BleListAdapter.java new file mode 100644 index 00000000..0066a637 --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/BleListAdapter.java @@ -0,0 +1,91 @@ +package com.openpositioning.PositionMe.presentation.viewitems; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import com.openpositioning.PositionMe.R; +import com.openpositioning.PositionMe.sensors.BleDevice; +import java.util.List; + +/** + * Adapter used for displaying BLE device data. + * + * @see BleViewHolder corresponding View Holder class + * @see com.openpositioning.PositionMe.R.layout#item_ble_card_view xml layout file + * @author Vlad Stratulat + */ +public class BleListAdapter extends RecyclerView.Adapter { + + Context context; + List items; + + /** + * Default public constructor with context for inflating views and list to be displayed. + * + * @param context application context to enable inflating views used in the list. + * @param items list of BleDevice objects to be displayed in the list. + * @see BleDevice the data class. + */ + public BleListAdapter(Context context, List items) { + this.context = context; + this.items = items; + } + + /** + * {@inheritDoc} + * + * @see com.openpositioning.PositionMe.R.layout#item_ble_card_view xml layout file + */ + @NonNull + @Override + public BleViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new BleViewHolder( + LayoutInflater.from(context).inflate(R.layout.item_ble_card_view, parent, false)); + } + + /** + * {@inheritDoc} Formats and assigns the data fields from the BleDevice object to the TextView + * fields. + * + * @see BleDevice data class + * @see com.openpositioning.PositionMe.R.string formatting for strings. + * @see com.openpositioning.PositionMe.R.layout#item_ble_card_view xml layout file + */ + @Override + public void onBindViewHolder(@NonNull BleViewHolder holder, int position) { + BleDevice device = items.get(position); + String macString = context.getString(R.string.mac, device.getMacAddress()); + holder.macAddress.setText(macString); + + // BLE Name + String rawName = device.getName(); + String nameToShow; + if (rawName == null || rawName.trim().isEmpty()) { + nameToShow = context.getString(R.string.unknown); + } else { + nameToShow = rawName; + } + String nameString = context.getString(R.string.name, nameToShow); + holder.name.setText(nameString); + + String levelString = context.getString(R.string.db, Integer.toString(device.getRssi())); + holder.rssi.setText(levelString); + } + + /** + * {@inheritDoc} Number of BleDevice objects. + * + * @return number of items in the list. + */ + @Override + public int getItemCount() { + return items.size(); + } + + public void updateData(List newItems) { + this.items = newItems; + notifyDataSetChanged(); + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/BleViewHolder.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/BleViewHolder.java new file mode 100644 index 00000000..9d722d62 --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/BleViewHolder.java @@ -0,0 +1,33 @@ +package com.openpositioning.PositionMe.presentation.viewitems; + +import android.view.View; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import com.openpositioning.PositionMe.R; + +/** + * View holder class for the RecyclerView displaying BLE device data. + * + * @see BleListAdapter the corresponding list adapter. + * @see com.openpositioning.PositionMe.R.layout#item_ble_card_view xml layout file + * @author Vlad Stratulat + */ +public class BleViewHolder extends RecyclerView.ViewHolder { + + TextView macAddress; + TextView name; + TextView rssi; + + /** + * {@inheritDoc} Assign TextView fields corresponding to BleDevice attributes. + * + * @see com.openpositioning.PositionMe.sensors.BleDevice the data class + */ + public BleViewHolder(@NonNull View itemView) { + super(itemView); + macAddress = itemView.findViewById(R.id.bleAddressItem); + name = itemView.findViewById(R.id.bleNameItem); + rssi = itemView.findViewById(R.id.bleRssiItem); + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/DownloadClickListener.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/DownloadClickListener.java index 202f4a43..74ae1484 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/DownloadClickListener.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/DownloadClickListener.java @@ -10,8 +10,7 @@ public interface DownloadClickListener { /** * Function executed when the item is clicked. * - * @param position integer position of the item in the list. + * @param position integer position of the item in the list. */ void onPositionClicked(int position); - } diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/SensorInfoListAdapter.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/SensorInfoListAdapter.java index 4315328d..35c1676f 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/SensorInfoListAdapter.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/SensorInfoListAdapter.java @@ -3,13 +3,10 @@ import android.content.Context; import android.view.LayoutInflater; import android.view.ViewGroup; - import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; - import com.openpositioning.PositionMe.R; import com.openpositioning.PositionMe.sensors.SensorInfo; - import java.util.List; import java.util.Objects; @@ -18,7 +15,6 @@ * * @see SensorInfoViewHolder corresponding View Holder class * @see com.openpositioning.PositionMe.R.layout#item_sensorinfo_card_view xml layout file - * * @author Mate Stodulka */ public class SensorInfoListAdapter extends RecyclerView.Adapter { @@ -29,9 +25,8 @@ public class SensorInfoListAdapter extends RecyclerView.Adapter sensorInfoList) { @@ -41,17 +36,20 @@ public SensorInfoListAdapter(Context context, List sensorInfoList) { /** * {@inheritDoc} + * * @see com.openpositioning.PositionMe.R.layout#item_sensorinfo_card_view xml layout file */ @NonNull @Override public SensorInfoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new SensorInfoViewHolder(LayoutInflater.from(context).inflate(R.layout.item_sensorinfo_card_view, parent, false)); + return new SensorInfoViewHolder( + LayoutInflater.from(context) + .inflate(R.layout.item_sensorinfo_card_view, parent, false)); } /** - * {@inheritDoc} - * Formats and assigns the data fields from the SensorInfo object to the TextView fields. + * {@inheritDoc} Formats and assigns the data fields from the SensorInfo object to the TextView + * fields. * * @see SensorInfo data class * @see com.openpositioning.PositionMe.R.string formatting for strings. @@ -61,20 +59,29 @@ public SensorInfoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int vi public void onBindViewHolder(@NonNull SensorInfoViewHolder holder, int position) { holder.name.setText(sensorInfoList.get(position).getName()); - String vendorString = context.getString(R.string.vendor, sensorInfoList.get(position).getVendor()); + String vendorString = + context.getString(R.string.vendor, sensorInfoList.get(position).getVendor()); holder.vendor.setText(vendorString); - String resolutionString = context.getString(R.string.resolution, String.format("%.03g", sensorInfoList.get(position).getResolution())); + String resolutionString = + context.getString( + R.string.resolution, + String.format("%.03g", sensorInfoList.get(position).getResolution())); holder.resolution.setText(resolutionString); - String powerString = context.getString(R.string.power, Objects.toString(sensorInfoList.get(position).getPower(), "N/A")); + String powerString = + context.getString( + R.string.power, + Objects.toString(sensorInfoList.get(position).getPower(), "N/A")); holder.power.setText(powerString); - String versionString = context.getString(R.string.version, Objects.toString(sensorInfoList.get(position).getVersion(), "N/A")); + String versionString = + context.getString( + R.string.version, + Objects.toString(sensorInfoList.get(position).getVersion(), "N/A")); holder.version.setText(versionString); } /** - * {@inheritDoc} - * Number of SensorInfo objects. + * {@inheritDoc} Number of SensorInfo objects. * * @see SensorInfo */ diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/SensorInfoViewHolder.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/SensorInfoViewHolder.java index 469ec16e..f3d64182 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/SensorInfoViewHolder.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/SensorInfoViewHolder.java @@ -2,10 +2,8 @@ import android.view.View; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; - import com.openpositioning.PositionMe.R; /** @@ -13,7 +11,6 @@ * * @see SensorInfoListAdapter the corresponding list adapter. * @see com.openpositioning.PositionMe.R.layout#item_sensorinfo_card_view xml layout file - * * @author Mate Stodulka */ public class SensorInfoViewHolder extends RecyclerView.ViewHolder { @@ -22,8 +19,7 @@ public class SensorInfoViewHolder extends RecyclerView.ViewHolder { TextView name, vendor, resolution, power, version; /** - * {@inheritDoc} - * Assign TextView fields corresponding to SensorInfo attributes. + * {@inheritDoc} Assign TextView fields corresponding to SensorInfo attributes. * * @see com.openpositioning.PositionMe.sensors.SensorInfo the data class */ diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/TrajDownloadListAdapter.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/TrajDownloadListAdapter.java index 7de29c8a..1da9076e 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/TrajDownloadListAdapter.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/TrajDownloadListAdapter.java @@ -1,46 +1,43 @@ package com.openpositioning.PositionMe.presentation.viewitems; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; -import java.util.Iterator; -import java.io.File; -import java.io.FileReader; -import java.io.BufferedReader; - +import android.content.Context; import android.content.Intent; -import android.os.Handler; -import android.os.Looper; import android.os.Environment; import android.os.FileObserver; -import android.content.Context; +import android.os.Handler; +import android.os.Looper; import android.util.Log; import android.view.LayoutInflater; import android.view.ViewGroup; - +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; - import com.google.android.material.button.MaterialButton; import com.openpositioning.PositionMe.R; import com.openpositioning.PositionMe.data.remote.ServerCommunications; import com.openpositioning.PositionMe.presentation.activity.ReplayActivity; import com.openpositioning.PositionMe.presentation.fragment.FilesFragment; - -import org.json.JSONObject; - +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; +import org.json.JSONObject; /** - * Adapter used for displaying trajectory metadata in a RecyclerView list. - * This adapter binds trajectory metadata from the server to individual view items. - * The download status is indicated via a button with different icons. - * The adapter also listens for file changes using FileObserver to update the download records in real time. - * A local set of "downloading" trajectory IDs is maintained to support simultaneous downloads. + * Adapter used for displaying trajectory metadata in a RecyclerView list. This adapter binds + * trajectory metadata from the server to individual view items. The download status is indicated + * via a button with different icons. The adapter also listens for file changes using FileObserver + * to update the download records in real time. A local set of "downloading" trajectory IDs is + * maintained to support simultaneous downloads. + * * @see TrajDownloadViewHolder for the corresponding view holder. * @see FilesFragment for details on how the data is generated. * @see ServerCommunications for where the response items are received. @@ -48,7 +45,8 @@ public class TrajDownloadListAdapter extends RecyclerView.Adapter { // Date-time formatter used to format date and time. - private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + private static final DateTimeFormatter dateFormat = + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); private final Context context; private final List> responseItems; @@ -63,11 +61,14 @@ public class TrajDownloadListAdapter extends RecyclerView.Adapter> responseItems, DownloadClickListener listener) { + public TrajDownloadListAdapter( + Context context, + List> responseItems, + DownloadClickListener listener) { this.context = context; this.responseItems = responseItems; this.listener = listener; @@ -78,18 +79,21 @@ public TrajDownloadListAdapter(Context context, List> respon } /** - * Loads the local download records from storage. - * The records are stored in a JSON file located in the app-specific Downloads directory. - * After loading, any trajectory IDs that have now finished downloading are removed - * from the downloading set. + * Loads the local download records from storage. The records are stored in a JSON file located + * in the app-specific Downloads directory. After loading, any trajectory IDs that have now + * finished downloading are removed from the downloading set. */ private void loadDownloadRecords() { try { - File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "download_records.json"); + File file = + new File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + "download_records.json"); if (file.exists()) { // Read the file line by line to reduce memory usage. StringBuilder jsonBuilder = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new FileReader(file), 8192)) { // Increase buffer size + try (BufferedReader reader = + new BufferedReader(new FileReader(file), 8192)) { // Increase buffer size String line; while ((line = reader.readLine()) != null) { jsonBuilder.append(line); @@ -113,17 +117,23 @@ private void loadDownloadRecords() { ServerCommunications.downloadRecords.put(id, recordDetails); } - System.out.println("Download records loaded: " + ServerCommunications.downloadRecords); + System.out.println( + "Download records loaded: " + ServerCommunications.downloadRecords); - // Remove any IDs from the downloading set that are now present in the download records. + // Remove any IDs from the downloading set that are now present in the download + // records. // This ensures the "downloading" state is removed when the download completes. - downloadingTrajIds.removeIf(id -> ServerCommunications.downloadRecords.containsKey(id)); + downloadingTrajIds.removeIf( + id -> ServerCommunications.downloadRecords.containsKey(id)); // Refresh the RecyclerView UI on the main thread. - new Handler(Looper.getMainLooper()).post(() -> { - notifyDataSetChanged(); - System.out.println("RecyclerView fully refreshed after loading records."); - }); + new Handler(Looper.getMainLooper()) + .post( + () -> { + notifyDataSetChanged(); + System.out.println( + "RecyclerView fully refreshed after loading records."); + }); } else { System.out.println("Download records file not found."); } @@ -142,44 +152,49 @@ private void initFileObserver() { return; } // Create a FileObserver for the directory where the file is located. - fileObserver = new FileObserver(downloadsFolder.getAbsolutePath(), FileObserver.MODIFY) { - @Override - public void onEvent(int event, String path) { - // Only act if the modified file is "download_records.json". - if (path != null && path.equals("download_records.json")) { - Log.i("FileObserver", "download_records.json has been modified."); - // On file modification, load the records and update the UI on the main thread. - new Handler(Looper.getMainLooper()).post(() -> { - loadDownloadRecords(); - }); - } - } - }; + fileObserver = + new FileObserver(downloadsFolder.getAbsolutePath(), FileObserver.MODIFY) { + @Override + public void onEvent(int event, String path) { + // Only act if the modified file is "download_records.json". + if (path != null && path.equals("download_records.json")) { + Log.i("FileObserver", "download_records.json has been modified."); + // On file modification, load the records and update the UI on the main + // thread. + new Handler(Looper.getMainLooper()) + .post( + () -> { + loadDownloadRecords(); + }); + } + } + }; fileObserver.startWatching(); } /** * Creates a new view holder for a trajectory item. * - * @param parent The parent view group. + * @param parent The parent view group. * @param viewType The view type. * @return A new instance of TrajDownloadViewHolder. */ @NonNull @Override public TrajDownloadViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new TrajDownloadViewHolder(LayoutInflater.from(context) - .inflate(R.layout.item_trajectorycard_view, parent, false), listener); + return new TrajDownloadViewHolder( + LayoutInflater.from(context) + .inflate(R.layout.item_trajectorycard_view, parent, false), + listener); } /** - * Binds data to the view holder. - * Formats and assigns trajectory metadata fields to the corresponding views. - * The button state is determined as follows: - * - If the trajectory is present in the download records, it is set as "downloaded". - * - Else if the trajectory is in the downloading set, it is set as "downloading". - * - Otherwise, it is set as "not downloaded". - * @param holder The view holder to bind data to. + * Binds data to the view holder. Formats and assigns trajectory metadata fields to the + * corresponding views. The button state is determined as follows: - If the trajectory is + * present in the download records, it is set as "downloaded". - Else if the trajectory is in + * the downloading set, it is set as "downloading". - Otherwise, it is set as "not downloaded". + * + * @param holder The view holder to bind data to. * @param position The position of the item in the list. */ @Override @@ -198,11 +213,8 @@ public void onBindViewHolder(@NonNull TrajDownloadViewHolder holder, int positio // Parse and format the submission date. String dateSubmittedStr = responseItems.get(position).get("date_submitted"); assert dateSubmittedStr != null; - holder.getTrajDate().setText( - dateFormat.format( - LocalDateTime.parse(dateSubmittedStr.split("\\.")[0]) - ) - ); + holder.getTrajDate() + .setText(dateFormat.format(LocalDateTime.parse(dateSubmittedStr.split("\\.")[0]))); // Determine if the trajectory is already downloaded by checking the records. JSONObject recordDetails = ServerCommunications.downloadRecords.get(id); @@ -213,7 +225,10 @@ public void onBindViewHolder(@NonNull TrajDownloadViewHolder holder, int positio try { String fileName = recordDetails.optString("file_name", null); if (fileName != null) { - File file = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), fileName); + File file = + new File( + context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), + fileName); filePath = file.getAbsolutePath(); } // Set the button state to "downloaded". @@ -234,26 +249,40 @@ public void onBindViewHolder(@NonNull TrajDownloadViewHolder holder, int positio final String finalFilePath = filePath; // Set the click listener for the download button. - holder.downloadButton.setOnClickListener(v -> { - String trajId = responseItems.get(position).get("id"); - - if (finalMatched) { - // If the item is already downloaded, start ReplayActivity to display the trajectory. - if (finalFilePath != null) { - Intent intent = new Intent(context, ReplayActivity.class); - intent.putExtra(ReplayActivity.EXTRA_TRAJECTORY_FILE_PATH, finalFilePath); - context.startActivity(intent); - } - } else { - // If the item is not downloaded, trigger the download action. - listener.onPositionClicked(position); - // Mark the trajectory as downloading. - downloadingTrajIds.add(trajId); - // Immediately update the button state to "downloading". - setButtonState(holder.downloadButton, 2); - // The FileObserver will update the UI when the file changes. - } - }); + holder.downloadButton.setOnClickListener( + v -> { + String trajId = responseItems.get(position).get("id"); + + if (finalMatched) { + // If the item is already downloaded, start ReplayActivity to display the + // trajectory. + if (finalFilePath != null) { + Intent intent = new Intent(context, ReplayActivity.class); + intent.putExtra( + ReplayActivity.EXTRA_TRAJECTORY_FILE_PATH, finalFilePath); + context.startActivity(intent); + } + } else if (downloadingTrajIds.contains(id)) { + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + context, + "This trajectory is already being" + + " processed", + Toast.LENGTH_SHORT) + .show(); + }); + } else { + // If the item is not downloaded, trigger the download action. + listener.onPositionClicked(position); + // Mark the trajectory as downloading. + downloadingTrajIds.add(trajId); + // Immediately update the button state to "downloading". + setButtonState(holder.downloadButton, 2); + // The FileObserver will update the UI when the file changes. + } + }); holder.downloadButton.invalidate(); } @@ -272,24 +301,24 @@ public int getItemCount() { * Sets the appearance of the button based on its state. * * @param button The MaterialButton to update. - * @param state The state of the button: - * 0 - Not downloaded, - * 1 - Downloaded, - * 2 - Downloading. + * @param state The state of the button: 0 - Not downloaded, 1 - Downloaded, 2 - Downloading. */ private void setButtonState(MaterialButton button, int state) { if (state == 1) { button.setIconResource(R.drawable.ic_baseline_play_circle_filled_24); button.setIconTintResource(R.color.md_theme_onPrimary); - button.setBackgroundTintList(ContextCompat.getColorStateList(context, R.color.md_theme_primary)); + button.setBackgroundTintList( + ContextCompat.getColorStateList(context, R.color.md_theme_primary)); } else if (state == 2) { button.setIconResource(R.drawable.baseline_data_usage_24); button.setIconTintResource(R.color.md_theme_onPrimary); - button.setBackgroundTintList(ContextCompat.getColorStateList(context, R.color.goldYellow)); + button.setBackgroundTintList( + ContextCompat.getColorStateList(context, R.color.goldYellow)); } else { button.setIconResource(R.drawable.ic_baseline_download_24); button.setIconTintResource(R.color.md_theme_onSecondary); - button.setBackgroundTintList(ContextCompat.getColorStateList(context, R.color.md_theme_light_primary)); + button.setBackgroundTintList( + ContextCompat.getColorStateList(context, R.color.md_theme_light_primary)); } } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/TrajDownloadViewHolder.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/TrajDownloadViewHolder.java index af14249f..5427e3a0 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/TrajDownloadViewHolder.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/TrajDownloadViewHolder.java @@ -2,14 +2,11 @@ import android.view.View; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; - import com.google.android.material.button.MaterialButton; import com.openpositioning.PositionMe.R; import com.openpositioning.PositionMe.presentation.fragment.FilesFragment; - import java.lang.ref.WeakReference; /** @@ -17,10 +14,10 @@ * * @see TrajDownloadListAdapter the corresponding list adapter. * @see com.openpositioning.PositionMe.R.layout#item_trajectorycard_view xml layout file - * * @author Mate Stodulka */ -public class TrajDownloadViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { +public class TrajDownloadViewHolder extends RecyclerView.ViewHolder + implements View.OnClickListener { private final TextView trajId; private final TextView trajDate; @@ -28,8 +25,7 @@ public class TrajDownloadViewHolder extends RecyclerView.ViewHolder implements V private final WeakReference listenerReference; /** - * {@inheritDoc} - * Assign TextView fields corresponding to Trajectory metadata. + * {@inheritDoc} Assign TextView fields corresponding to Trajectory metadata. * * @param listener DownloadClickListener to enable acting on clicks on items. * @see FilesFragment generating the data and implementing the listener. @@ -44,23 +40,17 @@ public TrajDownloadViewHolder(@NonNull View itemView, DownloadClickListener list this.downloadButton.setOnClickListener(this); } - /** - * Public getter for trajId. - */ + /** Public getter for trajId. */ public TextView getTrajId() { return trajId; } - /** - * Public getter for trajDate. - */ + /** Public getter for trajDate. */ public TextView getTrajDate() { return trajDate; } - /** - * Calls the onPositionClick function on the listenerReference object. - */ + /** Calls the onPositionClick function on the listenerReference object. */ @Override public void onClick(View view) { listenerReference.get().onPositionClicked(getAdapterPosition()); diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/UploadListAdapter.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/UploadListAdapter.java index b564e231..f4d0ad17 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/UploadListAdapter.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/UploadListAdapter.java @@ -1,16 +1,15 @@ package com.openpositioning.PositionMe.presentation.viewitems; import android.content.Context; +import android.os.Handler; +import android.os.Looper; import android.view.LayoutInflater; import android.view.ViewGroup; import android.widget.Toast; - import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; - import com.openpositioning.PositionMe.R; import com.openpositioning.PositionMe.presentation.fragment.UploadFragment; - import java.io.File; import java.util.List; import java.util.regex.Matcher; @@ -21,7 +20,6 @@ * * @see UploadViewHolder corresponding View Holder class * @see com.openpositioning.PositionMe.R.layout#item_upload_card_view xml layout file - * * @author Mate Stodulka */ public class UploadListAdapter extends RecyclerView.Adapter { @@ -33,13 +31,13 @@ public class UploadListAdapter extends RecyclerView.Adapter { /** * Default public constructor with context for inflating views and list to be displayed. * - * @param context application context to enable inflating views used in the list. - * @param uploadItems List of trajectory Files found locally on the device. - * @param listener clickListener to download trajectories when clicked. - * + * @param context application context to enable inflating views used in the list. + * @param uploadItems List of trajectory Files found locally on the device. + * @param listener clickListener to download trajectories when clicked. * @see com.openpositioning.PositionMe.Traj protobuf objects exchanged with the server. */ - public UploadListAdapter(Context context, List uploadItems, DownloadClickListener listener) { + public UploadListAdapter( + Context context, List uploadItems, DownloadClickListener listener) { this.context = context; this.uploadItems = uploadItems; this.listener = listener; @@ -53,12 +51,14 @@ public UploadListAdapter(Context context, List uploadItems, DownloadClickL @NonNull @Override public UploadViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new UploadViewHolder(LayoutInflater.from(context).inflate(R.layout.item_upload_card_view, parent, false), listener); + return new UploadViewHolder( + LayoutInflater.from(context).inflate(R.layout.item_upload_card_view, parent, false), + listener); } /** - * {@inheritDoc} - * Formats and assigns the data fields from the local Trajectory Files object to the TextView fields. + * {@inheritDoc} Formats and assigns the data fields from the local Trajectory Files object to + * the TextView fields. * * @see UploadFragment finding the data from on local storage. * @see com.openpositioning.PositionMe.R.layout#item_upload_card_view xml layout file. @@ -74,34 +74,41 @@ public void onBindViewHolder(@NonNull UploadViewHolder holder, int position) { // Set click listener for the delete button holder.deletebutton.setOnClickListener(v -> deleteFileAtPosition(position)); - } - /** - * {@inheritDoc} - * Number of local files. - */ + /** {@inheritDoc} Number of local files. */ @Override public int getItemCount() { return uploadItems.size(); } - private void deleteFileAtPosition(int position) - { - if (position >= 0 && position < uploadItems.size()) - { + private void deleteFileAtPosition(int position) { + if (position >= 0 && position < uploadItems.size()) { File fileToDelete = uploadItems.get(position); - if (fileToDelete.exists() && fileToDelete.delete()) - { + if (fileToDelete.exists() && fileToDelete.delete()) { uploadItems.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, uploadItems.size()); // Update subsequent items - Toast.makeText(context, "File deleted successfully", Toast.LENGTH_SHORT).show(); - } - else - { - Toast.makeText(context, "Failed to delete file", Toast.LENGTH_SHORT).show(); + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + context, + "File deleted successfully", + Toast.LENGTH_SHORT) + .show(); + }); + } else { + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + context, + "Failed to delete file", + Toast.LENGTH_SHORT) + .show(); + }); } } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/UploadViewHolder.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/UploadViewHolder.java index e6068969..c43fff09 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/UploadViewHolder.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/UploadViewHolder.java @@ -3,14 +3,11 @@ import android.view.View; import android.widget.Button; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; - import com.google.android.material.button.MaterialButton; import com.openpositioning.PositionMe.R; import com.openpositioning.PositionMe.presentation.fragment.UploadFragment; - import java.lang.ref.WeakReference; /** @@ -18,26 +15,22 @@ * * @see UploadListAdapter the corresponding list adapter. * @see com.openpositioning.PositionMe.R.layout#item_upload_card_view xml layout file - * * @author Mate Stodulka */ public class UploadViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { TextView trajId; TextView trajDate; - MaterialButton uploadButton; // Correct reference to MaterialButton + MaterialButton uploadButton; // Correct reference to MaterialButton // Weak reference to the click listener to enable garbage collection on recyclerview items private WeakReference listenerReference; public Button deletebutton; /** - * {@inheritDoc} - * Assign TextView fields corresponding to Trajectory file metadata. + * {@inheritDoc} Assign TextView fields corresponding to Trajectory file metadata. * * @param listener DownloadClickListener to enable acting on clicks on items. - * - * @see UploadFragment locating the data and implementing the - * listener. + * @see UploadFragment locating the data and implementing the listener. */ public UploadViewHolder(@NonNull View itemView, DownloadClickListener listener) { super(itemView); @@ -51,10 +44,7 @@ public UploadViewHolder(@NonNull View itemView, DownloadClickListener listener) this.deletebutton = itemView.findViewById(R.id.deletebutton); } - /** - * {@inheritDoc} - * Calls the onPositionClick function on the listenerReference object. - */ + /** {@inheritDoc} Calls the onPositionClick function on the listenerReference object. */ @Override public void onClick(View view) { listenerReference.get().onPositionClicked(getAdapterPosition()); diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/WifiListAdapter.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/WifiListAdapter.java index 887e7689..92bf80f6 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/WifiListAdapter.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/WifiListAdapter.java @@ -3,13 +3,10 @@ import android.content.Context; import android.view.LayoutInflater; import android.view.ViewGroup; - import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; - import com.openpositioning.PositionMe.R; import com.openpositioning.PositionMe.sensors.Wifi; - import java.util.List; /** @@ -17,7 +14,6 @@ * * @see WifiViewHolder corresponding View Holder class * @see com.openpositioning.PositionMe.R.layout#item_wifi_card_view xml layout file - * * @author Mate Stodulka */ public class WifiListAdapter extends RecyclerView.Adapter { @@ -28,9 +24,8 @@ public class WifiListAdapter extends RecyclerView.Adapter { /** * Default public constructor with context for inflating views and list to be displayed. * - * @param context application context to enable inflating views used in the list. - * @param items list of Wifi objects to be displayed in the list. - * + * @param context application context to enable inflating views used in the list. + * @param items list of Wifi objects to be displayed in the list. * @see Wifi the data class. */ public WifiListAdapter(Context context, List items) { @@ -40,17 +35,19 @@ public WifiListAdapter(Context context, List items) { /** * {@inheritDoc} + * * @see com.openpositioning.PositionMe.R.layout#item_wifi_card_view xml layout file */ @NonNull @Override public WifiViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new WifiViewHolder(LayoutInflater.from(context).inflate(R.layout.item_wifi_card_view,parent,false)); + return new WifiViewHolder( + LayoutInflater.from(context).inflate(R.layout.item_wifi_card_view, parent, false)); } /** - * {@inheritDoc} - * Formats and assigns the data fields from the Wifi object to the TextView fields. + * {@inheritDoc} Formats and assigns the data fields from the Wifi object to the TextView + * fields. * * @see Wifi data class * @see com.openpositioning.PositionMe.R.string formatting for strings. @@ -58,15 +55,27 @@ public WifiViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType */ @Override public void onBindViewHolder(@NonNull WifiViewHolder holder, int position) { - String macString = context.getString(R.string.mac, Long.toString(items.get(position).getBssid())); - holder.bssid.setText(macString); - String levelString = context.getString(R.string.db, Long.toString(items.get(position).getLevel())); + Wifi wifi = items.get(position); + + String macString = context.getString(R.string.mac, Long.toString(wifi.getBssid())); + holder.mac.setText(macString); + String levelString = context.getString(R.string.db, Long.toString(wifi.getLevel())); holder.level.setText(levelString); + + // Show SSID (name) + String rawSsid = wifi.getSsid(); + String ssidToShow; + if (rawSsid == null || rawSsid.trim().isEmpty()) { + ssidToShow = context.getString(R.string.unknown); + } else { + ssidToShow = rawSsid; + } + String nameString = context.getString(R.string.name, ssidToShow); + holder.ssid.setText(nameString); } /** - * {@inheritDoc} - * Number of Wifi objects. + * {@inheritDoc} Number of Wifi objects. * * @see Wifi */ @@ -74,4 +83,9 @@ public void onBindViewHolder(@NonNull WifiViewHolder holder, int position) { public int getItemCount() { return items.size(); } + + public void updateData(List newItems) { + this.items = newItems; + notifyDataSetChanged(); + } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/WifiViewHolder.java b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/WifiViewHolder.java index 96c563cf..a5d7ef42 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/WifiViewHolder.java +++ b/app/src/main/java/com/openpositioning/PositionMe/presentation/viewitems/WifiViewHolder.java @@ -2,10 +2,8 @@ import android.view.View; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; - import com.openpositioning.PositionMe.R; /** @@ -13,23 +11,23 @@ * * @see WifiListAdapter the corresponding list adapter. * @see com.openpositioning.PositionMe.R.layout#item_wifi_card_view xml layout file - * * @author Mate Stodulka */ public class WifiViewHolder extends RecyclerView.ViewHolder { - TextView bssid; + TextView mac; + TextView ssid; TextView level; /** - * {@inheritDoc} - * Assign TextView fields corresponding to Wifi attributes. + * {@inheritDoc} Assign TextView fields corresponding to Wifi attributes. * * @see com.openpositioning.PositionMe.sensors.Wifi the data class */ public WifiViewHolder(@NonNull View itemView) { super(itemView); - bssid = itemView.findViewById(R.id.wifiNameItem); + mac = itemView.findViewById(R.id.wifiMacItem); + ssid = itemView.findViewById(R.id.wifiSsidItem); level = itemView.findViewById(R.id.wifiLevelItem); } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/sensors/BleDataProcessor.java b/app/src/main/java/com/openpositioning/PositionMe/sensors/BleDataProcessor.java new file mode 100644 index 00000000..2ab2d10c --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/sensors/BleDataProcessor.java @@ -0,0 +1,190 @@ +package com.openpositioning.PositionMe.sensors; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothManager; +import android.bluetooth.le.BluetoothLeScanner; +import android.bluetooth.le.ScanCallback; +import android.bluetooth.le.ScanResult; +import android.bluetooth.le.ScanSettings; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.ParcelUuid; +import android.util.Log; +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +/** + * BLE data gathering and processing for fingerprinting. + * + *

Scans for nearby Bluetooth Low Energy beacons and devices, collecting MAC addresses, signal + * strength, and advertised data for positioning. + * + * @author Vlad Stratulat + */ +public class BleDataProcessor implements Observable { + public static final String TAG = "BleDataProcessor"; + + // Time over which a new scan will be initiated (same as WiFi) + private static final long SCAN_INTERVAL = 5000; + + // Application context for handling permissions and BluetoothLeScanner instances + private final Context context; + // Bluetooth scanner for scanning devices via the android system + private BluetoothLeScanner bleScanner; + // List of observers to be notified when changes are detected + private ArrayList observers; + // List of nearby devices + private BleDevice[] bleData; + // Timer object + private Timer bleScanTimer; + + public BleDataProcessor(Context context) { + this.context = context; + this.observers = new ArrayList<>(); + + if (!hasPermission()) { + Log.w(TAG, "Bluetooth lacks required permissions to work!"); + return; + } + + BluetoothManager bluetoothManager = + (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); + + if (bluetoothManager == null) { + return; + } + + BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter(); + + if (bluetoothAdapter != null && bluetoothAdapter.isEnabled()) { + bleScanner = bluetoothAdapter.getBluetoothLeScanner(); + if (bleScanner != null) { + startListening(); + } + } + } + + private boolean hasPermission() { + int buildSDK = android.os.Build.VERSION.SDK_INT; + Log.d(TAG, "Checking permission for Android version " + buildSDK); + if (buildSDK >= android.os.Build.VERSION_CODES.S) { + return (context.checkSelfPermission(Manifest.permission.BLUETOOTH_SCAN) + == PackageManager.PERMISSION_GRANTED + && context.checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) + == PackageManager.PERMISSION_GRANTED); + } else { + return (context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED); + } + } + + private final ScanCallback scanCallback = + new ScanCallback() { + @Override + public void onBatchScanResults(List results) { + if (results.isEmpty() || !hasPermission()) { + return; + } + + // Process results + bleData = new BleDevice[results.size()]; + for (int i = 0; i < results.size(); i++) { + ScanResult scanResult = results.get(i); + bleData[i] = new BleDevice(); + bleData[i].setMacAddress(scanResult.getDevice().getAddress()); + bleData[i].setRssi(scanResult.getRssi()); + + if (hasPermission()) { + @SuppressLint("MissingPermission") + String name = scanResult.getDevice().getName(); + bleData[i].setName(name != null ? name : ""); + } + bleData[i].setTxPowerLevel(scanResult.getTxPower()); + + if (scanResult.getScanRecord() != null) { + List serviceUuids = + scanResult.getScanRecord().getServiceUuids(); + if (serviceUuids != null && !serviceUuids.isEmpty()) { + String[] uuids = new String[serviceUuids.size()]; + for (int j = 0; j < serviceUuids.size(); j++) { + uuids[j] = serviceUuids.get(j).toString(); + } + bleData[i].setServiceUuids(uuids); + } + + bleData[i].setManufacturerData( + scanResult.getScanRecord().getManufacturerSpecificData()); + bleData[i].setAdvertiseFlags( + scanResult.getScanRecord().getAdvertiseFlags()); + } + } + + notifyObservers(0); + } + + @Override + public void onScanFailed(int errorCode) { + // Silent failure + } + }; + + private void startBleScan() { + if (!hasPermission() || bleScanner == null) { + return; + } + + ScanSettings settings = + new ScanSettings.Builder() + .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) + .setReportDelay(SCAN_INTERVAL) + .build(); + + try { + bleScanner.startScan(null, settings, scanCallback); + } catch (SecurityException e) { + // Permission denied + } + } + + public void startListening() { + this.bleScanTimer = new Timer(); + this.bleScanTimer.schedule( + new TimerTask() { + @Override + public void run() { + startBleScan(); + } + }, + 0, + SCAN_INTERVAL); + } + + public void stopListening() { + if (bleScanTimer != null) { + bleScanTimer.cancel(); + } + if (bleScanner != null && hasPermission()) { + try { + bleScanner.stopScan(scanCallback); + } catch (SecurityException e) { + // Permission denied + } + } + } + + @Override + public void registerObserver(Observer o) { + observers.add(o); + } + + @Override + public void notifyObservers(int idx) { + for (Observer o : observers) { + o.update(bleData); + } + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/sensors/BleDevice.java b/app/src/main/java/com/openpositioning/PositionMe/sensors/BleDevice.java new file mode 100644 index 00000000..05df51ec --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/sensors/BleDevice.java @@ -0,0 +1,76 @@ +package com.openpositioning.PositionMe.sensors; + +import android.util.SparseArray; + +/** + * BLE device information class. + * + * @author Vlad Stratulat + */ +public class BleDevice { + private String macAddress; + private int rssi; + private String name; + private int txPowerLevel; + private int advertiseFlags; + private String[] serviceUuids; + private SparseArray manufacturerData; + + public BleDevice() {} + + public String getMacAddress() { + return macAddress; + } + + public int getRssi() { + return rssi; + } + + public String getName() { + return name; + } + + public int getTxPowerLevel() { + return txPowerLevel; + } + + public int getAdvertiseFlags() { + return advertiseFlags; + } + + public String[] getServiceUuids() { + return serviceUuids; + } + + public SparseArray getManufacturerData() { + return manufacturerData; + } + + public void setMacAddress(String macAddress) { + this.macAddress = macAddress; + } + + public void setRssi(int rssi) { + this.rssi = rssi; + } + + public void setName(String name) { + this.name = name; + } + + public void setTxPowerLevel(int txPowerLevel) { + this.txPowerLevel = txPowerLevel; + } + + public void setAdvertiseFlags(int advertiseFlags) { + this.advertiseFlags = advertiseFlags; + } + + public void setServiceUuids(String[] serviceUuids) { + this.serviceUuids = serviceUuids; + } + + public void setManufacturerData(SparseArray manufacturerData) { + this.manufacturerData = manufacturerData; + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/sensors/GNSSDataProcessor.java b/app/src/main/java/com/openpositioning/PositionMe/sensors/GNSSDataProcessor.java index 579e344c..1c081021 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/sensors/GNSSDataProcessor.java +++ b/app/src/main/java/com/openpositioning/PositionMe/sensors/GNSSDataProcessor.java @@ -6,14 +6,15 @@ import android.content.pm.PackageManager; import android.location.LocationListener; import android.location.LocationManager; +import android.os.Handler; +import android.os.Looper; import android.widget.Toast; - import androidx.core.app.ActivityCompat; /** * Class for handling and recording location data. * - * The class is responsibly for handling location data from GNSS and cellular sources using the + *

The class is responsibly for handling location data from GNSS and cellular sources using the * Android LocationManager class. * * @author Virginia Cangelosi @@ -27,21 +28,19 @@ public class GNSSDataProcessor { // Location listener to receive the location data broadcast by the system private LocationListener locationListener; - /** * Public default constructor of the GNSSDataProcessor class. * - * The constructor saves the context, checks for permissions to use the location services, + *

The constructor saves the context, checks for permissions to use the location services, * creates an instance of the shared preferences to access settings using the context, * initialises the location manager, and the location listener that will receive the data in the * class the called the constructor. It checks if GPS and cellular networks are available and * notifies the user via toasts if they need to be turned on. If permissions are granted it * starts the location information gathering process. * - * @param context Application Context to be used for permissions and device accesses. - * @param locationListener Location listener that will receive the location information from - * the device broadcasts. - * + * @param context Application Context to be used for permissions and device accesses. + * @param locationListener Location listener that will receive the location information from the + * device broadcasts. * @see SensorFusion the intended parent class. */ public GNSSDataProcessor(Context context, LocationListener locationListener) { @@ -50,16 +49,25 @@ public GNSSDataProcessor(Context context, LocationListener locationListener) { // Check for permissions boolean permissionsGranted = checkLocationPermissions(); - //Location manager and listener + // Location manager and listener this.locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); this.locationListener = locationListener; // Turn on gps if it is currently disabled if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { - Toast.makeText(context, "Open GPS", Toast.LENGTH_SHORT).show(); + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText(context, "Open GPS", Toast.LENGTH_SHORT).show(); + }); } if (!locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { - Toast.makeText(context, "Enable Cellular", Toast.LENGTH_SHORT).show(); + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText(context, "Enable Cellular", Toast.LENGTH_SHORT) + .show(); + }); } // Start location updates if (permissionsGranted) { @@ -70,55 +78,81 @@ public GNSSDataProcessor(Context context, LocationListener locationListener) { /** * Checks if the user authorised all permissions necessary for accessing location data. * - * Explicit user permissions must be granted for android sdk version 23 and above. This + *

Explicit user permissions must be granted for android sdk version 23 and above. This * function checks which permissions are granted, and returns their conjunction. * - * @return boolean true if all permissions are granted for location access, false otherwise. + * @return boolean true if all permissions are granted for location access, false otherwise. */ private boolean checkLocationPermissions() { - int coarseLocationPermission = ActivityCompat.checkSelfPermission(this.context, - Manifest.permission.ACCESS_COARSE_LOCATION); - int fineLocationPermission = ActivityCompat.checkSelfPermission(this.context, - Manifest.permission.ACCESS_FINE_LOCATION); - int internetPermission = ActivityCompat.checkSelfPermission(this.context, - Manifest.permission.INTERNET); + int coarseLocationPermission = + ActivityCompat.checkSelfPermission( + this.context, Manifest.permission.ACCESS_COARSE_LOCATION); + int fineLocationPermission = + ActivityCompat.checkSelfPermission( + this.context, Manifest.permission.ACCESS_FINE_LOCATION); + int internetPermission = + ActivityCompat.checkSelfPermission(this.context, Manifest.permission.INTERNET); // Return missing permissions - return coarseLocationPermission == PackageManager.PERMISSION_GRANTED && - fineLocationPermission == PackageManager.PERMISSION_GRANTED && - internetPermission == PackageManager.PERMISSION_GRANTED; + return coarseLocationPermission == PackageManager.PERMISSION_GRANTED + && fineLocationPermission == PackageManager.PERMISSION_GRANTED + && internetPermission == PackageManager.PERMISSION_GRANTED; } /** * Request location updates via the GNSS and Cellular networks. * - * The function checks for permissions again, and then requests updates via the location + *

The function checks for permissions again, and then requests updates via the location * manager to the location listener. If permissions are granted but the GPS and cellular * networks are disabled it reminds the user via toasts to turn them on. */ @SuppressLint("MissingPermission") public void startLocationUpdates() { - //if (sharedPreferences.getBoolean("location", true)) { + // if (sharedPreferences.getBoolean("location", true)) { boolean permissionGranted = checkLocationPermissions(); - if (permissionGranted && locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) && - locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){ + if (permissionGranted + && locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) + && locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { - locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener); - locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); - } - else if(permissionGranted && !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){ - Toast.makeText(context, "Open GPS", Toast.LENGTH_LONG).show(); - } - else if(permissionGranted && !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){ - Toast.makeText(context, "Turn on WiFi", Toast.LENGTH_LONG).show(); + locationManager.requestLocationUpdates( + LocationManager.GPS_PROVIDER, 0, 0, locationListener); + locationManager.requestLocationUpdates( + LocationManager.NETWORK_PROVIDER, 0, 0, locationListener); + } else if (permissionGranted + && !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText(context, "Open GPS", Toast.LENGTH_LONG).show(); + }); + } else if (permissionGranted + && !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText(context, "Turn on WiFi", Toast.LENGTH_LONG).show(); + }); } } - /** - * Stops updates to the location listener via the location manager. - */ + /** Stops updates to the location listener via the location manager. */ public void stopUpdating() { locationManager.removeUpdates(locationListener); } + /** + * Get the last known location from the location manager. + * + * @return Last known location, or null if unavailable + */ + @SuppressLint("MissingPermission") + public android.location.Location getLastLocation() { + if (checkLocationPermissions()) { + android.location.Location gpsLoc = + locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); + if (gpsLoc != null) return gpsLoc; + else return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); + } + return null; + } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/sensors/MovementSensor.java b/app/src/main/java/com/openpositioning/PositionMe/sensors/MovementSensor.java index a5282150..d19f0dd0 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/sensors/MovementSensor.java +++ b/app/src/main/java/com/openpositioning/PositionMe/sensors/MovementSensor.java @@ -7,12 +7,11 @@ /** * Movement sensor class representing all Sensor Manager based devices. * - * The class is initialised with the application context to be used for permissions and hardware + *

The class is initialised with the application context to be used for permissions and hardware * access. Using the context, it adds a Sensor Manager, as well as a Sensor and {@link SensorInfo} * instance, with the type of the sensor determined upon initialisation of the class. * * @see SensorFusion where instances of this class are intended to be used. - * * @author Mate Stodulka */ public class MovementSensor { @@ -25,15 +24,13 @@ public class MovementSensor { // Information about the sensor stored in a SensorInfo object protected SensorInfo sensorInfo; - /** * Public default constructor for the Movement Sensor class. * - * It calls the superclass constructor with context, and then initialises local properties. - * - * @param context Application context used to check permissions and access devices. - * @param sensorType Type of the sensor to be created, using Sensor.TYPE constants. + *

It calls the superclass constructor with context, and then initialises local properties. * + * @param context Application context used to check permissions and access devices. + * @param sensorType Type of the sensor to be created, using Sensor.TYPE constants. * @see SensorInfo objects holding physical sensors properties. */ public MovementSensor(Context context, int sensorType) { @@ -43,26 +40,20 @@ public MovementSensor(Context context, int sensorType) { this.sensor = sensorManager.getDefaultSensor(sensorType); if (sensor != null) { - this.sensorInfo = new SensorInfo( - sensor.getName(), - sensor.getVendor(), - sensor.getResolution(), - sensor.getPower(), - sensor.getVersion(), - sensor.getType() - ); + this.sensorInfo = + new SensorInfo( + sensor.getName(), + sensor.getVendor(), + sensor.getResolution(), + sensor.getPower(), + sensor.getVersion(), + sensor.getType(), + sensor.getMaximumRange(), + 0.0f // frequency set later + ); System.err.println(sensorInfo); } else { - this.sensorInfo = new SensorInfo( - "Not available", - "-", - -1.0f, - 0.0f, - 0, - 0 - ); - + this.sensorInfo = new SensorInfo("Not available", "-", -1.0f, 0.0f, 0, 0, 0.0f, 0.0f); } } - } diff --git a/app/src/main/java/com/openpositioning/PositionMe/sensors/Observable.java b/app/src/main/java/com/openpositioning/PositionMe/sensors/Observable.java index dc7e0c73..6292584a 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/sensors/Observable.java +++ b/app/src/main/java/com/openpositioning/PositionMe/sensors/Observable.java @@ -1,8 +1,9 @@ package com.openpositioning.PositionMe.sensors; + /** * Interface for observable class. * - * Simplified version of default Observable interface, with only the resgisterObserver and + *

Simplified version of default Observable interface, with only the resgisterObserver and * notifyObservers methods included see {@link java.util.Observable}. * * @author Virginia Cangelosi @@ -17,11 +18,10 @@ public interface Observable { public void registerObserver(com.openpositioning.PositionMe.sensors.Observer o); /** - * Notify observers of changes to relevant data structures. If there are multiple data structures - * and not all are relevant to all observers, use the input to differentiate. + * Notify observers of changes to relevant data structures. If there are multiple data + * structures and not all are relevant to all observers, use the input to differentiate. * - * @param idx int index signaling which data-structure was updated. + * @param idx int index signaling which data-structure was updated. */ public void notifyObservers(int idx); } - diff --git a/app/src/main/java/com/openpositioning/PositionMe/sensors/Observer.java b/app/src/main/java/com/openpositioning/PositionMe/sensors/Observer.java index 765b1a0b..381ea9ee 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/sensors/Observer.java +++ b/app/src/main/java/com/openpositioning/PositionMe/sensors/Observer.java @@ -3,8 +3,8 @@ /** * Interface for observers of an observable class. * - * Simplified version of default Observer interface, with only the update method included - * see {@link java.util.Observer}. + *

Simplified version of default Observer interface, with only the update method included see + * {@link java.util.Observer}. * * @author Virginia Cangelosi * @author Mate Stodulka @@ -15,7 +15,7 @@ public interface Observer { * Updates from the class implementing the {@link Observable} interface, where this instance is * registered as an observer. * - * @param objList an array of objects that were updated in the Observable + * @param objList an array of objects that were updated in the Observable */ public void update(Object[] objList); } diff --git a/app/src/main/java/com/openpositioning/PositionMe/sensors/SensorFusion.java b/app/src/main/java/com/openpositioning/PositionMe/sensors/SensorFusion.java index 6eca847c..6daf4b51 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/sensors/SensorFusion.java +++ b/app/src/main/java/com/openpositioning/PositionMe/sensors/SensorFusion.java @@ -1,5 +1,12 @@ package com.openpositioning.PositionMe.sensors; +import static com.openpositioning.PositionMe.fusion.FusionConstants.DELTA_T; +import static com.openpositioning.PositionMe.fusion.FusionConstants.MAX_STEP_LENGTH; +import static com.openpositioning.PositionMe.fusion.FusionConstants.WIFI_STD_DEV; +import static com.openpositioning.PositionMe.utils.UtilConstants.ALPHA_PRESSURE_DEFAULT; +import static com.openpositioning.PositionMe.utils.UtilConstants.BUILDING_NAME_OUTSIDE; +import static com.openpositioning.PositionMe.utils.UtilConstants.SENSOR_POLL_TIME_MS; + import android.content.Context; import android.content.SharedPreferences; import android.hardware.Sensor; @@ -9,79 +16,79 @@ import android.location.Location; import android.location.LocationListener; import android.os.Build; +import android.os.Handler; import android.os.PowerManager; import android.os.SystemClock; import android.util.Log; - import androidx.annotation.NonNull; import androidx.preference.PreferenceManager; - import com.google.android.gms.maps.model.LatLng; +import com.openpositioning.PositionMe.Traj; +import com.openpositioning.PositionMe.data.remote.ServerCommunications; +import com.openpositioning.PositionMe.fusion.Fusion; +import com.openpositioning.PositionMe.fusion.KalmanFilter; +import com.openpositioning.PositionMe.fusion.Particle; import com.openpositioning.PositionMe.presentation.activity.MainActivity; +import com.openpositioning.PositionMe.presentation.fragment.SettingsFragment; +import com.openpositioning.PositionMe.utils.Building; import com.openpositioning.PositionMe.utils.PathView; import com.openpositioning.PositionMe.utils.PdrProcessing; -import com.openpositioning.PositionMe.data.remote.ServerCommunications; -import com.openpositioning.PositionMe.Traj; -import com.openpositioning.PositionMe.presentation.fragment.SettingsFragment; - -import org.json.JSONException; -import org.json.JSONObject; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Timer; import java.util.TimerTask; import java.util.stream.Collectors; import java.util.stream.Stream; - +import org.json.JSONException; +import org.json.JSONObject; /** * The SensorFusion class is the main data gathering and processing class of the application. * - * It follows the singleton design pattern to ensure that every fragment and process has access to - * the same date and sensor instances. Hence it has a private constructor, and must be initialised - * with the application context after creation. - *

- * The class implements {@link SensorEventListener} and has instances of {@link MovementSensor} for - * every device type necessary for data collection. As such, it implements the - * {@link SensorFusion#onSensorChanged(SensorEvent)} function, and process and records the data - * provided by the sensor hardware, which are stored in a {@link Traj} object. Data is read - * continuously but is only saved to the trajectory when recording is enabled. - *

- * The class provides a number of setters and getters so that other classes can have access to the - * sensor data and influence the behaviour of data collection. + *

It follows the singleton design pattern to ensure that every fragment and process has access + * to the same date and sensor instances. Hence it has a private constructor, and must be + * initialised with the application context after creation. + * + *

The class implements {@link SensorEventListener} and has instances of {@link MovementSensor} + * for every device type necessary for data collection. As such, it implements the {@link + * SensorFusion#onSensorChanged(SensorEvent)} function, and process and records the data provided by + * the sensor hardware, which are stored in a {@link Traj} object. Data is read continuously but is + * only saved to the trajectory when recording is enabled. + * + *

The class provides a number of setters and getters so that other classes can have access to + * the sensor data and influence the behaviour of data collection. * * @author Michal Dvorak * @author Mate Stodulka * @author Virginia Cangelosi */ public class SensorFusion implements SensorEventListener, Observer { + private static final String TAG = "SensorFusion"; + private static final String WAKE_LOCK_TAG = "MyApp::MyWakelockTag"; // Store the last event timestamps for each sensor type private HashMap lastEventTimestamps = new HashMap<>(); private HashMap eventCounts = new HashMap<>(); - long maxReportLatencyNs = 0; // Disable batching to deliver events immediately + long maxReportLatencyNs = 0; // Disable batching to deliver events immediately // Define a threshold for large time gaps (in milliseconds) - private static final long LARGE_GAP_THRESHOLD_MS = 500; // Adjust this if needed + private static final long LARGE_GAP_THRESHOLD_MS = 500; // Adjust this if needed - //region Static variables // Singleton Class private static final SensorFusion sensorFusion = new SensorFusion(); // Static constant for calculations with milliseconds private static final long TIME_CONST = 10; // Coefficient for fusing gyro-based and magnetometer-based orientation public static final float FILTER_COEFFICIENT = 0.96f; - //Tuning value for low pass filter - private static final float ALPHA = 0.8f; - // String for creating WiFi fingerprint JSO N object - private static final String WIFI_FINGERPRINT= "wf"; - //endregion + // Tuning value for low pass filter + private float alphaPressure; + // String for creating WiFi fingerprint JSON object + private static final String WIFI_FINGERPRINT = "wf"; - //region Instance variables // Keep device awake while recording private PowerManager.WakeLock wakeLock; private Context appContext; @@ -103,6 +110,7 @@ public class SensorFusion implements SensorEventListener, Observer { // Other data recording private WifiDataProcessor wifiProcessor; private GNSSDataProcessor gnssProcessor; + private BleDataProcessor bleProcessor; // Data listener private final LocationListener locationListener; @@ -110,10 +118,13 @@ public class SensorFusion implements SensorEventListener, Observer { private ServerCommunications serverCommunications; // Trajectory object containing all data private Traj.Trajectory.Builder trajectory; + // Name of current building recording is associated with + // Defaults to outside (invalid for upload to server) + private String currentBuilding = BUILDING_NAME_OUTSIDE; // Settings private boolean saveRecording; - private float filter_coefficient; + // Variables to help with timed events private long absoluteStartTime; private long bootTime; @@ -123,7 +134,6 @@ public class SensorFusion implements SensorEventListener, Observer { // Counters for dividing timer to record data every 1 second/ every 5 seconds private int counter; private int secondCounter; - // Sensor values private float[] acceleration; private float[] filteredAcc; @@ -131,22 +141,32 @@ public class SensorFusion implements SensorEventListener, Observer { private float[] magneticField; private float[] angularVelocity; private float[] orientation; + private float kalmanFilterOrientation; private float[] rotation; private float pressure; private float light; private float proximity; private float[] R; - private int stepCounter ; + private int stepCounter; // Derived values private float elevation; - private boolean elevator; + private boolean isInElevator; // Location values private float latitude; private float longitude; private float[] startLocation; // Wifi values - private List wifiList; - + private List wifiList = new ArrayList<>(); + // BLE values + private List bleList; + // Track seen APs to avoid duplicates + private Map seenAPs = new HashMap<>(); + // Track last fingerprint to avoid duplicates + private long lastWifiFingerprintTime = 0; + private int lastWifiFingerprintHash = 0; + // Track last BLE fingerprint to avoid duplicates + private long lastBleFingerprintTime = 0; + private int lastBleFingerprintHash = 0; // Over time accelerometer magnitude values since last step private List accelMagnitude; @@ -158,15 +178,22 @@ public class SensorFusion implements SensorEventListener, Observer { private PathView pathView; // WiFi positioning object private WiFiPositioning wiFiPositioning; + // Fusion used for corrected positioning + public Fusion fusion; + // Kalman filter used for orientation smoothing + private KalmanFilter kalmanFilter; + // Handler used to make kalman intervals + private Handler kalmanFilterHandler; + // Runnable used to execute kalman filter methods + private Runnable kalmanFIlterRunnable; - //region Initialisation /** - * Private constructor for implementing singleton design pattern for SensorFusion. - * Initialises empty arrays and new objects that do not depends on outside information. + * Private constructor for implementing singleton design pattern for SensorFusion. Initialises + * empty arrays and new objects that do not depends on outside information. */ private SensorFusion() { // Location listener to be used by the GNSS class - this.locationListener= new myLocationListener(); + this.locationListener = new myLocationListener(); // Timer to store sensor values in the trajectory object this.storeTrajectoryTimer = new Timer(); // Counters to track elements with slower frequency @@ -176,7 +203,7 @@ private SensorFusion() { this.stepCounter = 0; // PDR elevation initial values this.elevation = 0; - this.elevator = false; + this.isInElevator = false; // PDR position array this.startLocation = new float[2]; // Empty array initialisation @@ -189,15 +216,12 @@ private SensorFusion() { this.rotation = new float[4]; this.rotation[3] = 1.0f; this.R = new float[9]; - // GNSS initial Long-Lat array - this.startLocation = new float[2]; } - /** * Static function to access singleton instance of SensorFusion. * - * @return singleton instance of SensorFusion class. + * @return singleton instance of SensorFusion class. */ public static SensorFusion getInstance() { return sensorFusion; @@ -206,21 +230,20 @@ public static SensorFusion getInstance() { /** * Initialisation function for the SensorFusion instance. * - * Initialise all Movement sensor instances from context and predetermined types. Creates a + *

Initialise all Movement sensor instances from context and predetermined types. Creates a * server communication instance for sending trajectories. Saves current absolute and relative * time, and initialises saving the recording to false. * - * @param context application context for permissions and device access. - * + * @param context application context for permissions and device access. * @see MovementSensor handling all SensorManager based data collection devices. * @see ServerCommunications handling communication with the server. * @see GNSSDataProcessor for location data processing. * @see WifiDataProcessor for network data processing. */ public void setContext(Context context) { - this.appContext = context.getApplicationContext(); // store app context for later use + this.appContext = context.getApplicationContext(); - // Initialise data collection devices (unchanged)... + // Initialise data collection devices this.accelerometerSensor = new MovementSensor(context, Sensor.TYPE_ACCELEROMETER); this.barometerSensor = new MovementSensor(context, Sensor.TYPE_PRESSURE); this.gyroscopeSensor = new MovementSensor(context, Sensor.TYPE_GYROSCOPE); @@ -230,73 +253,76 @@ public void setContext(Context context) { this.stepDetectionSensor = new MovementSensor(context, Sensor.TYPE_STEP_DETECTOR); this.rotationSensor = new MovementSensor(context, Sensor.TYPE_ROTATION_VECTOR); this.gravitySensor = new MovementSensor(context, Sensor.TYPE_GRAVITY); - this.linearAccelerationSensor = new MovementSensor(context, Sensor.TYPE_LINEAR_ACCELERATION); + this.linearAccelerationSensor = + new MovementSensor(context, Sensor.TYPE_LINEAR_ACCELERATION); // Listener based devices this.wifiProcessor = new WifiDataProcessor(context); wifiProcessor.registerObserver(this); this.gnssProcessor = new GNSSDataProcessor(context, locationListener); + this.bleProcessor = new BleDataProcessor(context); + bleProcessor.registerObserver(this); + // Create object handling HTTPS communication this.serverCommunications = new ServerCommunications(context); + // Save absolute and relative start time this.absoluteStartTime = System.currentTimeMillis(); this.bootTime = SystemClock.uptimeMillis(); + // Initialise saveRecording to false this.saveRecording = false; // Other initialisations... this.accelMagnitude = new ArrayList<>(); + this.bleList = new ArrayList<>(); this.pdrProcessing = new PdrProcessing(context); this.settings = PreferenceManager.getDefaultSharedPreferences(context); this.pathView = new PathView(context, null); this.wiFiPositioning = new WiFiPositioning(context); - if(settings.getBoolean("overwrite_constants", false)) { - this.filter_coefficient = Float.parseFloat(settings.getString("accel_filter", "0.96")); - } else { - this.filter_coefficient = FILTER_COEFFICIENT; - } + updateConstants(); + + this.fusion = new Fusion(appContext); + fusion.updateConstants(appContext); // Keep app awake during the recording (using stored appContext) - PowerManager powerManager = (PowerManager) this.appContext.getSystemService(Context.POWER_SERVICE); - wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::MyWakelockTag"); + PowerManager powerManager = + (PowerManager) this.appContext.getSystemService(Context.POWER_SERVICE); + wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG); } - //endregion + /** Update any constants used based on the user's values from the {@link SettingsFragment} */ + public void updateConstants() { + if (settings.getBoolean("overwrite_fusion_constants", false)) { + alphaPressure = + (float) settings.getInt("alpha_pressure", (int) ALPHA_PRESSURE_DEFAULT * 100) + / 100; + } else { + alphaPressure = ALPHA_PRESSURE_DEFAULT; + } + + Log.d(TAG, "Constants updated"); + Log.d(TAG, "alphaPressure: " + alphaPressure); + } - //region Sensor processing /** * {@inheritDoc} * - * Called every time a Sensor value is updated. + *

Called every time a Sensor value is updated. * - * Checks originating sensor type, if the data is meaningful save it to a local variable. + *

Checks originating sensor type, if the data is meaningful save it to a local variable. * - * @param sensorEvent SensorEvent of sensor with values changed, includes types and values. + * @param sensorEvent SensorEvent of sensor with values changed, includes types and values. */ @Override public void onSensorChanged(SensorEvent sensorEvent) { - long currentTime = System.currentTimeMillis(); // Current time in milliseconds + long currentTime = System.currentTimeMillis(); // Current time in milliseconds int sensorType = sensorEvent.sensor.getType(); - // Get the previous timestamp for this sensor type - Long lastTimestamp = lastEventTimestamps.get(sensorType); - - if (lastTimestamp != null) { - long timeGap = currentTime - lastTimestamp; - -// // Log a warning if the time gap is larger than the threshold -// if (timeGap > LARGE_GAP_THRESHOLD_MS) { -// Log.e("SensorFusion", "Large time gap detected for sensor " + sensorType + -// " | Time gap: " + timeGap + " ms"); -// } - } - // Update timestamp and frequency counter for this sensor lastEventTimestamps.put(sensorType, currentTime); eventCounts.put(sensorType, eventCounts.getOrDefault(sensorType, 0) + 1); - - switch (sensorType) { case Sensor.TYPE_ACCELEROMETER: acceleration[0] = sensorEvent.values[0]; @@ -305,11 +331,15 @@ public void onSensorChanged(SensorEvent sensorEvent) { break; case Sensor.TYPE_PRESSURE: - pressure = (1 - ALPHA) * pressure + ALPHA * sensorEvent.values[0]; + pressure = (1 - alphaPressure) * pressure + alphaPressure * sensorEvent.values[0]; if (saveRecording) { - this.elevation = pdrProcessing.updateElevation( - SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure) - ); + this.elevation = + pdrProcessing.updateElevation( + SensorManager.getAltitude( + SensorManager.PRESSURE_STANDARD_ATMOSPHERE, pressure)); + } + if (fusion.isActive()) { + fusion.onAltitudeUpdate(this.elevation); } break; @@ -317,6 +347,7 @@ public void onSensorChanged(SensorEvent sensorEvent) { angularVelocity[0] = sensorEvent.values[0]; angularVelocity[1] = sensorEvent.values[1]; angularVelocity[2] = sensorEvent.values[2]; + break; case Sensor.TYPE_LINEAR_ACCELERATION: filteredAcc[0] = sensorEvent.values[0]; @@ -324,19 +355,15 @@ public void onSensorChanged(SensorEvent sensorEvent) { filteredAcc[2] = sensorEvent.values[2]; // Compute magnitude & add to accelMagnitude - double accelMagFiltered = Math.sqrt( - Math.pow(filteredAcc[0], 2) + - Math.pow(filteredAcc[1], 2) + - Math.pow(filteredAcc[2], 2) - ); - this.accelMagnitude.add(accelMagFiltered); - -// // Debug logging -// Log.v("SensorFusion", -// "Added new linear accel magnitude: " + accelMagFiltered -// + "; accelMagnitude size = " + accelMagnitude.size()); - - elevator = pdrProcessing.estimateElevator(gravity, filteredAcc); + double accelMagFiltered = + Math.sqrt( + Math.pow(filteredAcc[0], 2) + + Math.pow(filteredAcc[1], 2) + + Math.pow(filteredAcc[2], 2)); + + // TODO - This grows without bound! Would limiting it break functionality? + accelMagnitude.add(accelMagFiltered); + isInElevator = pdrProcessing.estimateElevator(gravity, filteredAcc); break; case Sensor.TYPE_GRAVITY: @@ -344,10 +371,7 @@ public void onSensorChanged(SensorEvent sensorEvent) { gravity[1] = sensorEvent.values[1]; gravity[2] = sensorEvent.values[2]; - // Possibly log gravity values if needed - //Log.v("SensorFusion", "Gravity: " + Arrays.toString(gravity)); - - elevator = pdrProcessing.estimateElevator(gravity, filteredAcc); + isInElevator = pdrProcessing.estimateElevator(gravity, filteredAcc); break; case Sensor.TYPE_LIGHT: @@ -365,179 +389,374 @@ public void onSensorChanged(SensorEvent sensorEvent) { break; case Sensor.TYPE_ROTATION_VECTOR: - this.rotation = sensorEvent.values.clone(); - float[] rotationVectorDCM = new float[9]; - SensorManager.getRotationMatrixFromVector(rotationVectorDCM, this.rotation); - SensorManager.getOrientation(rotationVectorDCM, this.orientation); + rotation = sensorEvent.values.clone(); + SensorManager.getRotationMatrixFromVector(R, rotation); + SensorManager.getOrientation(R, orientation); break; case Sensor.TYPE_STEP_DETECTOR: long stepTime = SystemClock.uptimeMillis() - bootTime; - - if (currentTime - lastStepTime < 20) { - Log.e("SensorFusion", "Ignoring step event, too soon after last step event:" + (currentTime - lastStepTime) + " ms"); + if (currentTime - lastStepTime < SENSOR_POLL_TIME_MS) { + Log.w( + TAG, + "Ignoring step event, too soon after last step event:" + + (currentTime - lastStepTime) + + " ms"); // Ignore rapid successive step events break; - } - - else { + } else { lastStepTime = currentTime; // Log if accelMagnitude is empty if (accelMagnitude.isEmpty()) { - Log.e("SensorFusion", - "stepDetection triggered, but accelMagnitude is empty! " + - "This can cause updatePdr(...) to fail or return bad results."); + Log.e( + TAG, + "stepDetection triggered, but accelMagnitude is empty! This can" + + " cause updatePdr(...) to fail or return bad results."); } else { - Log.d("SensorFusion", - "stepDetection triggered, accelMagnitude size = " + accelMagnitude.size()); + Log.d( + TAG, + "stepDetection triggered, accelMagnitude size = " + + accelMagnitude.size()); } - float[] newCords = this.pdrProcessing.updatePdr( - stepTime, - this.accelMagnitude, - this.orientation[0] - ); - + float[] newCords = + this.pdrProcessing.updatePdr( + stepTime, this.accelMagnitude, this.orientation[0]); + + float dx = newCords[2]; + float dy = newCords[3]; + // Extract step length from PDR displacement vector and forward raw heading + // separately + // so each particle can apply its own orientation error correction in the filter + float stepLength = + (float) + Math.sqrt( + newCords[2] * newCords[2] + newCords[3] * newCords[3]); + stepLength = Math.max(stepLength, MAX_STEP_LENGTH); + if (fusion.isActive()) { + fusion.onPDRUpdate(stepLength, orientation[0], dx, dy); + } // Clear the accelMagnitude after using it + // CAUTION - This line never runs! this.accelMagnitude.clear(); - if (saveRecording) { this.pathView.drawTrajectory(newCords); stepCounter++; - trajectory.addPdrData(Traj.Pdr_Sample.newBuilder() - .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime) - .setX(newCords[0]) - .setY(newCords[1])); + trajectory.addPdrData( + Traj.RelativePosition.newBuilder() + .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime) + .setX(newCords[0]) + .setY(newCords[1])); } break; } + default: + } + } + /** + * Applies a low-pass filter to the orientation result to give smoother orientation tracking + * + * @param oldOrientation The current orientation value + * @param newOrientation The raw value of the new orientation from the phone's sensors + * @return The new orientation value to be used, after a low-pass filter has been applied + * @see SensorFusion#onSensorChanged(SensorEvent) + */ + private float applyLPFToOrientation(float oldOrientation, float newOrientation, float alpha) { + // Do not apply filter if going from positive angle to negative angle + // (Prevents orientation from glitching) + boolean bothPositive = (oldOrientation >= 0 && newOrientation >= 0); + boolean bothNegative = (oldOrientation < 0 && newOrientation < 0); + if (!bothPositive && !bothNegative) { + return newOrientation; + } else { + return (1 - alpha) * oldOrientation + alpha * newOrientation; } } /** - * Utility function to log the event frequency of each sensor. - * Call this periodically for debugging purposes. + * Getter for the estimated floor number from the {@link Fusion} class + * + * @return The floor number + * @see Fusion#getEstimatedFloorNumber() + */ + public int getEstimatedFloorNumber() { + return fusion.getEstimatedFloorNumber(); + } + + /** + * Utility function to log the event frequency of each sensor. Call this periodically for + * debugging purposes. */ public void logSensorFrequencies() { for (int sensorType : eventCounts.keySet()) { - Log.d("SensorFusion", "Sensor " + sensorType + " | Event Count: " + eventCounts.get(sensorType)); + Log.d(TAG, "Sensor " + sensorType + " | Event Count: " + eventCounts.get(sensorType)); } } /** * {@inheritDoc} * - * Location listener class to receive updates from the location manager. + *

Location listener class to receive updates from the location manager. * - * Passed to the {@link GNSSDataProcessor} to receive the location data in this class. Save the - * values in instance variables. + *

Passed to the {@link GNSSDataProcessor} to receive the location data in this class. Save + * the values in instance variables. */ - class myLocationListener implements LocationListener{ + class myLocationListener implements LocationListener { @Override public void onLocationChanged(@NonNull Location location) { - //Toast.makeText(context, "Location Changed", Toast.LENGTH_SHORT).show(); latitude = (float) location.getLatitude(); longitude = (float) location.getLongitude(); float altitude = (float) location.getAltitude(); - float accuracy = (float) location.getAccuracy(); - float speed = (float) location.getSpeed(); + float accuracy = location.getAccuracy(); + float speed = location.getSpeed(); + float bearing = location.getBearing(); String provider = location.getProvider(); - if(saveRecording) { - trajectory.addGnssData(Traj.GNSS_Sample.newBuilder() - .setAccuracy(accuracy) - .setAltitude(altitude) - .setLatitude(latitude) - .setLongitude(longitude) - .setSpeed(speed) - .setProvider(provider) - .setRelativeTimestamp(System.currentTimeMillis()-absoluteStartTime)); + + Log.d( + TAG, + "GNSS fix: lat=" + latitude + " lng=" + longitude + " acc=" + accuracy + "m"); + + // Forward the GNSS fix to the particle filter as a position observation + // Queued until the next PDR step, where it will be used to update particle weights + fusion.onGnssUpdate(new LatLng(latitude, longitude), accuracy); + + if (saveRecording) { + trajectory.addGnssData( + Traj.GNSSReading.newBuilder() + .setPosition( + Traj.GNSSPosition.newBuilder() + .setRelativeTimestamp( + System.currentTimeMillis() + - absoluteStartTime) + .setLatitude(latitude) + .setLongitude(longitude) + .setAltitude(altitude)) + .setAccuracy(accuracy) + .setSpeed(speed) + .setBearing(bearing) + .setProvider(provider)); } } } + @Override + public void update(Object[] objList) { + if (objList instanceof Wifi[]) { + updateWifi((Wifi[]) objList); + } else if (objList instanceof BleDevice[]) { + updateBle((BleDevice[]) objList); + } + } + /** * {@inheritDoc} * - * Receives updates from {@link WifiDataProcessor}. + *

Receives updates from {@link WifiDataProcessor}. * * @see WifiDataProcessor object for wifi scanning. */ - @Override - public void update(Object[] wifiList) { + private void updateWifi(Object[] wifiList) { // Save newest wifi values to local variable this.wifiList = Stream.of(wifiList).map(o -> (Wifi) o).collect(Collectors.toList()); - if(this.saveRecording) { - Traj.WiFi_Sample.Builder wifiData = Traj.WiFi_Sample.newBuilder() - .setRelativeTimestamp(SystemClock.uptimeMillis()-bootTime); + if (this.saveRecording) { + // Check for repeated fingerprints using 32 bit hash, using MAC and signal strength + int fingerprintHash = 0; for (Wifi data : this.wifiList) { - wifiData.addMacScans(Traj.Mac_Scan.newBuilder() - .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime) - .setMac(data.getBssid()).setRssi(data.getLevel())); + fingerprintHash = + 31 * fingerprintHash + (int) (data.getBssid() ^ (data.getBssid() >>> 32)); + fingerprintHash = 31 * fingerprintHash + data.getLevel(); + } + + // Skip if duplicate fingerprint within 1 second + long currentTime = System.currentTimeMillis(); + if (fingerprintHash == lastWifiFingerprintHash + && (currentTime - lastWifiFingerprintTime) < 1000) { + return; } - // Adding WiFi data to Trajectory - this.trajectory.addWifiData(wifiData); + + lastWifiFingerprintHash = fingerprintHash; + lastWifiFingerprintTime = currentTime; + + // Create Fingerprint for WiFi + Traj.Fingerprint.Builder wifiFingerprint = + Traj.Fingerprint.newBuilder() + .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime); + + for (Wifi data : this.wifiList) { + // Create RFScan for each WiFi + wifiFingerprint.addRfScans( + Traj.RFScan.newBuilder() + .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime) + .setMac(data.getBssid()) + .setRssi(data.getLevel())); + + // Add AP data only if not seen before + if (!seenAPs.containsKey(data.getBssid())) { + trajectory.addApsData( + Traj.WiFiAPData.newBuilder() + .setMac(data.getBssid()) + .setSsid(data.getSsid()) + .setFrequency(data.getFrequency()) + .setRttEnabled(data.isRttEnabled())); + seenAPs.put(data.getBssid(), true); + } + } + + // Add to trajectory + this.trajectory.addWifiFingerprints(wifiFingerprint); } - createWifiPositioningRequest(); + // Changed to createWifiPositionRequestCallback since this function was updated with + // onSuccess/onError update + createWifiPositionRequestCallback(); + } + + // Handle BLE updates + private void updateBle(BleDevice[] bleDevices) { + // Save newest BLE values to local variable + if (bleDevices != null) { + this.bleList = java.util.Arrays.asList(bleDevices); + } + + if (!saveRecording || bleDevices == null || bleDevices.length == 0) { + return; + } + + // Check for repeated BLE fingerprints using hash, using MAC and signal strength + int fingerprintHash = 0; + for (BleDevice device : bleDevices) { + long macLong = convertMacToLong(device.getMacAddress()); + fingerprintHash = 31 * fingerprintHash + (int) (macLong ^ (macLong >>> 32)); + fingerprintHash = 31 * fingerprintHash + device.getRssi(); + } + + // Skip if duplicate fingerprint within 1 second + long currentTime = System.currentTimeMillis(); + if (fingerprintHash == lastBleFingerprintHash + && (currentTime - lastBleFingerprintTime) < 1000) { + return; + } + + lastBleFingerprintHash = fingerprintHash; + lastBleFingerprintTime = currentTime; + + // Build BLE fingerprint + Traj.Fingerprint.Builder bleFingerprint = + Traj.Fingerprint.newBuilder() + .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime); + + for (BleDevice device : bleDevices) { + bleFingerprint.addRfScans( + Traj.RFScan.newBuilder() + .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime) + .setMac(convertMacToLong(device.getMacAddress())) + .setRssi(device.getRssi())); + + // Add BLE data + Traj.BleData.Builder bleData = + Traj.BleData.newBuilder() + .setMacAddress(device.getMacAddress()) + .setName(device.getName()) + .setTxPowerLevel(device.getTxPowerLevel()) + .setAdvertiseFlags(device.getAdvertiseFlags()); + + if (device.getServiceUuids() != null) { + for (String uuid : device.getServiceUuids()) { + bleData.addServiceUuids(uuid); + } + } + + // Convert first manufacturer data entry to bytes + if (device.getManufacturerData() != null && device.getManufacturerData().size() > 0) { + byte[] mfgData = device.getManufacturerData().valueAt(0); + bleData.setManufacturerData(com.google.protobuf.ByteString.copyFrom(mfgData)); + } + + trajectory.addBleData(bleData); + } + + trajectory.addBleFingerprints(bleFingerprint); } /** - * Function to create a request to obtain a wifi location for the obtained wifi fingerprint + * Helper to convert MAC string to long (ie, remove the colon separators) * + * @param macAddress The MAC address + * @return the MAC address as a long */ - private void createWifiPositioningRequest(){ - // Try catch block to catch any errors and prevent app crashing + private long convertMacToLong(String macAddress) { + String cleanMac = macAddress.replace(":", ""); + return Long.parseLong(cleanMac, 16); + } + + /** Create a request to obtain a Wi-Fi location for the obtained Wi-Fi fingerprint */ + private void createWifiPositioningRequest() { try { // Creating a JSON object to store the WiFi access points - JSONObject wifiAccessPoints=new JSONObject(); - for (Wifi data : this.wifiList){ + JSONObject wifiAccessPoints = new JSONObject(); + for (Wifi data : this.wifiList) { wifiAccessPoints.put(String.valueOf(data.getBssid()), data.getLevel()); } // Creating POST Request JSONObject wifiFingerPrint = new JSONObject(); wifiFingerPrint.put(WIFI_FINGERPRINT, wifiAccessPoints); + + Log.d(TAG, "Sending: " + wifiFingerPrint); + this.wiFiPositioning.request(wifiFingerPrint); } 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()); + Log.e(TAG, "Error creating json object" + e); } } - // Callback Example Function + /** * Function to create a request to obtain a wifi location for the obtained wifi fingerprint * using Volley Callback */ - private void createWifiPositionRequestCallback(){ + private void createWifiPositionRequestCallback() { try { // Creating a JSON object to store the WiFi access points - JSONObject wifiAccessPoints=new JSONObject(); - for (Wifi data : this.wifiList){ + JSONObject wifiAccessPoints = new JSONObject(); + for (Wifi data : wifiList) { wifiAccessPoints.put(String.valueOf(data.getBssid()), data.getLevel()); } // Creating POST Request JSONObject wifiFingerPrint = new JSONObject(); wifiFingerPrint.put(WIFI_FINGERPRINT, wifiAccessPoints); - this.wiFiPositioning.request(wifiFingerPrint, new WiFiPositioning.VolleyCallback() { - @Override - public void onSuccess(LatLng wifiLocation, int floor) { - // Handle the success response - } - @Override - public void onError(String message) { - // Handle the error response - } - }); + Log.d(TAG, "Sending: " + wifiFingerPrint); + + wiFiPositioning.request( + wifiFingerPrint, + new WiFiPositioning.VolleyCallback() { + // Logic added for onSuccess and onError cases + // Wifilocation now updates + // Sigma set to 10 as a guess for now + @Override + public void onSuccess(LatLng wifiLocation, int floor) { + Log.d( + TAG, + "WiFi position received -> lat=" + + wifiLocation.latitude + + " lon=" + + wifiLocation.longitude + + " floor=" + + floor); + + fusion.onWifiUpdate(wifiLocation, WIFI_STD_DEV, floor); + } + + @Override + public void onError(String message) { + Log.e(TAG, "WiFi positioning failed: " + message); + } + }); } 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()); + Log.e(TAG, "Error creating json object" + e); } - } /** @@ -545,15 +764,18 @@ public void onError(String message) { * * @return {@link LatLng} corresponding to user's position. */ - public LatLng getLatLngWifiPositioning(){return this.wiFiPositioning.getWifiLocation();} + public LatLng getLatLngWifiPositioning() { + return wiFiPositioning.getWifiLocation(); + } /** - * Method to get current floor the user is at, obtained using WiFiPositioning + * Method to get current floor the user is at, obtained using {@link WiFiPositioning} + * * @see WiFiPositioning for WiFi positioning * @return Current floor user is at using WiFiPositioning */ - public int getWifiFloor(){ - return this.wiFiPositioning.getFloor(); + public int getWifiFloor() { + return wiFiPositioning.getFloor(); } /** @@ -567,27 +789,45 @@ private float[] getRotationMatrixFromOrientation(float[] o) { float[] yM = new float[9]; float[] zM = new float[9]; - float sinX = (float)Math.sin(o[1]); - float cosX = (float)Math.cos(o[1]); - float sinY = (float)Math.sin(o[2]); - float cosY = (float)Math.cos(o[2]); - float sinZ = (float)Math.sin(o[0]); - float cosZ = (float)Math.cos(o[0]); + float sinX = (float) Math.sin(o[1]); + float cosX = (float) Math.cos(o[1]); + float sinY = (float) Math.sin(o[2]); + float cosY = (float) Math.cos(o[2]); + float sinZ = (float) Math.sin(o[0]); + float cosZ = (float) Math.cos(o[0]); // rotation about x-axis (pitch) - xM[0] = 1.0f; xM[1] = 0.0f; xM[2] = 0.0f; - xM[3] = 0.0f; xM[4] = cosX; xM[5] = sinX; - xM[6] = 0.0f; xM[7] = -sinX; xM[8] = cosX; + xM[0] = 1.0f; + xM[1] = 0.0f; + xM[2] = 0.0f; + xM[3] = 0.0f; + xM[4] = cosX; + xM[5] = sinX; + xM[6] = 0.0f; + xM[7] = -sinX; + xM[8] = cosX; // rotation about y-axis (roll) - yM[0] = cosY; yM[1] = 0.0f; yM[2] = sinY; - yM[3] = 0.0f; yM[4] = 1.0f; yM[5] = 0.0f; - yM[6] = -sinY; yM[7] = 0.0f; yM[8] = cosY; + yM[0] = cosY; + yM[1] = 0.0f; + yM[2] = sinY; + yM[3] = 0.0f; + yM[4] = 1.0f; + yM[5] = 0.0f; + yM[6] = -sinY; + yM[7] = 0.0f; + yM[8] = cosY; // rotation about z-axis (azimuth) - zM[0] = cosZ; zM[1] = sinZ; zM[2] = 0.0f; - zM[3] = -sinZ; zM[4] = cosZ; zM[5] = 0.0f; - zM[6] = 0.0f; zM[7] = 0.0f; zM[8] = 1.0f; + zM[0] = cosZ; + zM[1] = sinZ; + zM[2] = 0.0f; + zM[3] = -sinZ; + zM[4] = cosZ; + zM[5] = 0.0f; + zM[6] = 0.0f; + zM[7] = 0.0f; + zM[8] = 1.0f; // rotation order is y, x, z (roll, pitch, azimuth) float[] resultMatrix = matrixMultiplication(xM, yM); @@ -620,27 +860,22 @@ private float[] matrixMultiplication(float[] A, float[] B) { return result; } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ @Override public void onAccuracyChanged(Sensor sensor, int i) {} - //endregion - //region Getters/Setters /** * Getter function for core location data. * - * @param start set true to get the initial location + * @param getStartingLocation set true to get the initial location * @return longitude and latitude data in a float[2]. */ - public float[] getGNSSLatitude(boolean start) { - float [] latLong = new float[2]; - if(!start) { + public float[] getGNSSLatitude(boolean getStartingLocation) { + float[] latLong = new float[2]; + if (!getStartingLocation) { latLong[0] = latitude; latLong[1] = longitude; - } - else{ + } else { latLong = startLocation; } return latLong; @@ -649,49 +884,59 @@ public float[] getGNSSLatitude(boolean start) { /** * Setter function for core location data. * - * @param startPosition contains the initial location set by the user + * @param startPosition The starting location of the recording */ - public void setStartGNSSLatitude(float[] startPosition){ + public void setStartLocation(float[] startPosition) { startLocation = startPosition; } - /** * Function to redraw path in corrections fragment. * * @param scalingRatio new size of path due to updated step length */ - public void redrawPath(float scalingRatio){ + public void redrawPath(float scalingRatio) { pathView.redraw(scalingRatio); } /** - * Getter function for average step count. - * Calls the average step count function in pdrProcessing class + * Getter function for average step count. Calls the average step count function in {@link + * PdrProcessing} * * @return average step count of total PDR. */ - public float passAverageStepLength(){ + public float passAverageStepLength() { return pdrProcessing.getAverageStepLength(); } /** - * Getter function for device orientation. - * Passes the orientation variable + * Getter function for device orientation. Passes the orientation variable * * @return orientation of device. */ - public float passOrientation(){ - return orientation[0]; + public float getOrientation() { + if (!Float.isNaN(orientation[0])) { + return orientation[0]; + } else { + return 0.00f; + } + } + + public float getKalmanFilterOrientation() { + if (!Float.isNaN(kalmanFilterOrientation)) { + return kalmanFilterOrientation; + } else { + return 0.00f; + } } /** * Return most recent sensor readings. * - * Collects all most recent readings from movement and location sensors, packages them in a map - * that is indexed by {@link SensorTypes} and makes it accessible for other classes. + *

Collects all most recent readings from movement and location sensors, packages them in a + * map that is indexed by {@link SensorTypes} and makes it accessible for other classes. * - * @return Map of SensorTypes to float array of most recent values. + * @return Map of SensorTypes to float array of most recent values. */ public Map getSensorValueMap() { Map sensorValueMap = new HashMap<>(); @@ -699,28 +944,38 @@ public Map getSensorValueMap() { sensorValueMap.put(SensorTypes.GRAVITY, gravity); sensorValueMap.put(SensorTypes.MAGNETICFIELD, magneticField); sensorValueMap.put(SensorTypes.GYRO, angularVelocity); - sensorValueMap.put(SensorTypes.LIGHT, new float[]{light}); - sensorValueMap.put(SensorTypes.PRESSURE, new float[]{pressure}); - sensorValueMap.put(SensorTypes.PROXIMITY, new float[]{proximity}); + sensorValueMap.put(SensorTypes.LIGHT, new float[] {light}); + sensorValueMap.put(SensorTypes.PRESSURE, new float[] {pressure}); + sensorValueMap.put(SensorTypes.PROXIMITY, new float[] {proximity}); sensorValueMap.put(SensorTypes.GNSSLATLONG, getGNSSLatitude(false)); sensorValueMap.put(SensorTypes.PDR, pdrProcessing.getPDRMovement()); return sensorValueMap; } /** - * Return the most recent list of WiFi names and levels. - * Each Wifi object contains a BSSID and a level value. + * Return the most recent list of WiFi names and levels. Each Wifi object contains a BSSID and a + * level value. * - * @return list of Wifi objects. + * @return list of Wifi objects. */ public List getWifiList() { return this.wifiList; } + /** + * Return the most recent list of BLE devices. Each BleDevice object contains a MAC address, + * RSSI, name, and other BLE data. + * + * @return list of BleDevice objects. + */ + public List getBleList() { + return this.bleList; + } + /** * Get information about all the sensors registered in SensorFusion. * - * @return List of SensorInfo objects containing name, resolution, power, etc. + * @return List of SensorInfo objects containing name, resolution, power, etc. */ public List getSensorInfos() { List sensorInfoList = new ArrayList<>(); @@ -734,35 +989,36 @@ public List getSensorInfos() { } /** - * Registers the caller observer to receive updates from the server instance. - * Necessary when classes want to act on a trajectory being successfully or unsuccessfully send - * to the server. This grants access to observing the {@link ServerCommunications} instance - * used by the SensorFusion class. + * Registers the caller observer to receive updates from the server instance. Necessary when + * classes want to act on a trajectory being successfully or unsuccessfully send to the server. + * This grants access to observing the {@link ServerCommunications} instance used by the + * SensorFusion class. * - * @param observer Instance implementing {@link Observer} class who wants to be notified of - * events relating to sending and receiving trajectories. + * @param observer Instance implementing {@link Observer} class who wants to be notified of + * events relating to sending and receiving trajectories. */ public void registerForServerUpdate(Observer observer) { serverCommunications.registerObserver(observer); } /** - * Get the estimated elevation value in meters calculated by the PDR class. - * Elevation is relative to the starting position. + * Get the estimated elevation value in meters calculated by the PDR class. Elevation is + * relative to the starting position. * - * @return float of the estimated elevation in meters. + * @return float of the estimated elevation in meters. */ public float getElevation() { - return this.elevation; + return elevation; } /** - * Get an estimate by the PDR class whether it estimates the user is currently taking an elevator. + * Get an estimate by the PDR class whether it estimates the user is currently taking an + * elevator. * - * @return true if the PDR estimates the user is in an elevator, false otherwise. + * @return true if the PDR estimates the user is in an elevator, false otherwise. */ - public boolean getElevator() { - return this.elevator; + public boolean getIsInElevator() { + return isInElevator; } /** @@ -770,56 +1026,59 @@ public boolean getElevator() { * * @return int 1 if the phone is by the ear, int 0 otherwise. */ - public int getHoldMode(){ - int proximityThreshold = 1, lightThreshold = 100; //holdMode: by ear=1, not by ear =0 - if(proximitylightThreshold) { //unit cm + public int getHoldMode() { + // holdMode: by ear = 1, not by ear = 0 + int proximityThreshold = 1, lightThreshold = 100; + if (proximity < proximityThreshold && light > lightThreshold) { // unit cm return 1; - } - else{ + } else { return 0; } } - //endregion - - //region Start/Stop - /** * Registers all device listeners and enables updates with the specified sampling rate. * - * Should be called from {@link MainActivity} when resuming the application. Sampling rate is in - * microseconds, IMU needs 100Hz, rest 1Hz + *

Should be called from {@link MainActivity} when resuming the application. Sampling rate is + * in microseconds, IMU needs 100Hz, rest 1Hz * * @see MovementSensor handles SensorManager based devices. * @see WifiDataProcessor handles wifi data. * @see GNSSDataProcessor handles location data. */ public void resumeListening() { - accelerometerSensor.sensorManager.registerListener(this, accelerometerSensor.sensor, 10000, (int) maxReportLatencyNs); - accelerometerSensor.sensorManager.registerListener(this, linearAccelerationSensor.sensor, 10000, (int) maxReportLatencyNs); - accelerometerSensor.sensorManager.registerListener(this, gravitySensor.sensor, 10000, (int) maxReportLatencyNs); + accelerometerSensor.sensorManager.registerListener( + this, accelerometerSensor.sensor, 10000, (int) maxReportLatencyNs); + accelerometerSensor.sensorManager.registerListener( + this, linearAccelerationSensor.sensor, 10000, (int) maxReportLatencyNs); + accelerometerSensor.sensorManager.registerListener( + this, gravitySensor.sensor, 10000, (int) maxReportLatencyNs); barometerSensor.sensorManager.registerListener(this, barometerSensor.sensor, (int) 1e6); - gyroscopeSensor.sensorManager.registerListener(this, gyroscopeSensor.sensor, 10000, (int) maxReportLatencyNs); + gyroscopeSensor.sensorManager.registerListener( + this, gyroscopeSensor.sensor, 10000, (int) maxReportLatencyNs); lightSensor.sensorManager.registerListener(this, lightSensor.sensor, (int) 1e6); proximitySensor.sensorManager.registerListener(this, proximitySensor.sensor, (int) 1e6); - magnetometerSensor.sensorManager.registerListener(this, magnetometerSensor.sensor, 10000, (int) maxReportLatencyNs); - stepDetectionSensor.sensorManager.registerListener(this, stepDetectionSensor.sensor, SensorManager.SENSOR_DELAY_NORMAL); + magnetometerSensor.sensorManager.registerListener( + this, magnetometerSensor.sensor, 10000, (int) maxReportLatencyNs); + stepDetectionSensor.sensorManager.registerListener( + this, stepDetectionSensor.sensor, SensorManager.SENSOR_DELAY_NORMAL); rotationSensor.sensorManager.registerListener(this, rotationSensor.sensor, (int) 1e6); wifiProcessor.startListening(); gnssProcessor.startLocationUpdates(); + bleProcessor.startListening(); } /** * Un-registers all device listeners and pauses data collection. * - * Should be called from {@link MainActivity} when pausing the application. + *

Should be called from {@link MainActivity} when pausing the application. * * @see MovementSensor handles SensorManager based devices. * @see WifiDataProcessor handles wifi data. * @see GNSSDataProcessor handles location data. */ public void stopListening() { - if(!saveRecording) { + if (!saveRecording) { // Unregister sensor-manager based devices accelerometerSensor.sensorManager.unregisterListener(this); barometerSensor.sensorManager.unregisterListener(this); @@ -831,184 +1090,371 @@ public void stopListening() { rotationSensor.sensorManager.unregisterListener(this); linearAccelerationSensor.sensorManager.unregisterListener(this); gravitySensor.sensorManager.unregisterListener(this); - //The app often crashes here because the scan receiver stops after it has found the list. + // The app often crashes here because the scan receiver stops after it has found the + // list. // It will only unregister one if there is to unregister try { - this.wifiProcessor.stopListening(); //error here? + this.wifiProcessor.stopListening(); // error here? } catch (Exception e) { System.err.println("Wifi resumed before existing"); } // Stop receiving location updates this.gnssProcessor.stopUpdating(); + // Stop bluetooth processor with error catching + try { + bleProcessor.stopListening(); + } catch (Exception e) { + System.err.println("Bluetooth resumed before existing"); + } } } + /** + * Generate unique trajectory ID based on timestamp and device info Format: + * android_{device}_{timestamp} + */ + private String generateTrajectoryId() { + String deviceModel = Build.MODEL.replaceAll("\\s+", "_"); + long timestamp = System.currentTimeMillis(); + return String.format("android_%s_%d", deviceModel, timestamp); + } + /** * Enables saving sensor values to the trajectory object. * - * Sets save recording to true, resets the absolute start time and create new timer object for - * periodically writing data to trajectory. + *

Sets save recording to true, resets the absolute start time and create new timer object + * for periodically writing data to trajectory. * * @see Traj object for storing data. */ public void startRecording() { // If wakeLock is null (e.g. not initialized or was cleared), reinitialize it. if (wakeLock == null) { - PowerManager powerManager = (PowerManager) this.appContext.getSystemService(Context.POWER_SERVICE); - wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::MyWakelockTag"); + PowerManager powerManager = + (PowerManager) this.appContext.getSystemService(Context.POWER_SERVICE); + wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG); } wakeLock.acquire(31 * 60 * 1000L /*31 minutes*/); this.saveRecording = true; this.stepCounter = 0; + this.seenAPs.clear(); this.absoluteStartTime = System.currentTimeMillis(); this.bootTime = SystemClock.uptimeMillis(); // Protobuf trajectory class for sending sensor data to restful API - this.trajectory = Traj.Trajectory.newBuilder() - .setAndroidVersion(Build.VERSION.RELEASE) - .setStartTimestamp(absoluteStartTime) - .setAccelerometerInfo(createInfoBuilder(accelerometerSensor)) - .setGyroscopeInfo(createInfoBuilder(gyroscopeSensor)) - .setMagnetometerInfo(createInfoBuilder(magnetometerSensor)) - .setBarometerInfo(createInfoBuilder(barometerSensor)) - .setLightSensorInfo(createInfoBuilder(lightSensor)); - - - + this.trajectory = + Traj.Trajectory.newBuilder() + .setAndroidVersion(Build.VERSION.RELEASE) + .setStartTimestamp(absoluteStartTime) + .setAccelerometerInfo(createInfoBuilder(accelerometerSensor)) + .setGyroscopeInfo(createInfoBuilder(gyroscopeSensor)) + .setMagnetometerInfo(createInfoBuilder(magnetometerSensor)) + .setBarometerInfo(createInfoBuilder(barometerSensor)) + .setLightSensorInfo(createInfoBuilder(lightSensor)) + .setRotationVectorInfo(createInfoBuilder(rotationSensor)) + .setProximityInfo(createInfoBuilder(proximitySensor)) + .setTrajectoryVersion(2.0f) + .setTrajectoryId(generateTrajectoryId()); + + // Set initial position + if (startLocation != null && (startLocation[0] != 0 || startLocation[1] != 0)) { + trajectory.setInitialPosition( + Traj.GNSSPosition.newBuilder() + .setRelativeTimestamp(0) + .setLatitude(startLocation[0]) + .setLongitude(startLocation[1]) + .setAltitude(0)); + + // Save initial orientation + trajectory.addImuData( + Traj.IMUReading.newBuilder() + .setRelativeTimestamp(0) + .setAcc( + Traj.Vector3.newBuilder() + .setX(acceleration[0]) + .setY(acceleration[1]) + .setZ(acceleration[2])) + .setGyr( + Traj.Vector3.newBuilder() + .setX(angularVelocity[0]) + .setY(angularVelocity[1]) + .setZ(angularVelocity[2])) + .setRotationVector( + Traj.Quaternion.newBuilder() + .setX(rotation[0]) + .setY(rotation[1]) + .setZ(rotation[2]) + .setW(rotation[3])) + .setStepCount(0)); + // Start fusion predictions + fusion.start(new LatLng(startLocation[0], startLocation[1]), elevation); + } this.storeTrajectoryTimer = new Timer(); this.storeTrajectoryTimer.schedule(new storeDataInTrajectory(), 0, TIME_CONST); this.pdrProcessing.resetPDR(); - if(settings.getBoolean("overwrite_constants", false)) { - this.filter_coefficient = Float.parseFloat(settings.getString("accel_filter", "0.96")); - } else { - this.filter_coefficient = FILTER_COEFFICIENT; - } + + updateConstants(); + fusion.updateConstants(appContext); + + // Initialise kalman filter handler + kalmanFilter = new KalmanFilter(appContext); + kalmanFilter.updateConstants(appContext); + kalmanFilter.setInitialHeading(sensorFusion.getOrientation()); + this.kalmanFilterHandler = new Handler(); + // Initialise kalman filter runnable + this.kalmanFIlterRunnable = + new Runnable() { + @Override + public void run() { + // perform kalman filter prediction step with angular velocity in + // counterclockwise direction + kalmanFilter.predict(angularVelocity[2]); + kalmanFilter.measure(getOrientation()); + kalmanFilterOrientation = kalmanFilter.getMeasurement(); + // wait for kalman filter specified time delay (sampling frequency) + kalmanFilterHandler.postDelayed(this, (long) (DELTA_T * 1000)); + } + }; + kalmanFilterHandler.post(kalmanFIlterRunnable); } /** * Disables saving sensor values to the trajectory object. * - * Check if a recording is in progress. If it is, it sets save recording to false, and cancels - * the timer objects. + *

Check if a recording is in progress. If it is, it sets save recording to false, and + * cancels the timer objects. * * @see Traj object for storing data. * @see SettingsFragment navigation that might cancel recording. */ public void stopRecording() { // Only cancel if we are running - if(this.saveRecording) { + if (this.saveRecording) { this.saveRecording = false; storeTrajectoryTimer.cancel(); } - if(wakeLock.isHeld()) { + if (wakeLock.isHeld()) { this.wakeLock.release(); } + if (fusion.isActive()) { + this.fusion.stop(); + } + kalmanFilterHandler.removeCallbacks(kalmanFIlterRunnable); } - //endregion - - //region Trajectory object - /** * Send the trajectory object to servers. * * @see ServerCommunications for sending and receiving data via HTTPS. + * @return Boolean to confirm upload has completed */ - public void sendTrajectoryToCloud() { + public boolean sendTrajectoryToCloud() { // Build object Traj.Trajectory sentTrajectory = trajectory.build(); // Pass object to communications object - this.serverCommunications.sendTrajectory(sentTrajectory); + this.serverCommunications.sendTrajectory(sentTrajectory, currentBuilding); + return true; } /** - * Creates a {@link Traj.Sensor_Info} objects from the specified sensor's data. + * Creates a {@link Traj.SensorInfo} objects from the specified sensor's data. * - * @param sensor MovementSensor objects with populated sensorInfo fields - * @return Traj.SensorInfo object to be used in building the trajectory - * - * @see Traj Trajectory object used for communication with the server - * @see MovementSensor class abstracting SensorManager based sensors + * @param sensor MovementSensor objects with populated sensorInfo fields + * @return Traj.SensorInfo object to be used in building the trajectory + * @see Traj Trajectory object used for communication with the server + * @see MovementSensor class abstracting SensorManager based sensors */ - private Traj.Sensor_Info.Builder createInfoBuilder(MovementSensor sensor) { - return Traj.Sensor_Info.newBuilder() + private Traj.SensorInfo.Builder createInfoBuilder(MovementSensor sensor) { + return Traj.SensorInfo.newBuilder() .setName(sensor.sensorInfo.getName()) .setVendor(sensor.sensorInfo.getVendor()) .setResolution(sensor.sensorInfo.getResolution()) .setPower(sensor.sensorInfo.getPower()) .setVersion(sensor.sensorInfo.getVersion()) - .setType(sensor.sensorInfo.getType()); + .setType(sensor.sensorInfo.getType()) + .setMaxRange(sensor.sensorInfo.getMaxRange()) + .setFrequency(sensor.sensorInfo.getFrequency()); } /** * Timer task to record data with the desired frequency in the trajectory class. * - * Inherently threaded, runnables are created in {@link SensorFusion#startRecording()} and + *

Inherently threaded; runnables are created in {@link SensorFusion#startRecording()} and * destroyed in {@link SensorFusion#stopRecording()}. */ private class storeDataInTrajectory extends TimerTask { + public void run() { - // Store IMU and magnetometer data in Trajectory class - trajectory.addImuData(Traj.Motion_Sample.newBuilder() - .setRelativeTimestamp(SystemClock.uptimeMillis()-bootTime) - .setAccX(acceleration[0]) - .setAccY(acceleration[1]) - .setAccZ(acceleration[2]) - .setGyrX(angularVelocity[0]) - .setGyrY(angularVelocity[1]) - .setGyrZ(angularVelocity[2]) - .setGyrZ(angularVelocity[2]) - .setRotationVectorX(rotation[0]) - .setRotationVectorY(rotation[1]) - .setRotationVectorZ(rotation[2]) - .setRotationVectorW(rotation[3]) - .setStepCount(stepCounter)) - .addPositionData(Traj.Position_Sample.newBuilder() - .setMagX(magneticField[0]) - .setMagY(magneticField[1]) - .setMagZ(magneticField[2]) - .setRelativeTimestamp(SystemClock.uptimeMillis()-bootTime)) -// .addGnssData(Traj.GNSS_Sample.newBuilder() -// .setLatitude(latitude) -// .setLongitude(longitude) -// .setRelativeTimestamp(SystemClock.uptimeMillis()-bootTime)) - ; + // Store IMU data in Trajectory class + trajectory.addImuData( + Traj.IMUReading.newBuilder() + .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime) + .setAcc( + Traj.Vector3.newBuilder() + .setX(acceleration[0]) + .setY(acceleration[1]) + .setZ(acceleration[2])) + .setGyr( + Traj.Vector3.newBuilder() + .setX(angularVelocity[0]) + .setY(angularVelocity[1]) + .setZ(angularVelocity[2])) + .setRotationVector( + Traj.Quaternion.newBuilder() + .setX(rotation[0]) + .setY(rotation[1]) + .setZ(rotation[2]) + .setW(rotation[3])) + .setStepCount(stepCounter)); + + // Store magnetometer data in Trajectory class + trajectory.addMagnetometerData( + Traj.MagnetometerReading.newBuilder() + .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime) + .setMag( + Traj.Vector3.newBuilder() + .setX(magneticField[0]) + .setY(magneticField[1]) + .setZ(magneticField[2]))); // Divide timer with a counter for storing data every 1 second - if (counter == 99) { + if (counter < 99) { + counter++; + } else { counter = 0; + if (fusion != null && fusion.isActive()) { + LatLng fused = fusion.getBestEstimate(); + if (fused != null) { + // Store corrected position + Traj.GNSSPosition.Builder builder = + Traj.GNSSPosition.newBuilder() + .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime) + .setLatitude(fused.latitude) + .setLongitude(fused.longitude) + .setAltitude(fusion.getElevation()); + if (!getCurrentBuilding().equals(BUILDING_NAME_OUTSIDE)) { + builder = builder.setFloor(fusion.getEstimatedFloorName()); + } + trajectory.addCorrectedPositions(builder); + } + } + // Store pressure and light data if (barometerSensor.sensor != null) { - trajectory.addPressureData(Traj.Pressure_Sample.newBuilder() - .setPressure(pressure) - .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime)) - .addLightData(Traj.Light_Sample.newBuilder() - .setLight(light) - .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime) - .build()); + trajectory + .addPressureData( + Traj.BarometerReading.newBuilder() + .setPressure(pressure) + .setRelativeTimestamp( + SystemClock.uptimeMillis() - bootTime)) + .addLightData( + Traj.LightReading.newBuilder() + .setLight(light) + .setRelativeTimestamp( + SystemClock.uptimeMillis() - bootTime)) + .addProximityData( + Traj.ProximityReading.newBuilder() + .setRelativeTimestamp( + SystemClock.uptimeMillis() - bootTime) + .setDistance(proximity)); } // Divide the timer for storing AP data every 5 seconds - if (secondCounter == 4) { + if (secondCounter < 4) { + secondCounter++; + } else { secondCounter = 0; - //Current Wifi Object + // Current Wifi Object Wifi currentWifi = wifiProcessor.getCurrentWifiData(); - trajectory.addApsData(Traj.AP_Data.newBuilder() - .setMac(currentWifi.getBssid()) - .setSsid(currentWifi.getSsid()) - .setFrequency(currentWifi.getFrequency())); - } - else { - secondCounter++; + trajectory.addApsData( + Traj.WiFiAPData.newBuilder() + .setMac(currentWifi.getBssid()) + .setSsid(currentWifi.getSsid()) + .setFrequency(currentWifi.getFrequency()) + .setRttEnabled(currentWifi.isRttEnabled())); + seenAPs.put(currentWifi.getBssid(), true); } } - else { - counter++; - } + } + } + /** + * TODO - JavaDoc + * + * @return ??? + */ + public double getGNSSAltitude() { + if (gnssProcessor != null && gnssProcessor.getLastLocation() != null) { + return gnssProcessor.getLastLocation().getAltitude(); } + return 0.0; } - //endregion + /** + * TODO - JavaDoc + * + * @param latitude ??? + * @param longitude ??? + * @param altitude ??? + */ + public void addTestPoint(double latitude, double longitude, double altitude) { + if (saveRecording && trajectory != null) { + trajectory.addTestPoints( + Traj.GNSSPosition.newBuilder() + .setRelativeTimestamp(SystemClock.uptimeMillis() - bootTime) + .setLatitude(latitude) + .setLongitude(longitude) + .setAltitude(altitude)); + } + } + /** + * Provides building geometry to the fusion system for map-matching constraints. + * + *

Call this when a building's floor plans have been loaded and the user is inside the + * building. If fusion is not yet active, the building is ignored — call again after recording + * starts. + * + * @param building the {@link Building} whose geometry should constrain the particle filter. + */ + public void onBuildingAvailable(Building building) { + if (fusion != null && fusion.isActive()) { + fusion.setBuilding(building); + } + } + + public long getRecordingElapsedMs() { + return SystemClock.uptimeMillis() - bootTime; + } + + public void requestFloorPlans(LatLng position) { + this.serverCommunications.requestFloorplans(position, this.wifiList); + } + + public void setCurrentBuilding(String currentBuilding) { + if (!Objects.equals(this.currentBuilding, currentBuilding)) { + this.currentBuilding = currentBuilding; + Log.i(TAG, "Route now associated with " + this.currentBuilding); + } + } + + public String getCurrentBuilding() { + return currentBuilding; + } + + public LatLng getFusionEstimate() { + return fusion.getBestEstimate(); + } + + public List getFusionParticles() { + return fusion.getParticles(); + } + + public LatLng convertENToLatLng(double[] en) { + return fusion.convertENToLatLng(en); + } + + public double getOrientationError() { + return fusion.getOrientationError(); + } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/sensors/SensorInfo.java b/app/src/main/java/com/openpositioning/PositionMe/sensors/SensorInfo.java index 23b92848..6bd1b1cb 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/sensors/SensorInfo.java +++ b/app/src/main/java/com/openpositioning/PositionMe/sensors/SensorInfo.java @@ -5,7 +5,7 @@ /** * The Sensor Info object holds physical properties of a sensor in the device. * - * It contains it's name, vendor, resolution, power, version and type, which vary across devices. + *

It contains it's name, vendor, resolution, power, version and type, which vary across devices. * * @author Virginia Cangelosi * @author Mate Stodulka @@ -17,30 +17,41 @@ public class SensorInfo { private final float power; private final int version; private final int type; + private final float maxRange; + private final float frequency; /** * Public default constructor of the Sensor Info object. * - * Should be initialised with all its parameters, typically from {@link MovementSensor}. + *

Should be initialised with all its parameters, typically from {@link MovementSensor}. * - * @param name name string of the sensor. Unique for a particular sensor type. - * @param vendor vendor string of this sensor. - * @param resolution resolution of the sensor in the sensor's unit. - * @param power the power in mA used by this sensor while in use. - * @param version version of the sensor's module. - * @param type generic type of this sensor. + * @param name name string of the sensor. Unique for a particular sensor type. + * @param vendor vendor string of this sensor. + * @param resolution resolution of the sensor in the sensor's unit. + * @param power the power in mA used by this sensor while in use. + * @param version version of the sensor's module. + * @param type generic type of this sensor. */ - public SensorInfo(String name, String vendor, float resolution, float power, int version, int type) { + public SensorInfo( + String name, + String vendor, + float resolution, + float power, + int version, + int type, + float maxRange, + float frequency) { this.name = name; this.vendor = vendor; this.resolution = resolution; this.power = power; this.version = version; this.type = type; + this.maxRange = maxRange; + this.frequency = frequency; } - - //region Getters + // region Getters public String getName() { return name; @@ -66,22 +77,35 @@ public int getType() { return type; } - //endregion + public float getMaxRange() { + return maxRange; + } - /** - * {@inheritDoc} - * Basic string representation for debug - */ + public float getFrequency() { + return frequency; + } + + // endregion + + /** {@inheritDoc} Basic string representation for debug */ @NonNull @Override public String toString() { - return "SensorInfo{" + - "name='" + name + '\'' + - ", vendor='" + vendor + '\'' + - ", resolution=" + resolution + - ", power=" + power + - ", version=" + version + - ", type=" + type + - '}'; + return "SensorInfo{" + + "name='" + + name + + '\'' + + ", vendor='" + + vendor + + '\'' + + ", resolution=" + + resolution + + ", power=" + + power + + ", version=" + + version + + ", type=" + + type + + '}'; } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/sensors/SensorTypes.java b/app/src/main/java/com/openpositioning/PositionMe/sensors/SensorTypes.java index ee3bbcc1..f77afe74 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/sensors/SensorTypes.java +++ b/app/src/main/java/com/openpositioning/PositionMe/sensors/SensorTypes.java @@ -5,9 +5,9 @@ /** * Enum of the sensor types. * - * Simplified version of default Android Sensor.TYPE, with the order matching the table layout for - * the {@link MeasurementsFragment}. Includes virtual sensors and other - * data providing devices as well as derived data. + *

Simplified version of default Android Sensor.TYPE, with the order matching the table layout + * for the {@link MeasurementsFragment}. Includes virtual sensors and other data providing devices + * as well as derived data. * * @author Mate Stodulka */ diff --git a/app/src/main/java/com/openpositioning/PositionMe/sensors/WiFiPositioning.java b/app/src/main/java/com/openpositioning/PositionMe/sensors/WiFiPositioning.java index dbf809dd..7b08f259 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/sensors/WiFiPositioning.java +++ b/app/src/main/java/com/openpositioning/PositionMe/sensors/WiFiPositioning.java @@ -1,181 +1,224 @@ package com.openpositioning.PositionMe.sensors; + +import static com.openpositioning.PositionMe.utils.UtilConstants.API_POST_WIFI_FINE; +import static com.openpositioning.PositionMe.utils.UtilConstants.URL_API; + import android.content.Context; import android.util.Log; - import com.android.volley.Request; 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 java.nio.charset.StandardCharsets; import org.json.JSONException; import org.json.JSONObject; + /** - * Class for creating and handling POST requests for obtaining the current position using - * WiFi positioning API from https://openpositioning.org/api/position/fine - * * The class creates POST requests based on WiFi fingerprints and obtains the user's location * - * The request are handled asynchronously, The WiFi position coordinates and floor are updated - * when the response of the POST request is obtained. + *

The request are handled asynchronously using using {@link + * WiFiPositioning#request(JSONObject)}. The WiFi position coordinates and floor are updated when + * the response of the POST request is obtained. + * + *

com.openpositioning.PositionMe.data.remote.ServerCommunications ServerCommunications} for API + * calls * - * One can create a POST request using the function provided in the class (createPostRequest()) with - * the WiFi fingerprint - * Its then added to the RequestQueue to be handled asynchronously (not blocking the main thread) - * When the response to the request is obtained the wifiLocation and floor are updated. - * Calling the getters for wifiLocation and the floor allows obtaining the WiFi location and floor - * from the POST request response. * @author Arun Gopalakrishnan */ public class WiFiPositioning { + private static final String TAG = "WiFiPositioning"; // Queue for storing the POST requests made private RequestQueue requestQueue; - // URL for WiFi positioning API - private static final String url="https://openpositioning.org/api/position/fine"; - - /** - * Getter for the WiFi positioning coordinates obtained using openpositioning API - * @return the user's coordinates based on openpositioning API - */ - public LatLng getWifiLocation() { - return wifiLocation; - } + // URL for Wi-Fi positioning API + private static final String URL_FINE = URL_API + API_POST_WIFI_FINE; // Store user's location obtained using WiFi positioning private LatLng wifiLocation; - /** - * Getter for the WiFi positioning floor obtained using openpositioning API - * @return the user's location based on openpositioning API - */ - public int getFloor() { - return floor; - } // Store current floor of user, default value 0 (ground floor) - private int floor=0; - + private int floor = 0; /** * Constructor to create the WiFi positioning object * - * Initialising a request queue to handle the POST requests asynchronously + *

Initialising a request queue to handle the POST requests asynchronously * * @param context Context of object calling */ - public WiFiPositioning(Context context){ + public WiFiPositioning(Context context) { // Initialising the Request queue this.requestQueue = Volley.newRequestQueue(context.getApplicationContext()); } /** - * Creates a POST request using the WiFi fingerprint to obtain user's location - * The POST request is issued to https://openpositioning.org/api/position/fine - * (the openpositioning API) with the WiFI fingerprint passed as the parameter. + * Getter for the WiFi positioning coordinates obtained using OpenPositioning API * - * The response of the post request returns the coordinates of the WiFi position - * along with the floor of the building the user is at. + * @return the user's coordinates based on OpenPositioning API + */ + public LatLng getWifiLocation() { + return wifiLocation; + } + + /** + * Getter for the WiFi positioning floor obtained using OpenPositioning API + * + * @return the user's location based on OpenPositioning API + */ + public int getFloor() { + return floor; + } + + /** + * Creates a POST request using the WiFi fingerprint to obtain user's location. The POST request + * is issued to the OpenPositioning API with the Wi-Fi fingerprint passed as the parameter. * - * A try and catch block along with error Logs have been added to keep a record of error's - * obtained while handling POST requests (for better maintainability and secure programming) + *

The response of the post request returns the coordinates of the Wi-Fi position along with + * the floor of the building the user is at though a callback. * - * @param jsonWifiFeatures WiFi Fingerprint from device + * @param jsonWifiFeatures Wi-Fi Fingerprint from device */ public void request(JSONObject jsonWifiFeatures) { // Creating the POST request using WiFi fingerprint (a JSON object) - JsonObjectRequest jsonObjectRequest = new JsonObjectRequest( - Request.Method.POST, url, jsonWifiFeatures, - // Parses the response to obtain the WiFi location and WiFi floor - response -> { - try { - wifiLocation = new LatLng(response.getDouble("lat"),response.getDouble("lon")); - floor = 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); - } - }, - // 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()); - } - } - } - ); + JsonObjectRequest jsonObjectRequest = + new JsonObjectRequest( + Request.Method.POST, + URL_FINE, + jsonWifiFeatures, + // Parses the response to obtain the WiFi location and WiFi floor + response -> { + try { + wifiLocation = + new LatLng( + response.getDouble("lat"), + response.getDouble("lon")); + floor = response.getInt("floor"); + } catch (JSONException e) { + Log.e( + TAG, + "Error parsing response: " + + e.getMessage() + + " " + + response); + } + }, + error -> { + if (error.networkResponse != null) { + + int statusCode = error.networkResponse.statusCode; + String responseBody = ""; + + try { + if (error.networkResponse.data != null) { + responseBody = + new String( + error.networkResponse.data, + StandardCharsets.UTF_8); + } + } catch (Exception e) { + Log.e(TAG, "Error reading response body: " + e.getMessage()); + } + try { + JSONObject jsonObject = new JSONObject(responseBody); + String errorCause = + jsonObject.optString("detail", "Unknown cause"); + String errorBody = "[HTTP " + statusCode + "] " + errorCause; + Log.e(TAG, errorBody); + } catch (JSONException e) { + Log.w(TAG, "Unable to parse error response"); + } + } else { + String errorBody = "Network error: " + error.getMessage(); + Log.e(TAG, errorBody); + } + }); // Adds the request to the request queue requestQueue.add(jsonObjectRequest); } - /** - * Creates a POST request using the WiFi fingerprint to obtain user's location - * The POST request is issued to https://openpositioning.org/api/position/fine - * (the openpositioning API) with the WiFI fingerprint passed as the parameter. - * - * The response of the post request returns the coordinates of the WiFi position - * along with the floor of the building the user is at though a callback. + * Creates a POST request using the WiFi fingerprint to obtain user's location. The POST request + * is issued to the OpenPositioning API with the Wi-Fi fingerprint passed as the parameter. * - * A try and catch block along with error Logs have been added to keep a record of error's - * obtained while handling POST requests (for better maintainability and secure programming) + *

The response of the post request returns the coordinates of the Wi-Fi position along with + * the floor of the building the user is at though a callback. * - * @param jsonWifiFeatures WiFi Fingerprint from device - * @param callback callback function to allow user to use location when ready + * @param jsonWifiFeatures Wi-Fi Fingerprint from device + * @param callback callback to allow use of location when ready */ - public void request( JSONObject jsonWifiFeatures, final VolleyCallback callback) { + public void request(JSONObject jsonWifiFeatures, VolleyCallback callback) { + // Creating the POST request using WiFi fingerprint (a JSON object) - JsonObjectRequest jsonObjectRequest = new JsonObjectRequest( - Request.Method.POST, url, jsonWifiFeatures, - response -> { - try { - Log.d("jsonObject",response.toString()); - wifiLocation = new LatLng(response.getDouble("lat"),response.getDouble("lon")); - floor = response.getInt("floor"); - callback.onSuccess(wifiLocation,floor); - } catch (JSONException e) { - Log.e("jsonErrors","Error parsing response: "+e.getMessage()+" "+ response); - callback.onError("Error parsing response: " + e.getMessage()); - } - }, - error -> { - // Validation Error - if (error.networkResponse!=null && error.networkResponse.statusCode==422){ - Log.e("WiFiPositioning", "Validation Error "+ error.getMessage()); - callback.onError( "Validation Error (422): "+ error.getMessage()); - } - // Other Errors - else{ - // When Response code is available - if (error.networkResponse!=null) { - Log.e("WiFiPositioning","Response Code: " + error.networkResponse.statusCode + ", " + error.getMessage()); - callback.onError("Response Code: " + error.networkResponse.statusCode + ", " + error.getMessage()); - } - else{ - Log.e("WiFiPositioning","Error message: " + error.getMessage()); - callback.onError("Error message: " + error.getMessage()); - } - } - } - ); + JsonObjectRequest jsonObjectRequest = + new JsonObjectRequest( + Request.Method.POST, + URL_FINE, + jsonWifiFeatures, + response -> { + try { + Log.d(TAG, "Response: " + response.toString()); + + wifiLocation = + new LatLng( + response.getDouble("lat"), + response.getDouble("lon")); + + floor = response.getInt("floor"); + callback.onSuccess(wifiLocation, floor); + + } catch (JSONException e) { + String errorMessage = + "Error parsing response: " + + e.getMessage() + + " (" + + response + + ")"; + Log.e(TAG, errorMessage); + callback.onError(errorMessage); + } + }, + error -> { + if (error.networkResponse != null) { + + int statusCode = error.networkResponse.statusCode; + String responseBody = ""; + + try { + if (error.networkResponse.data != null) { + responseBody = + new String( + error.networkResponse.data, + StandardCharsets.UTF_8); + } + } catch (Exception e) { + Log.e(TAG, "Error reading response body: " + e.getMessage()); + } + try { + JSONObject jsonObject = new JSONObject(responseBody); + String errorCause = + jsonObject.optString("detail", "Unknown cause"); + String errorBody = "[HTTP " + statusCode + "] " + errorCause; + Log.e(TAG, errorBody); + callback.onError(errorBody); + } catch (JSONException e) { + Log.w(TAG, "Unable to parse error response"); + callback.onError(error.getMessage()); + } + } else { + String errorBody = "Network error: " + error.getMessage(); + Log.e(TAG, errorBody); + callback.onError(errorBody); + } + }); + // Adds the request to the request queue requestQueue.add(jsonObjectRequest); } - /** - * Interface defined for the callback to access response obtained after POST request - */ + /** Interface defined for the callback to access response obtained after POST request */ public interface VolleyCallback { void onSuccess(LatLng location, int floor); + void onError(String message); } - -} \ No newline at end of file +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/sensors/Wifi.java b/app/src/main/java/com/openpositioning/PositionMe/sensors/Wifi.java index d2e981cb..c54f5a6f 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/sensors/Wifi.java +++ b/app/src/main/java/com/openpositioning/PositionMe/sensors/Wifi.java @@ -5,7 +5,7 @@ /** * The Wifi object holds the Wifi parameters listed below. * - * It contains the ssid (the identifier of the wifi), bssid (the mac address of the wifi), level + *

It contains the ssid (the identifier of the wifi), bssid (the mac address of the wifi), level * (the strength of the wifi in dB) and frequency (the frequency of the wifi network (2.4GHz or * 5GHz). For most objects only the bssid and the level are set. * @@ -17,36 +17,60 @@ public class Wifi { private long bssid; private int level; private long frequency; + private boolean rttEnabled; - /** - * Empty public default constructor of the Wifi object. - */ - public Wifi(){} + /** Empty public default constructor of the Wifi object. */ + public Wifi() {} - /** - * Getters for each property - */ - public String getSsid() { return ssid; } - public long getBssid() { return bssid; } - public int getLevel() { return level; } - public long getFrequency() { return frequency; } + /** Getters for each property */ + public String getSsid() { + return ssid; + } - /** - * Setters for each property - */ - public void setSsid(String ssid) { this.ssid = ssid; } - public void setBssid(long bssid) { this.bssid = bssid; } - public void setLevel(int level) { this.level = level; } - public void setFrequency(long frequency) { this.frequency = frequency; } + public long getBssid() { + return bssid; + } + + public int getLevel() { + return level; + } + + public long getFrequency() { + return frequency; + } + + public boolean isRttEnabled() { + return rttEnabled; + } + + /** Setters for each property */ + public void setSsid(String ssid) { + this.ssid = ssid; + } + + public void setBssid(long bssid) { + this.bssid = bssid; + } + + public void setLevel(int level) { + this.level = level; + } + + public void setFrequency(long frequency) { + this.frequency = frequency; + } + + public void setRttEnabled(boolean rttEnabled) { + this.rttEnabled = rttEnabled; + } /** * Generates a string containing mac address and rssi of Wifi. * - * Concatenates mac address and rssi to display in the - * {@link MeasurementsFragment} fragment + *

Concatenates mac address and rssi to display in the {@link MeasurementsFragment} fragment */ @Override public String toString() { - return "bssid: " + bssid +", level: " + level; + return "bssid: " + bssid + ", level: " + level; } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/sensors/WifiDataProcessor.java b/app/src/main/java/com/openpositioning/PositionMe/sensors/WifiDataProcessor.java index fa8a17dd..3ebe6411 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/sensors/WifiDataProcessor.java +++ b/app/src/main/java/com/openpositioning/PositionMe/sensors/WifiDataProcessor.java @@ -10,37 +10,38 @@ import android.net.NetworkInfo; import android.net.wifi.ScanResult; import android.net.wifi.WifiManager; +import android.os.Handler; +import android.os.Looper; import android.provider.Settings; import android.widget.Toast; - import androidx.core.app.ActivityCompat; - import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; + /** * The WifiDataProcessor class is the Wi-Fi data gathering and processing class of the application. * It implements the wifi scanning and broadcasting design to identify a list of nearby Wi-Fis as * well as collecting information about the current Wi-Fi connection. - *

- * The class implements {@link Observable} for informing {@link Observer} classes of updated - * variables. As such, it implements the {@link WifiDataProcessor#notifyObservers(int idx)} function and - * the {@link WifiDataProcessor#registerObserver(Observer o)} function to add new users which will - * be notified of new changes. - *

- * The class ensures all required permissions are granted before enabling the Wi-Fi. The class will - * periodically start a wifi scan as determined by {@link SensorFusion}. When a broadcast is - * received it will collect a list of users and notify users. The - * {@link WifiDataProcessor#getCurrentWifiData()} function will return information about the current - * Wi-Fi when called by {@link SensorFusion}. + * + *

The class implements {@link Observable} for informing {@link Observer} classes of updated + * variables. As such, it implements the {@link WifiDataProcessor#notifyObservers(int idx)} function + * and the {@link WifiDataProcessor#registerObserver(Observer o)} function to add new users which + * will be notified of new changes. + * + *

The class ensures all required permissions are granted before enabling the Wi-Fi. The class + * will periodically start a wifi scan as determined by {@link SensorFusion}. When a broadcast is + * received it will collect a list of users and notify users. The {@link + * WifiDataProcessor#getCurrentWifiData()} function will return information about the current Wi-Fi + * when called by {@link SensorFusion}. * * @author Mate Stodulka * @author Virginia Cangelosi */ public class WifiDataProcessor implements Observable { - //Time over which a new scan will be initiated + // Time over which a new scan will be initiated private static final long scanInterval = 5000; // Application context for handling permissions and WifiManager instances @@ -48,27 +49,24 @@ public class WifiDataProcessor implements Observable { // Locations manager to enable access to Wifi data via the android system private final WifiManager wifiManager; - //List of nearby networks + // List of nearby networks private Wifi[] wifiData; - //List of observers to be notified when changes are detected + // List of observers to be notified when changes are detected private ArrayList observers; // Timer object private Timer scanWifiDataTimer; /** - * Public default constructor of the WifiDataProcessor class. - * The constructor saves the context, checks for permissions to use the location services, - * creates an instance of the shared preferences to access settings using the context, - * initialises the wifi manager, and creates a timer object and list of observers. It checks if - * wifi is enabled and enables wifi scans every 5seconds. It also informs the user to disable - * wifi throttling if the device implements it. - * - * @param context Application Context to be used for permissions and device accesses. + * Public default constructor of the WifiDataProcessor class. The constructor saves the context, + * checks for permissions to use the location services, creates an instance of the shared + * preferences to access settings using the context, initialises the wifi manager, and creates a + * timer object and list of observers. It checks if wifi is enabled and enables wifi scans every + * 5seconds. It also informs the user to disable wifi throttling if the device implements it. * + * @param context Application Context to be used for permissions and device accesses. * @see SensorFusion the intended parent class. - * * @author Virginia Cangelosi * @author Mate Stodulka */ @@ -83,146 +81,160 @@ public WifiDataProcessor(Context context) { // Decreapted method after API 29 // Turn on wifi if it is currently disabled // TODO - turn it to a notification toward user -// // if(permissionsGranted && wifiManager.getWifiState()== WifiManager.WIFI_STATE_DISABLED) { -// // wifiManager.setWifiEnabled(true); -// // } + // // if(permissionsGranted && wifiManager.getWifiState()== + // WifiManager.WIFI_STATE_DISABLED) { + // // wifiManager.setWifiEnabled(true); + // // } // Start wifi scan and return results via broadcast - if(permissionsGranted) { + if (permissionsGranted) { this.scanWifiDataTimer.schedule(new scheduledWifiScan(), 0, scanInterval); } - //Inform the user if wifi throttling is enabled on their device + // Inform the user if wifi throttling is enabled on their device checkWifiThrottling(); } /** - * Broadcast receiver to receive updates from the wifi manager. - * Receives updates when a wifi scan is complete. Observers are notified when the broadcast is - * received to update the list of wifis + * Broadcast receiver to receive updates from the wifi manager. Receives updates when a wifi + * scan is complete. Observers are notified when the broadcast is received to update the list of + * wifis */ - BroadcastReceiver wifiScanReceiver = new BroadcastReceiver() { - /** - * Updates the list of nearby wifis when the broadcast is received. - * Ensures wifi scans are not enabled if permissions are not granted. The list of wifis is - * then passed to store the Mac Address and strength and observers of the WifiDataProcessor - * class are notified of the updated wifi list. - * - * - * @param context Application Context to be used for permissions and device accesses. - * @param intent ???. - */ - @Override - public void onReceive(Context context, Intent intent) { - - if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - // Unregister this listener - stopListening(); - return; - } - - //Collect the list of nearby wifis - List wifiScanList = wifiManager.getScanResults(); - //Stop receiver as scan is complete - context.unregisterReceiver(this); - - //Loop though each item in wifi list - wifiData = new Wifi[wifiScanList.size()]; - for(int i = 0; i < wifiScanList.size(); i++) { - wifiData[i] = new Wifi(); - //Convert String mac address to an integer - String wifiMacAddress = wifiScanList.get(i).BSSID; - long intMacAddress = convertBssidToLong(wifiMacAddress); - //store mac address and rssi of wifi - wifiData[i].setBssid(intMacAddress); - wifiData[i].setLevel(wifiScanList.get(i).level); - } - - //Notify observers of change in wifiData variable - notifyObservers(0); - } - }; + BroadcastReceiver wifiScanReceiver = + new BroadcastReceiver() { + /** + * Updates the list of nearby wifis when the broadcast is received. Ensures wifi + * scans are not enabled if permissions are not granted. The list of wifis is then + * passed to store the Mac Address and strength and observers of the + * WifiDataProcessor class are notified of the updated wifi list. + * + * @param context Application Context to be used for permissions and device + * accesses. + * @param intent ???. + */ + @Override + public void onReceive(Context context, Intent intent) { + + if (ActivityCompat.checkSelfPermission( + context, Manifest.permission.ACCESS_FINE_LOCATION) + != PackageManager.PERMISSION_GRANTED) { + // Unregister this listener + stopListening(); + return; + } + + // Collect the list of nearby wifis + List wifiScanList = wifiManager.getScanResults(); + // Stop receiver as scan is complete + context.unregisterReceiver(this); + + // Loop though each item in wifi list + wifiData = new Wifi[wifiScanList.size()]; + for (int i = 0; i < wifiScanList.size(); i++) { + wifiData[i] = new Wifi(); + // Convert String mac address to an integer + String wifiMacAddress = wifiScanList.get(i).BSSID; + long intMacAddress = convertBssidToLong(wifiMacAddress); + // store mac address and rssi of wifi + wifiData[i].setBssid(intMacAddress); + wifiData[i].setLevel(wifiScanList.get(i).level); + wifiData[i].setSsid(wifiScanList.get(i).SSID); + wifiData[i].setFrequency(wifiScanList.get(i).frequency); + wifiData[i].setRttEnabled(wifiScanList.get(i).is80211mcResponder()); + } + + // Notify observers of change in wifiData variable + notifyObservers(0); + } + }; /** - * Converts mac address from string to integer. - * Removes semicolons from mac address and converts each hex byte to a hex integer. + * Converts mac address from string to integer. Removes semicolons from mac address and converts + * each hex byte to a hex integer. * - * - * @param wifiMacAddress String Mac Address received from WifiManager containing colons - * - * @return Long variable with decimal conversion of the mac address + * @param wifiMacAddress String Mac Address received from WifiManager containing colons + * @return Long variable with decimal conversion of the mac address */ - private long convertBssidToLong(String wifiMacAddress){ - long intMacAddress =0; - int colonCount =5; - //Loop through each character - for(int j =0; j<17; j++){ - //Identify character + private long convertBssidToLong(String wifiMacAddress) { + long intMacAddress = 0; + int colonCount = 5; + // Loop through each character + for (int j = 0; j < 17; j++) { + // Identify character char macByte = wifiMacAddress.charAt(j); - //convert string hex mac address with colons to decimal long integer - if(macByte != ':'){ - //For characters 0-9 subtract 48 from ASCII code and multiply by 16^position - if((int) macByte >= 48 && (int) macByte <= 57){ - intMacAddress = intMacAddress + (((int)macByte-48)*((long)Math.pow(16,16-j-colonCount))); + // convert string hex mac address with colons to decimal long integer + if (macByte != ':') { + // For characters 0-9 subtract 48 from ASCII code and multiply by 16^position + if ((int) macByte >= 48 && (int) macByte <= 57) { + intMacAddress = + intMacAddress + + (((int) macByte - 48) + * ((long) Math.pow(16, 16 - j - colonCount))); } - //For characters a-f subtract 87 (=97-10) from ASCII code and multiply by 16^index - else if ((int) macByte >= 97 && (int) macByte <= 102){ - intMacAddress = intMacAddress + (((int)macByte-87)*((long)Math.pow(16,16-j-colonCount))); + // For characters a-f subtract 87 (=97-10) from ASCII code and multiply by 16^index + else if ((int) macByte >= 97 && (int) macByte <= 102) { + intMacAddress = + intMacAddress + + (((int) macByte - 87) + * ((long) Math.pow(16, 16 - j - colonCount))); } - } - else - //coloncount is used to obtain the index of each character - colonCount --; + } else + // coloncount is used to obtain the index of each character + colonCount--; } return intMacAddress; } /** - * Checks if the user authorised all permissions necessary for accessing wifi data. - * Explicit user permissions must be granted for android sdk version 23 and above. This - * function checks which permissions are granted, and returns their conjunction. + * Checks if the user authorised all permissions necessary for accessing wifi data. Explicit + * user permissions must be granted for android sdk version 23 and above. This function checks + * which permissions are granted, and returns their conjunction. * - * @return boolean true if all permissions are granted for wifi access, false otherwise. + * @return boolean true if all permissions are granted for wifi access, false otherwise. */ private boolean checkWifiPermissions() { - int wifiAccessPermission = ActivityCompat.checkSelfPermission(this.context, - Manifest.permission.ACCESS_WIFI_STATE); - int wifiChangePermission = ActivityCompat.checkSelfPermission(this.context, - Manifest.permission.CHANGE_WIFI_STATE); - int coarseLocationPermission = ActivityCompat.checkSelfPermission(this.context, - Manifest.permission.ACCESS_COARSE_LOCATION); - int fineLocationPermission = ActivityCompat.checkSelfPermission(this.context, - Manifest.permission.ACCESS_FINE_LOCATION); + int wifiAccessPermission = + ActivityCompat.checkSelfPermission( + this.context, Manifest.permission.ACCESS_WIFI_STATE); + int wifiChangePermission = + ActivityCompat.checkSelfPermission( + this.context, Manifest.permission.CHANGE_WIFI_STATE); + int coarseLocationPermission = + ActivityCompat.checkSelfPermission( + this.context, Manifest.permission.ACCESS_COARSE_LOCATION); + int fineLocationPermission = + ActivityCompat.checkSelfPermission( + this.context, Manifest.permission.ACCESS_FINE_LOCATION); // Return missing permissions - return wifiAccessPermission == PackageManager.PERMISSION_GRANTED && - wifiChangePermission == PackageManager.PERMISSION_GRANTED && - coarseLocationPermission == PackageManager.PERMISSION_GRANTED && - fineLocationPermission == PackageManager.PERMISSION_GRANTED; + return wifiAccessPermission == PackageManager.PERMISSION_GRANTED + && wifiChangePermission == PackageManager.PERMISSION_GRANTED + && coarseLocationPermission == PackageManager.PERMISSION_GRANTED + && fineLocationPermission == PackageManager.PERMISSION_GRANTED; } /** - * Scan for nearby networks. - * The method checks for permissions again, and then requests a scan of nearby wifis. A - * broadcast receiver is registered to be called when the scan is complete. + * Scan for nearby networks. The method checks for permissions again, and then requests a scan + * of nearby wifis. A broadcast receiver is registered to be called when the scan is complete. */ private void startWifiScan() { - //Check settings for wifi permissions - if(checkWifiPermissions()) { - //if(sharedPreferences.getBoolean("wifi", false)) { - //Register broadcast receiver for wifi scans - context.registerReceiver(wifiScanReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); + // Check settings for wifi permissions + if (checkWifiPermissions()) { + // if(sharedPreferences.getBoolean("wifi", false)) { + // Register broadcast receiver for wifi scans + context.registerReceiver( + wifiScanReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); wifiManager.startScan(); - //} + // } } } /** - * Initiate scans for nearby networks every 5 seconds. - * The method declares a new timer instance to schedule a scan for nearby wifis every 5 seconds. + * Initiate scans for nearby networks every 5 seconds. The method declares a new timer instance + * to schedule a scan for nearby wifis every 5 seconds. */ public void startListening() { this.scanWifiDataTimer = new Timer(); @@ -230,9 +242,8 @@ public void startListening() { } /** - * Cancel wifi scans. - * The method unregisters the broadcast receiver associated with the wifi scans and cancels the - * timer so that new scans are not initiated. + * Cancel wifi scans. The method unregisters the broadcast receiver associated with the wifi + * scans and cancels the timer so that new scans are not initiated. */ public void stopListening() { context.unregisterReceiver(wifiScanReceiver); @@ -240,28 +251,47 @@ public void stopListening() { } /** - * Inform user if throttling is resent on their device. - * If the device supports wifi throttling check if it is enabled and instruct the user to - * disable it. + * Inform user if throttling is resent on their device. If the device supports wifi throttling + * check if it is enabled and instruct the user to disable it. */ - public void checkWifiThrottling(){ - if(checkWifiPermissions()) { - //If the device does not support wifi throttling an exception is thrown - try { - if(Settings.Global.getInt(context.getContentResolver(), "wifi_scan_throttle_enabled")==1) { - //Inform user to disable wifi throttling - Toast.makeText(context, "Disable Wi-Fi Throttling", Toast.LENGTH_SHORT).show(); - } - } catch (Settings.SettingNotFoundException e) { - e.printStackTrace(); + public void checkWifiThrottling() { + if (!checkWifiPermissions()) { + return; + } + // If the device does not support wifi throttling an exception is thrown + try { + boolean isThrottled = false; + // For Android 11+ + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) { + isThrottled = wifiManager.isScanThrottleEnabled(); + } else { + isThrottled = + Settings.Global.getInt( + context.getContentResolver(), "wifi_scan_throttle_enabled") + == 1; + } + + if (isThrottled) { + // Inform user to disable wifi throttling + new Handler(Looper.getMainLooper()) + .post( + () -> { + Toast.makeText( + context, + "Disable Wi-Fi Throttling", + Toast.LENGTH_SHORT) + .show(); + }); } + } catch (Settings.SettingNotFoundException e) { + e.printStackTrace(); } } /** * Implement default method from Observable Interface to add new observers to the class. * - * @param o Classes which implement the Observer interface to receive updates from the class. + * @param o Classes which implement the Observer interface to receive updates from the class. */ @Override public void registerObserver(Observer o) { @@ -271,11 +301,12 @@ public void registerObserver(Observer o) { /** * Implement default method from Observable Interface to add notify observers to the class. * Changes to the wifiData variable are passed to observers of the class. - * @param idx Unused. + * + * @param idx Unused. */ @Override public void notifyObservers(int idx) { - for(Observer o : observers) { + for (Observer o : observers) { o.update(wifiData); } } @@ -283,8 +314,8 @@ public void notifyObservers(int idx) { /** * Class to schedule wifi scans. * - * Implements default method in {@link TimerTask} class which it implements. It begins to start - * calling wifi scans every 5 seconds. + *

Implements default method in {@link TimerTask} class which it implements. It begins to + * start calling wifi scans every 5 seconds. */ private class scheduledWifiScan extends TimerTask { @@ -297,32 +328,31 @@ public void run() { /** * Obtains required information about wifi in which the device is currently connected. * - * A connectivity manager is used to obtain information about the current network. If the device - * is connected to a network its ssid, mac address and frequency is stored to a Wifi object so - * that it can be accessed by the caller of the method + *

A connectivity manager is used to obtain information about the current network. If the + * device is connected to a network its ssid, mac address and frequency is stored to a Wifi + * object so that it can be accessed by the caller of the method * * @return wifi object containing the currently connected wifi's ssid, mac address and frequency */ - public Wifi getCurrentWifiData(){ - //Set up a connectivity manager to get information about the wifi - ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService - (Context.CONNECTIVITY_SERVICE); - //Set up a network info object to store information about the current network + public Wifi getCurrentWifiData() { + // Set up a connectivity manager to get information about the wifi + ConnectivityManager connectivityManager = + (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + // Set up a network info object to store information about the current network NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); - //Only obtain wifi data if the device is connected - //Wifi in which the device is currently connected to + // Only obtain wifi data if the device is connected + // Wifi in which the device is currently connected to Wifi currentWifi = new Wifi(); - if(networkInfo.isConnected()) { - //Store the ssid, mac address and frequency of the current wifi + if (networkInfo.isConnected()) { + // Store the ssid, mac address and frequency of the current wifi currentWifi.setSsid(wifiManager.getConnectionInfo().getSSID()); String wifiMacAddress = wifiManager.getConnectionInfo().getBSSID(); long intMacAddress = convertBssidToLong(wifiMacAddress); currentWifi.setBssid(intMacAddress); currentWifi.setFrequency(wifiManager.getConnectionInfo().getFrequency()); - } - else{ - //Store standard information if not connected + } else { + // Store standard information if not connected currentWifi.setSsid("Not connected"); currentWifi.setBssid(0); currentWifi.setFrequency(0); diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/Building.java b/app/src/main/java/com/openpositioning/PositionMe/utils/Building.java new file mode 100644 index 00000000..a846737a --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/utils/Building.java @@ -0,0 +1,478 @@ +package com.openpositioning.PositionMe.utils; + +import static com.openpositioning.PositionMe.utils.BuildingConstants.BUILDING_ELEMENT_LIFT; +import static com.openpositioning.PositionMe.utils.BuildingConstants.BUILDING_ELEMENT_STAIRS; +import static com.openpositioning.PositionMe.utils.BuildingConstants.BUILDING_ELEMENT_WALL; +import static com.openpositioning.PositionMe.utils.BuildingConstants.BUILDING_NO_FLOOR_NUMBER; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_BUILDING_WITHOUT_FLOOR_MAPS; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_BUILDING_WITH_FLOOR_MAPS; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_FLOOR_PLAN_ELEMENTS_DEFAULT; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_FLOOR_PLAN_ELEMENTS_LIFT; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_FLOOR_PLAN_ELEMENTS_STAIRS; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_FLOOR_PLAN_ELEMENTS_WALL; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_FLOOR_PLAN_FILL_TRANSPARENT; +import static com.openpositioning.PositionMe.utils.BuildingConstants.FLOOR_HEIGHT_DEFAULT; +import static com.openpositioning.PositionMe.utils.BuildingConstants.FLOOR_HEIGHT_NUCLEUS; +import static com.openpositioning.PositionMe.utils.BuildingConstants.LINE_WEIGHT_FLOOR_PLAN; +import static com.openpositioning.PositionMe.utils.BuildingConstants.LINE_WEIGHT_OUTLINE; +import static com.openpositioning.PositionMe.utils.UtilConstants.BUILDING_NAME_NUCLEUS; + +import android.util.Log; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.Polygon; +import com.google.android.gms.maps.model.PolygonOptions; +import com.google.android.gms.maps.model.Polyline; +import com.google.android.gms.maps.model.PolylineOptions; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * This class defines all buildings retrieved from the OpenPosition API. Buildings have a name, an + * outline, and multiple floor plans. These are drawn onto Google Map objects in {@link + * IndoorMapManager}. + * + * @see IndoorMapManager + */ +public class Building { + private static final String TAG = "Building"; + private static final String BUILDING_GROUND_PREFIX = "G"; + + /* + * Sort the floor names in the order: + * - Basement + * - Lower ground + * - Ground + * - Upper ground + * - (Upper) Floors + * */ + private static final String[] BUILDING_FLOOR_PREFIX_ORDER = + new String[] {"B", "L", BUILDING_GROUND_PREFIX, "U", "F"}; + + private List outlinePoints; + private String name; + private List floorPlans; + private List floorNames; + private float floorHeight; + private int floorNumber = BUILDING_NO_FLOOR_NUMBER; + private int groundFloorIndex = 0; + private boolean isInsideBuilding = false; + private boolean isPreviewingFloorPlan = false; + private Map> floorPlanElementOptions; + private Map> floorPlanElements; + private Map> floorPlanPolygons; + private PolygonOptions outlinePolygonOptions; + private Polygon outlinePolygon; + + public Building(String name, List outlinePoints, List floorPlans) { + this.name = name; + this.floorPlans = floorPlans; + this.outlinePoints = outlinePoints; + this.floorPlanElements = new HashMap<>(); + this.floorPlanPolygons = new HashMap<>(); + + /* + Build the building outline, and all floor plan elements. + These Option objects will then be applied to a GoogleMap + object from TrajectoryMapManager to create a Polygon and + List of Polyline objects respectively + */ + this.outlinePolygonOptions = buildOutlinePolygon(); + this.floorPlanElementOptions = buildFloorPlanElements(); + + this.floorNames = defineFloorNameOrder(this.floorPlans); + + // Define the floor height + if (name.equals(BUILDING_NAME_NUCLEUS)) { + floorHeight = FLOOR_HEIGHT_NUCLEUS; + } else { + floorHeight = FLOOR_HEIGHT_DEFAULT; + } + Log.d(TAG, "Created new building: " + this.name); + } + + /** + * Prepare polygon of building outline + * + * @return PolygonOption representing the building outline + */ + private PolygonOptions buildOutlinePolygon() { + return new PolygonOptions() + .strokeWidth(LINE_WEIGHT_OUTLINE) + .strokeColor(COLOUR_BUILDING_WITH_FLOOR_MAPS) + .fillColor(COLOUR_FLOOR_PLAN_FILL_TRANSPARENT) + .zIndex(0) + .clickable(true) + .addAll(this.outlinePoints); + } + + /** + * Generate a map of possible floor plans with their associated elements, indexed by floor plan + * name + * + * @return Map of floor plan elements indexed by name + */ + private Map> buildFloorPlanElements() { + Map> floorPlanElementOptions = new HashMap<>(); + List floorNames = new ArrayList<>(); + + for (FloorPlan floorPlan : floorPlans) { + String floorName = floorPlan.getFloorName(); + floorNames.add(floorName); + + List> elementsWall = floorPlan.getElementsOfType(BUILDING_ELEMENT_WALL); + List> elementsStairs = + floorPlan.getElementsOfType(BUILDING_ELEMENT_STAIRS); + List> elementsLift = floorPlan.getElementsOfType(BUILDING_ELEMENT_LIFT); + List> elementsUnknown = floorPlan.getUnknownElements(); + + List floorElements = new ArrayList<>(); + for (List elementWall : elementsWall) { + floorElements.add( + new PolygonOptions() + .strokeWidth(LINE_WEIGHT_FLOOR_PLAN) + .strokeColor(COLOUR_FLOOR_PLAN_ELEMENTS_WALL) + .fillColor(COLOUR_FLOOR_PLAN_ELEMENTS_WALL) + .zIndex(2) + .addAll(elementWall)); + } + for (List elementStairs : elementsStairs) { + floorElements.add( + new PolygonOptions() + .strokeWidth(LINE_WEIGHT_FLOOR_PLAN) + .strokeColor(COLOUR_FLOOR_PLAN_ELEMENTS_STAIRS) + .fillColor(COLOUR_FLOOR_PLAN_ELEMENTS_STAIRS) + .zIndex(1) + .addAll(elementStairs)); + } + for (List elementLift : elementsLift) { + floorElements.add( + new PolygonOptions() + .strokeWidth(LINE_WEIGHT_FLOOR_PLAN) + .strokeColor(COLOUR_FLOOR_PLAN_ELEMENTS_LIFT) + .fillColor(COLOUR_FLOOR_PLAN_ELEMENTS_LIFT) + .zIndex(1) + .addAll(elementLift)); + } + for (List elementUnknown : elementsUnknown) { + floorElements.add( + new PolylineOptions() + .width(LINE_WEIGHT_FLOOR_PLAN) + .color(COLOUR_FLOOR_PLAN_ELEMENTS_DEFAULT) + .zIndex(1) + .addAll(elementUnknown)); + } + floorPlanElementOptions.put(floorName, floorElements); + } + return floorPlanElementOptions; + } + + /** + * Sort the floor plan names such that the lowest index is the lowest floor. Also sets the + * ground floor index for future reference + * + * @param floors The list of all {@link FloorPlan FloorPlans} associated with the building + * @return A list of sorted floor plan names + */ + private List defineFloorNameOrder(List floors) { + List orderedNames = new ArrayList<>(); + + List allNames = new ArrayList<>(); + for (FloorPlan floor : floors) { + allNames.add(floor.getFloorName()); + } + + for (String floorPrefix : BUILDING_FLOOR_PREFIX_ORDER) { + for (String name : allNames) { + if (name.toUpperCase().startsWith(floorPrefix)) { + orderedNames.add(name); + } + } + } + + // Add floor names with unexpected/unknown prefixes to end of floor plan list + for (String name : allNames) { + if (!orderedNames.contains(name)) { + Log.w(TAG, "Unexpected floor name \"" + name + "\"; adding to end of list"); + orderedNames.add(name); + } + } + + // Set the index of the ground floor, for future reference + for (String name : orderedNames) { + if (name.toUpperCase().startsWith(BUILDING_GROUND_PREFIX)) { + this.groundFloorIndex = orderedNames.indexOf(name); + } + } + return orderedNames; + } + + public String getName() { + return name; + } + + public float getFloorHeight() { + return floorHeight; + } + + public int getGroundFloorIndex() { + return groundFloorIndex; + } + + public List getFloorPlans() { + return floorPlans; + } + + /** + * Getter to obtain if currently an indoor floor map is being displayed + * + * @return true if an indoor map is visible to the user, false otherwise + */ + public boolean getIsInsideBuilding() { + return isInsideBuilding; + } + + public boolean getIsPreviewingFloorPlan() { + return isPreviewingFloorPlan; + } + + public int getFloorNumber() { + return floorNumber; + } + + public String getFloorName() { + return floorNames.get(floorNumber); + } + + public List getFloorNames() { + return floorNames; + } + + public Polygon getBuildingOutline() { + return outlinePolygon; + } + + public List getFloorPlanElements(String floorName) { + return floorPlanElements.get(floorName); + } + + public void setIsPreviewingFloorPlan(boolean set) { + isPreviewingFloorPlan = set; + } + + /** + * Draw an outline of the building on the map. + * + * @param map The GoogleMap object where the outline is being drawn + */ + public void drawBuildingOutline(GoogleMap map) { + if (outlinePolygon == null) { + // Set stroke colour depending on presence of floor plans + int strokeColour = + !floorPlans.isEmpty() + ? COLOUR_BUILDING_WITH_FLOOR_MAPS + : COLOUR_BUILDING_WITHOUT_FLOOR_MAPS; + this.outlinePolygon = map.addPolygon(outlinePolygonOptions.strokeColor(strokeColour)); + Log.d(TAG, name + ": Building outline drawn"); + } else { + Log.d(TAG, name + ": Outline already visible"); + } + } + + /** + * Set the fill colour of the building polygon + * + * @param colour The desired colour of the polygon + */ + public void setFillColour(int colour) { + if (outlinePolygon == null) { + Log.w(TAG, name + ": Outline polygon is null!"); + } else { + outlinePolygon.setFillColor(colour); + } + } + + /** + * Draw the floor plan elements of the desired floor on a map object + * + * @param newFloor The number of the floor being drawn + * @param gMap The GoogleMap object where floor plans are being drawn + */ + public void setCurrentFloor(int newFloor, GoogleMap gMap) { + if (newFloor < 0 || newFloor >= floorNames.size()) { + Log.w( + TAG, + name + + ": Suggested floor " + + newFloor + + " outside of range {0," + + floorNames.size() + + "}"); + } else if (newFloor == floorNumber) { + // Redraw the floor plan elements + editFloorPlan(gMap, floorNumber, true); + Log.d(TAG, name + ": Already on floor " + newFloor); + } else { + // Floor number initialises to -1, so reinitialise if required + if (floorNumber == BUILDING_NO_FLOOR_NUMBER) { + floorNumber = groundFloorIndex; + } else { + // Remove old floor plan before continuing + editFloorPlan(gMap, floorNumber, false); + floorNumber = newFloor; + } + editFloorPlan(gMap, floorNumber, true); + Log.d(TAG, name + ": Floor set to " + floorNumber); + } + } + + /** + * Hide all available floor plans for the building + * + * @param map The GoogleMap object showing the floor plans of the building + */ + public void hideFloorPlans(GoogleMap map) { + for (int i = 0; i < floorNames.size(); i++) { + editFloorPlan(map, i, false); + } + // Reset floor number upon leaving building + if (!isInsideBuilding) { + floorNumber = BUILDING_NO_FLOOR_NUMBER; + } + } + + /** + * Draw the desired floor number's floor plan on the map. + * + *

Either add the polylines required if they have never been drawn before, or toggle their + * visibility + * + * @param map The GoogleMap object drawing the floor plans + * @param floorNumber The floor being displayed or hidden + * @param showFloor True if the floor plan should be visible; false otherwise, to hide the + * floorplan + */ + public void editFloorPlan(GoogleMap map, int floorNumber, boolean showFloor) { + String floorName = floorNames.get(floorNumber); + List elementsPolyline; + List elementsPolygon; + + // Use pre-existing floor plan elements if possible + if (floorPlanElements.containsKey(floorName)) { + elementsPolyline = floorPlanElements.get(floorName); + elementsPolygon = floorPlanPolygons.get(floorName); + } else { + // Continue only if floor plan elements can be created + if (!floorPlanElementOptions.containsKey(floorName)) { + Log.w(TAG, name + ": Floor " + floorNumber + " has no floor plan!"); + return; + } + // Create the Polyline/Polygon objects for the first time + elementsPolyline = new ArrayList<>(); + elementsPolygon = new ArrayList<>(); + for (Object options : floorPlanElementOptions.get(floorName)) { + if (options instanceof PolylineOptions polylineOptions) { + Polyline floorElement = map.addPolyline(polylineOptions); + elementsPolyline.add(floorElement); + } else if (options instanceof PolygonOptions polygonOptions) { + Polygon floorElement = map.addPolygon(polygonOptions); + elementsPolygon.add(floorElement); + } + } + floorPlanElements.put(floorName, elementsPolyline); + floorPlanPolygons.put(floorName, elementsPolygon); + Log.d(TAG, name + " floor " + floorNumber + " added to list"); + } + + // With all elements gathered, set their visibility as required + for (Polyline element : elementsPolyline) { + element.setVisible(showFloor); + } + for (Polygon element : elementsPolygon) { + element.setVisible(showFloor); + } + Log.d(TAG, name + " floor " + floorNumber + " visibility set to " + showFloor); + } + + /** + * Function to check if point in polygon (approximates earth to be flat) Ray casting algorithm + * https://en.wikipedia.org/wiki/Point_in_polygon + * + * @param point point to be checked if in polygon + * @return True if point in polygon False otherwise + */ + public boolean isPointInBuilding(LatLng point) { + int numCrossings = 0; + // For each edge + for (int i = 0; i < outlinePoints.size(); i++) { + LatLng a = outlinePoints.get(i); + int j = i + 1; + // Last edge (includes first point of Polygon) + if (j >= outlinePoints.size()) { + j = 0; + } + LatLng b = outlinePoints.get(j); + if (crossingSegment(point, a, b)) { + numCrossings++; + } + } + + // If odd number of numCrossings, return true (point is in polygon) + isInsideBuilding = (numCrossings % 2 == 1); + return isInsideBuilding; + } + + /** + * Ray Casting algorithm for a segment joining ab + * + * @param point the point we check + * @param a the line segment's starting point + * @param b the line segment's ending point + * @return True if the point is 1) To the left of the segment ab 2) Not above nor below the + * segment ab Otherwise False + */ + private static boolean crossingSegment(LatLng point, LatLng a, LatLng b) { + double pointLng = point.longitude, + pointLat = point.latitude, + aLng = a.longitude, + aLat = a.latitude, + bLng = b.longitude, + bLat = b.latitude; + if (aLat > bLat) { + aLng = b.longitude; + aLat = b.latitude; + bLng = a.longitude; + bLat = a.latitude; + } + // Alter longitude to correct for 180 degree crossings + if (pointLng < 0 || aLng < 0 || bLng < 0) { + pointLng += 360; + aLng += 360; + bLng += 360; + } + // If point has same latitude as a or b, increase slightly pointLat + if (pointLat == aLat || pointLat == bLat) pointLat += 0.00000001; + + // If the point is above, below or to the right of the segment, return false + if ((pointLat > bLat || pointLat < aLat) || (pointLng > Math.max(aLng, bLng))) { + return false; + } + // If the point is not above, below or to the right and is to the left, return true + else if (pointLng < Math.min(aLng, bLng)) { + return true; + } + // Comparing the slope of segment [a,b] (slope1) + // and segment [a,point] (slope2) to check if to the left of segment [a,b] or not + else { + double slope1 = + (aLng != bLng) ? ((bLat - aLat) / (bLng - aLng)) : Double.POSITIVE_INFINITY; + double slope2 = + (aLng != pointLng) + ? ((pointLat - aLat) / (pointLng - aLng)) + : Double.POSITIVE_INFINITY; + return (slope2 >= slope1); + } + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/BuildingConstants.java b/app/src/main/java/com/openpositioning/PositionMe/utils/BuildingConstants.java new file mode 100644 index 00000000..377506b6 --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/utils/BuildingConstants.java @@ -0,0 +1,51 @@ +package com.openpositioning.PositionMe.utils; + +import android.graphics.Color; + +/** + * Centralised definitions of {@link Building} related constants + * + * @see Building + * @see com.openpositioning.PositionMe.presentation.fragment.TrajectoryMapFragment + * TrajectoryMapFragment + * @see IndoorMapManager + * @see FloorPlan + */ +public class BuildingConstants { + + // Building outlines + public static final int COLOUR_BUILDING_WITHOUT_FLOOR_MAPS = Color.YELLOW; + public static final int COLOUR_BUILDING_WITH_FLOOR_MAPS = Color.GREEN; + + public static final String BUILDING_ELEMENT_WALL = "wall"; + public static final String BUILDING_ELEMENT_STAIRS = "stairs"; + public static final String BUILDING_ELEMENT_LIFT = "lift"; + + public static final int BUILDING_NO_FLOOR_NUMBER = -1; + public static final String BUILDING_NO_FLOOR_NAME = "N/A"; + + // Paths + public static final int COLOUR_PATH_COLOUR = Color.RED; + public static final int COLOUR_PATH_MONOCHROME = Color.BLACK; + public static final int COLOUR_PATH_GNSS = Color.BLUE; + public static final int COLOUR_PATH_FUSION = Color.GREEN; + + // Floor plans + public static final int COLOUR_FLOOR_PLAN_FILL_TRANSPARENT = Color.TRANSPARENT; + public static final int COLOUR_FLOOR_PLAN_FILL_PREVIEW = Color.LTGRAY; + public static final int COLOUR_FLOOR_PLAN_FILL_INSIDE = Color.WHITE; + public static final int COLOUR_FLOOR_PLAN_ELEMENTS_DEFAULT = Color.BLACK; + public static final int COLOUR_FLOOR_PLAN_ELEMENTS_WALL = Color.BLACK; + public static final int COLOUR_FLOOR_PLAN_ELEMENTS_STAIRS = Color.CYAN; + public static final int COLOUR_FLOOR_PLAN_ELEMENTS_LIFT = Color.BLUE; + + // Set priority level for drawing elements on top of one another on the map + public static final int MAP_DRAWING_PRIORITY_MAX = 1000; + + public static final float LINE_WEIGHT_FLOOR_PLAN = 5f; + public static final float LINE_WEIGHT_OUTLINE = 10f; + + public static final float FLOOR_HEIGHT_DEFAULT = 3.6F; + public static final float FLOOR_HEIGHT_NKM_LIBRARY = 3.6F; + public static final float FLOOR_HEIGHT_NUCLEUS = 4.2F; +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/BuildingPolygon.java b/app/src/main/java/com/openpositioning/PositionMe/utils/BuildingPolygon.java deleted file mode 100644 index 2d0a3265..00000000 --- a/app/src/main/java/com/openpositioning/PositionMe/utils/BuildingPolygon.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.openpositioning.PositionMe.utils; - - -import com.google.android.gms.maps.model.LatLng; - -import java.util.ArrayList; -import java.util.List; - -/** - * Class used to check for a pre-defined set of coordinates if it is in a Building (Nucleus, Library) - * (Can be used to add more buildings by adding the coordinates of the buildings and adding methods) - * @see IndoorMapManager Used by the the IndoorFloorManager class - * @author Arun Gopalakrishnan - */ -public class BuildingPolygon { - // Defining the coordinates of the building boundaries (rectangular boundaries based on floor map shape) - // North-East and South-West Coordinates for the Nucleus Building - public static final LatLng NUCLEUS_NE=new LatLng(55.92332001571212, -3.1738768212979593); - public static final LatLng NUCLEUS_SW=new LatLng(55.92282257022002, -3.1745956532857647); - // North-East and South-West Coordinates for the Kenneth and Murray Library Building - public static final LatLng LIBRARY_NE=new LatLng(55.92306692576906, -3.174771893078224); - public static final LatLng LIBRARY_SW=new LatLng(55.92281045664704, -3.175184089079065); - // Boundary coordinates of the Nucleus building (clockwise) - - public static final List NUCLEUS_POLYGON = new ArrayList() {{ - add(BuildingPolygon.NUCLEUS_NE); - add(new LatLng(BuildingPolygon.NUCLEUS_SW.latitude, BuildingPolygon.NUCLEUS_NE.longitude)); // South-East - add(BuildingPolygon.NUCLEUS_SW); - add(new LatLng(BuildingPolygon.NUCLEUS_NE.latitude, BuildingPolygon.NUCLEUS_SW.longitude)); // North-West - }}; - //Boundary coordinates of the Library building (clockwise) - public static final List LIBRARY_POLYGON = new ArrayList() {{ - add(BuildingPolygon.LIBRARY_NE); - add(new LatLng(BuildingPolygon.LIBRARY_SW.latitude,BuildingPolygon.LIBRARY_NE.longitude));//(South-East) - add(BuildingPolygon.LIBRARY_SW); - add(new LatLng(BuildingPolygon.LIBRARY_NE.latitude,BuildingPolygon.LIBRARY_SW.longitude));//(North-West) - }}; - - /** - * Function to check if a point is in the Nucleus Building - * @param point the point to be checked if inside the building - * @return True if point is in Nucleus building else False - */ - public static boolean inNucleus(LatLng point){ - return (pointInPolygon(point,NUCLEUS_POLYGON)); - - } - /** - * Function to check if a point is in the Library Building - * @param point the point which is checked if inside the building - * @return True if point is in Library building else False - */ - public static boolean inLibrary(LatLng point){ - return (pointInPolygon(point,LIBRARY_POLYGON)); - } - - /** - * Function to check if point in polygon (approximates earth to be flat) - * Ray casting algorithm https://en.wikipedia.org/wiki/Point_in_polygon - * @param point point to be checked if in polygon - * @param polygon Boundaries of the building - * @return True if point in polygon - * False otherwise - */ - private static boolean pointInPolygon(LatLng point, List polygon) { - int numCrossings = 0; - List path=polygon; - // For each edge - for (int i=0; i < path.size(); i++) { - LatLng a = path.get(i); - int j = i + 1; - // Last edge (includes first point of Polygon) - if (j >= path.size()) { - j = 0; - } - LatLng b = path.get(j); - if (crossingSegment(point, a, b)) { - numCrossings++; - } - } - - //if odd number of numCrossings return true (point is in polygon) - return (numCrossings % 2 == 1); - } - - /** - * Ray Casting algorithm for a segment joining ab - * @param point the point we check - * @param a the line segment's starting point - * @param b the line segment's ending point - * @return True if the point is - * 1) To the left of the segment ab - * 2) Not above nor below the segment ab - * Otherwise False - */ - private static boolean crossingSegment(LatLng point, LatLng a,LatLng b) { - double pointLng = point.longitude, - pointLat = point.latitude, - aLng = a.longitude, - aLat = a.latitude, - bLng = b.longitude, - bLat = b.latitude; - if (aLat > bLat) { - aLng = b.longitude; - aLat = b.latitude; - bLng = a.longitude; - bLat = a.latitude; - } - // Alter longitude to correct for 180 degree crossings - if (pointLng < 0 || aLng <0 || bLng <0) { pointLng += 360; aLng+=360; bLng+=360; } - // If point has same latitude as a or b, increase slightly pointLat - if (pointLat == aLat || pointLat == bLat) pointLat += 0.00000001; - - //If the point is above, below or to the right of the segment,return false - if ((pointLat > bLat || pointLat < aLat) || (pointLng > Math.max(aLng, bLng))){ - return false; - } - // If the point is not above, below or to the right and is to the left, return true - else if (pointLng < Math.min(aLng, bLng)){ - return true; - } - // Comparing the slope of segment [a,b] (slope1) - // and segment [a,point] (slope2) to check if to the left of segment [a,b] or not - else { - double slope1 = (aLng != bLng) ? ((bLat - aLat) / (bLng - aLng)) : Double.POSITIVE_INFINITY; - double slope2 = (aLng != pointLng) ? ((pointLat - aLat) / (pointLng - aLng)) : Double.POSITIVE_INFINITY; - return (slope2 >= slope1); - } - } -} diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/CircularFloatBuffer.java b/app/src/main/java/com/openpositioning/PositionMe/utils/CircularFloatBuffer.java index 73abb674..9979dbd3 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/utils/CircularFloatBuffer.java +++ b/app/src/main/java/com/openpositioning/PositionMe/utils/CircularFloatBuffer.java @@ -22,7 +22,7 @@ public class CircularFloatBuffer { /** * Default constructor for a Circular Float Buffer with a given capacity. * - * @param capacity size of the array. + * @param capacity size of the array. */ public CircularFloatBuffer(int capacity) { this.capacity = (capacity < 1) ? DEFAULT_CAPACITY : capacity; @@ -32,11 +32,11 @@ public CircularFloatBuffer(int capacity) { } /** - * Put in a new element to the array. - * Overwrites the existing values if present already and moves the write head forward. + * Put in a new element to the array. Overwrites the existing values if present already and + * moves the write head forward. * - * @param element float value to be added to the array. - * @return true if adding to the element was successful. + * @param element float value to be added to the array. + * @return true if adding to the element was successful. */ public boolean putNewest(float element) { int nextWriteSeq = writeSequence + 1; @@ -46,11 +46,10 @@ public boolean putNewest(float element) { } /** - * Get the oldest element in the array. - * If empty, return an empty Optional. Moves the read head forward. - * - * @return Optional float of the oldest element. + * Get the oldest element in the array. If empty, return an empty Optional. Moves the read head + * forward. * + * @return Optional float of the oldest element. * @see Optional */ public Optional getOldest() { @@ -65,7 +64,7 @@ public Optional getOldest() { /** * Get the capacity of the buffer. * - * @return int capacity, size of the underlying array. + * @return int capacity, size of the underlying array. */ public int getCapacity() { return capacity; @@ -74,7 +73,7 @@ public int getCapacity() { /** * Get the number of elements currently in the buffer. * - * @return int number of floats in the buffer. + * @return int number of floats in the buffer. */ public int getCurrentSize() { return (writeSequence - readSequence) + 1; @@ -83,7 +82,7 @@ public int getCurrentSize() { /** * Checks if the buffer is empty. * - * @return true if there are no elements in the buffer, false otherwise + * @return true if there are no elements in the buffer, false otherwise */ public boolean isEmpty() { return writeSequence < readSequence; @@ -92,23 +91,22 @@ public boolean isEmpty() { /** * Check if the buffer is full. * - * @return true if the number of elements in the buffer matches the capacity, false otherwise. + * @return true if the number of elements in the buffer matches the capacity, false otherwise. */ public boolean isFull() { return getCurrentSize() >= capacity; } /** - * Get a copy of the buffer as a list starting with the oldest element. - * If the list is not full return null. + * Get a copy of the buffer as a list starting with the oldest element. If the list is not full + * return null. * * @return List of Floats contained in the buffer from oldest to newest. */ public List getListCopy() { - if(!isFull()) return null; + if (!isFull()) return null; return IntStream.range(readSequence, readSequence + capacity) .mapToObj(i -> this.data[i % capacity]) .collect(Collectors.toList()); } - } diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/FloorPlan.java b/app/src/main/java/com/openpositioning/PositionMe/utils/FloorPlan.java new file mode 100644 index 00000000..528a45b3 --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/utils/FloorPlan.java @@ -0,0 +1,76 @@ +package com.openpositioning.PositionMe.utils; + +import static com.openpositioning.PositionMe.utils.BuildingConstants.BUILDING_ELEMENT_LIFT; +import static com.openpositioning.PositionMe.utils.BuildingConstants.BUILDING_ELEMENT_STAIRS; +import static com.openpositioning.PositionMe.utils.BuildingConstants.BUILDING_ELEMENT_WALL; + +import com.google.android.gms.maps.model.LatLng; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * This class contains information about a floor plan for a {@link Building} as received from the + * OpenPosition Server + * + * @see Building + * @see IndoorMapManager + */ +public class FloorPlan { + public static final String TAG = "FloorPlan"; + + private String floorName; + // List of elements, indexed by their element type, and comprised of a list of points + private List>> elements; + + // List of element types expected for the server to return + private static final List ELEMENT_TYPES_KNOWN = + Arrays.asList(BUILDING_ELEMENT_WALL, BUILDING_ELEMENT_LIFT, BUILDING_ELEMENT_STAIRS); + + public FloorPlan(String floorName, List>> elements) { + this.floorName = floorName; + this.elements = elements; + } + + public String getFloorName() { + return floorName; + } + + /** + * Retrieve a list of every floor element of a given type + * + * @param type The element type requested + * @return A list of list of points, with each list representing a different floor plan element + */ + public List> getElementsOfType(String type) { + List> elements = new ArrayList<>(); + + for (Map> floorElement : this.elements) { + if (floorElement.keySet().toArray()[0].equals(type)) { + elements.add(floorElement.get(type)); + } + } + + return elements; + } + + /** + * Retrieve any elements of an unexpected type + * + * @return A list of elements, represented by their points, which have unexpected types + * @see FloorPlan#ELEMENT_TYPES_KNOWN + */ + public List> getUnknownElements() { + List> elements = new ArrayList<>(); + + for (Map> floorElement : this.elements) { + String type = floorElement.keySet().toArray()[0].toString(); + if (!ELEMENT_TYPES_KNOWN.contains(type)) { + elements.addAll(getElementsOfType(type)); + } + } + + return elements; + } +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/IndoorMapManager.java b/app/src/main/java/com/openpositioning/PositionMe/utils/IndoorMapManager.java index 9d7167df..c9fb9b21 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/utils/IndoorMapManager.java +++ b/app/src/main/java/com/openpositioning/PositionMe/utils/IndoorMapManager.java @@ -1,193 +1,321 @@ package com.openpositioning.PositionMe.utils; -import android.graphics.Color; -import android.util.Log; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_FLOOR_PLAN_FILL_INSIDE; +import static com.openpositioning.PositionMe.utils.BuildingConstants.COLOUR_FLOOR_PLAN_FILL_TRANSPARENT; +import android.util.Log; import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.model.BitmapDescriptorFactory; -import com.google.android.gms.maps.model.GroundOverlay; -import com.google.android.gms.maps.model.GroundOverlayOptions; import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.LatLngBounds; -import com.google.android.gms.maps.model.PolylineOptions; -import com.openpositioning.PositionMe.R; - -import java.util.Arrays; +import com.openpositioning.PositionMe.data.remote.ServerCommunications; +import com.openpositioning.PositionMe.sensors.Observer; +import com.openpositioning.PositionMe.sensors.SensorFusion; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; /** - * Class used to manage indoor floor map overlays - * Currently used by RecordingFragment - * @see BuildingPolygon Describes the bounds of buildings and the methods to check if point is - * in the building + * Class used to manage indoor floor map overlays Currently used by RecordingFragment + * + * @see Building Describes the bounds of buildings and the methods to check if point is in the + * building + * @see Observer Interface for handling server responses * @author Arun Gopalakrishnan */ -public class IndoorMapManager { +public class IndoorMapManager implements Observer { + private static final String TAG = "IndoorMapManager"; // To store the map instance private GoogleMap gMap; - //Stores the overlay of the indoor maps - private GroundOverlay groundOverlay; - // Stores the current Location of user + private SensorFusion sensorFusion; + // Stores the current location of the user private LatLng currentLocation; - // Stores if indoor map overlay is currently set - private boolean isIndoorMapSet=false; - //Stores the current floor in building - private int currentFloor; - // Floor height of current building - private float floorHeight; - //Images of the Nucleus Building and Library indoor floor maps - private final List NUCLEUS_MAPS =Arrays.asList( - R.drawable.nucleuslg, R.drawable.nucleusg, R.drawable.nucleus1, - R.drawable.nucleus2,R.drawable.nucleus3); - private final List LIBRARY_MAPS =Arrays.asList( - R.drawable.libraryg, R.drawable.library1, R.drawable.library2, - R.drawable.library3); - // South-west and north east Bounds of Nucleus building and library to set the Overlay - LatLngBounds NUCLEUS=new LatLngBounds( - BuildingPolygon.NUCLEUS_SW, - BuildingPolygon.NUCLEUS_NE - ); - LatLngBounds LIBRARY=new LatLngBounds( - BuildingPolygon.LIBRARY_SW, - BuildingPolygon.LIBRARY_NE - ); - //Average Floor Heights of the Buildings - public static final float NUCLEUS_FLOOR_HEIGHT=4.2F; - public static final float LIBRARY_FLOOR_HEIGHT=3.6F; + private List buildings = new ArrayList<>(); + private List buildingNames = new ArrayList<>(); /** * Constructor to set the map instance + * * @param map The map on which the indoor floor map overlays are set */ - public IndoorMapManager(GoogleMap map){ - this.gMap=map; + public IndoorMapManager(GoogleMap map) { + this.gMap = map; + this.sensorFusion = SensorFusion.getInstance(); + sensorFusion.registerForServerUpdate(this); } - /** - * Function to update the current location of user and display the indoor map - * if user in building with indoor map available - * @param currentLocation new location of user - */ - public void setCurrentLocation(LatLng currentLocation){ - this.currentLocation=currentLocation; - setBuildingOverlay(); + public List getAllBuildings() { + return buildings; + } + + public List getAllBuildingNames() { + return buildingNames; + } + + public void addBuilding(Building building) { + buildings.add(building); + buildingNames.add(building.getName()); } /** - * Function to obtain the current building's floor height - * @return the floor height of the current building the user is in + * Function to update the current location of user and display the indoor map if user in + * building with indoor map available + * + * @param currentLocation Location of user */ - public float getFloorHeight() { - return floorHeight; + public void setCurrentLocation(LatLng currentLocation) { + this.currentLocation = currentLocation; } /** - * Getter to obtain if currently an indoor floor map is being displayed - * @return true if an indoor map is visible to the user, false otherwise + * Handle {@link com.google.android.gms.maps.model.Polygon Polygon} drawing if inside the {@link + * Building}, and hide all elements otherwise */ - public boolean getIsIndoorMapSet(){ - return isIndoorMapSet; + public void drawBuildingPolygons() { + for (Building building : buildings) { + if (building.equals(getCurrentBuilding(currentLocation))) { + building.setFillColour(COLOUR_FLOOR_PLAN_FILL_INSIDE); + // Disable preview if present + building.setIsPreviewingFloorPlan(false); + } else if (building.getIsPreviewingFloorPlan()) { + return; + } else { + Log.d(TAG, "Outside building " + building.getName() + "; hiding floor plans"); + building.setFillColour(COLOUR_FLOOR_PLAN_FILL_TRANSPARENT); + building.hideFloorPlans(gMap); + } + } } /** - * Setting the new floor of a user and displaying the indoor floor map accordingly - * (if floor exists in building) - * @param newFloor the floor the user is at - * @param autoFloor flag if function called by auto-floor feature + * Get the building the user is currently inside of, based on a given position. + * + * @param position The position being queried + * @return The building, if position is inside one, or null if no building contains position */ - public void setCurrentFloor(int newFloor, boolean autoFloor) { - if (BuildingPolygon.inNucleus(currentLocation)){ - //Special case for nucleus when auto-floor is being used - if (autoFloor) { - // If nucleus add bias floor as lower-ground floor referred to as floor 0 - newFloor += 1; + public Building getCurrentBuilding(LatLng position) { + if (position == null) return null; + for (Building building : buildings) { + if (building.isPointInBuilding(position)) { + return building; } - // If within bounds and different from floor map currently being shown - if (newFloor>=0 && newFloor=0 && newFloorCalled by {@link ServerCommunications} when the response to the HTTP info request is + * received. + * + * @param objList The response from the server, including a {@link Boolean} value of success and + * the server's response as a string. + */ + @Override + public void update(Object[] objList) { + boolean success = (boolean) objList[0]; + String response = objList[1].toString(); + Log.d(TAG, "Received response: " + response); + if (!success) return; + + try { + // Parse the JSON, and draw all possible buildings + List> entryList = processPOSTResponse(response); + for (Map buildingEntry : entryList) { + + String name = buildingEntry.get("name").toString(); + @SuppressWarnings("unchecked") + List outline = (List) buildingEntry.get("outline"); + @SuppressWarnings("unchecked") + List mapShapes = (List) buildingEntry.get("map_shapes"); + + // Add building to list of known buildings + if (!this.getAllBuildingNames().contains(name)) { + this.addBuilding(new Building(name, outline, mapShapes)); + } else { + Log.w(TAG, "Building " + name + " already exists. Skipping creation."); + } } + } catch (RuntimeException e) { + Log.e(TAG, "Error processing server response: " + e.getMessage()); } - } /** - * Increments the Current Floor and changes to higher floor's map (if a higher floor exists) + * Parses the GeoJSON response for floor plans + * + * @param response The raw JSON string response from the server + * @return A list of maps containing the data associated with every building contained with the + * response */ - public void increaseFloor(){ - this.setCurrentFloor(currentFloor+1,false); + private List> processPOSTResponse(String response) throws RuntimeException { + List> entryList = new ArrayList<>(); + + try { + JSONArray jsonArray = new JSONArray(response); + + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject buildingEntry = jsonArray.getJSONObject(i); + Map entryMap = new HashMap<>(); + + // Part 1 - Building Name + String name = buildingEntry.getString("name"); + + // Part 2 - Building Outline + String outlineJson = buildingEntry.optString("outline", ""); + ArrayList outlinePoints = parseOutlineJSON(outlineJson); + + // Part 3 - Floor plans + String mapShapesJson = buildingEntry.optString("map_shapes", ""); + List floorPlans = parseFloorPlanJSON(mapShapesJson); + + entryMap.put("name", name); + entryMap.put("outline", outlinePoints); + entryMap.put("map_shapes", floorPlans); + + entryList.add(entryMap); + Log.d(TAG, "Building '" + name + "' parsed"); + } + Log.d(TAG, entryList.size() + " buildings parsed"); + } catch (JSONException e) { + Log.e(TAG, "JSON Parse Failed: " + e.getMessage()); + } + return entryList; } /** - * Decrements the Current Floor and changes to the lower floor's map (if a lower floor exists) + * Extract the geometry and coordinates from the outline JSON, and reconstruct the outline as a + * list of {@link LatLng} points + * + * @param outlineJson The raw JSON of the outline as a String + * @return A list of points representing the outline, or an empty list on a parse error */ - public void decreaseFloor(){ - this.setCurrentFloor(currentFloor-1,false); + private ArrayList parseOutlineJSON(String outlineJson) { + ArrayList outlinePoints = new ArrayList<>(); + + if (!outlineJson.isEmpty()) { + try { + JSONObject outlineObject = new JSONObject(outlineJson); + JSONArray features = outlineObject.getJSONArray("features"); + + // Only expecting one Feature for the outline + if (features.length() > 0) { + JSONObject geometry = features.getJSONObject(0).getJSONObject("geometry"); + JSONArray coordinates = geometry.getJSONArray("coordinates"); + + // Extract the 'first ring', where LatLng points are stored + JSONArray firstRing = new JSONArray(); + if (coordinates.length() > 0) { + JSONArray firstPolygon = coordinates.getJSONArray(0); + if (firstPolygon.length() > 0) { + firstRing = firstPolygon.getJSONArray(0); + } + } + + for (int i = 0; i < firstRing.length(); i++) { + // GeoJSON: [longitude, latitude] + JSONArray point = firstRing.getJSONArray(i); + outlinePoints.add(new LatLng(point.getDouble(1), point.getDouble(0))); + } + } + } catch (JSONException e) { + Log.w(TAG, e.getMessage()); + outlinePoints.clear(); + } + } + return outlinePoints; } /** - * Sets the map overlay for the building if user's current - * location is in building and is not already set - * Removes the overlay if user no longer in building + * Generate a list of all {@link FloorPlan floorplans} present in the OpenPositioning server's + * response + * + * @param floorPlanJSON The raw JSON response from the server as a String + * @return A list of {@link FloorPlan} objects for each floor in the response */ - private void setBuildingOverlay() { - // Try catch block to prevent fatal crashes - try { - // Setting overlay if in Nucleus and not already set - if (BuildingPolygon.inNucleus(currentLocation) && !isIndoorMapSet) { - groundOverlay = gMap.addGroundOverlay(new GroundOverlayOptions() - .image(BitmapDescriptorFactory.fromResource(R.drawable.nucleusg)) - .positionFromBounds(NUCLEUS)); - isIndoorMapSet = true; - // Nucleus has an LG floor so G floor is at index 1 - currentFloor=1; - floorHeight=NUCLEUS_FLOOR_HEIGHT; - } - // Setting overlay if in Library and not already set - else if (BuildingPolygon.inLibrary(currentLocation) && !isIndoorMapSet) { - groundOverlay = gMap.addGroundOverlay(new GroundOverlayOptions() - .image(BitmapDescriptorFactory.fromResource(R.drawable.libraryg)) - .positionFromBounds(LIBRARY)); - isIndoorMapSet = true; - currentFloor=0; - floorHeight=LIBRARY_FLOOR_HEIGHT; + private List parseFloorPlanJSON(String floorPlanJSON) { + List floorplans = new ArrayList<>(); + + if (!floorPlanJSON.isEmpty()) { + try { + JSONObject floorplansObject = new JSONObject(floorPlanJSON); + for (Iterator it = floorplansObject.keys(); it.hasNext(); ) { + String floorName = it.next(); + JSONObject floor = floorplansObject.getJSONObject(floorName); + + JSONArray elementsJSON = floor.getJSONArray("features"); + + List>> elements = new ArrayList<>(); + for (int j = 0; j < elementsJSON.length(); j++) { + JSONObject elementObject = elementsJSON.getJSONObject(j); + + JSONObject properties = elementObject.getJSONObject("properties"); + String elementType = properties.getString("indoor_type"); + + JSONObject geometry = elementObject.getJSONObject("geometry"); + String geometryType = geometry.getString("type"); + JSONArray coordinates = geometry.getJSONArray("coordinates"); + + switch (geometryType) { + case "MultiLineString": + // coordinates[line_index][point_index] = [lon, lat] + for (int k = 0; k < coordinates.length(); k++) { + JSONArray line = coordinates.getJSONArray(k); + List points = constructPointsList(line); + Map> element = new HashMap<>(); + element.put(elementType, points); + elements.add(element); + } + break; + case "MultiPolygon": + // coordinates[polygon_index][ring_index][point_index] = + // [lon, lat] + for (int k = 0; k < coordinates.length(); k++) { + JSONArray polygon = coordinates.getJSONArray(k); + if (polygon.length() > 0) { + // Use the outer ring (index 0) of each polygon + JSONArray outerRing = polygon.getJSONArray(0); + List points = constructPointsList(outerRing); + Map> element = new HashMap<>(); + element.put(elementType, points); + elements.add(element); + } + } + break; + default: + } + } + FloorPlan floorResult = new FloorPlan(floorName, elements); + floorplans.add(floorResult); + } + } catch (JSONException e) { + Log.w(TAG, e.getMessage()); } - // Removing overlay if user no longer in area with indoor maps available - else if (!BuildingPolygon.inLibrary(currentLocation) && - !BuildingPolygon.inNucleus(currentLocation)&& isIndoorMapSet){ - groundOverlay.remove(); - isIndoorMapSet = false; - currentFloor=0; - } - } catch (Exception ex) { - Log.e("Error with overlay, Exception:", ex.toString()); } + return floorplans; } /** - * Function used to set the indication of available floor maps for building using green Polylines - * along the building's boundaries. + * Helper function to parse JSON lists of points and generate the corresponding {@link List} of + * {@link LatLng} points + * + * @param pointsArray {@link JSONArray} of points + * @return {@link List} of {@link LatLng} points */ - public void setIndicationOfIndoorMap(){ - //Indicator for Nucleus Building - List points=BuildingPolygon.NUCLEUS_POLYGON; - // Closing Boundary - points.add(BuildingPolygon.NUCLEUS_POLYGON.get(0)); - gMap.addPolyline(new PolylineOptions().color(Color.GREEN) - .addAll(points)); - - // Indicator for the Library Building - points=BuildingPolygon.LIBRARY_POLYGON; - // Closing Boundary - points.add(BuildingPolygon.LIBRARY_POLYGON.get(0)); - gMap.addPolyline(new PolylineOptions().color(Color.GREEN) - .addAll(points)); + private List constructPointsList(JSONArray pointsArray) { + List points = new ArrayList<>(); + try { + for (int i = 0; i < pointsArray.length(); i++) { + JSONArray point = pointsArray.getJSONArray(i); + points.add(new LatLng(point.getDouble(1), point.getDouble(0))); + } + } catch (JSONException e) { + Log.w(TAG, e.getMessage()); + } + return points; } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/NucleusBuildingManager.java b/app/src/main/java/com/openpositioning/PositionMe/utils/NucleusBuildingManager.java deleted file mode 100644 index 3570e8ad..00000000 --- a/app/src/main/java/com/openpositioning/PositionMe/utils/NucleusBuildingManager.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.openpositioning.PositionMe.utils; - -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.LatLngBounds; -import com.openpositioning.PositionMe.R; -import com.openpositioning.PositionMe.presentation.fragment.IndoorMapFragment; - -import java.util.ArrayList; - -public class NucleusBuildingManager { - private IndoorMapFragment indoorMapFragment; - private ArrayList buildingPolygon; - - public NucleusBuildingManager(GoogleMap map) { - // The nuclear building has 5 floors - indoorMapFragment = new IndoorMapFragment(map, 5); - - // southwest corner - double N1 = 55.92279; - double W1 = 3.174643; - - // Northeast corner - double N2 = 55.92335; - double W2 = 3.173829; - - // Define the full polygon with 4 vertices - buildingPolygon = new ArrayList<>(); - buildingPolygon.add(new LatLng(N1, -W1)); // Southwest corner - buildingPolygon.add(new LatLng(N1, -W2)); // Southeast corner - buildingPolygon.add(new LatLng(N2, -W2)); // Northeast corner - buildingPolygon.add(new LatLng(N2, -W1)); // Northwest corner - - // Initialize the indoor map of each layer - indoorMapFragment.addFloor(0, R.drawable.floor_lg, new LatLngBounds(buildingPolygon.get(0), buildingPolygon.get(2))); - indoorMapFragment.addFloor(1, R.drawable.floor_ug, new LatLngBounds(buildingPolygon.get(0), buildingPolygon.get(2))); - indoorMapFragment.addFloor(2, R.drawable.floor_1, new LatLngBounds(buildingPolygon.get(0), buildingPolygon.get(2))); - indoorMapFragment.addFloor(3, R.drawable.floor_2, new LatLngBounds(buildingPolygon.get(0), buildingPolygon.get(2))); - indoorMapFragment.addFloor(4, R.drawable.floor_3, new LatLngBounds(buildingPolygon.get(0), buildingPolygon.get(2))); - } - - public IndoorMapFragment getIndoorMapManager() { - return indoorMapFragment; - } - - /** - * Determines if a given point is inside the building polygon. - * - * @param point the point to check - * @return true if the point is inside the polygon, false otherwise - */ - public boolean isPointInBuilding(LatLng point) { - int intersectCount = 0; - // Loop through each edge of the polygon - for (int j = 0; j < buildingPolygon.size(); j++) { - LatLng vertA = buildingPolygon.get(j); - LatLng vertB = buildingPolygon.get((j + 1) % buildingPolygon.size()); - // Check if the ray from the point intersects with the edge - if (rayCastIntersect(point, vertA, vertB)) { - intersectCount++; - } - } - // If the number of intersections is odd, the point is inside the polygon - return ((intersectCount % 2) == 1); // odd = inside, even = outside; - } - - /** - * Determines if a ray from a point intersects with a given edge of the polygon. - * - * @param point the point from which the ray is cast - * @param vertA the first vertex of the edge - * @param vertB the second vertex of the edge - * @return true if the ray intersects with the edge, false otherwise - */ - private boolean rayCastIntersect(LatLng point, LatLng vertA, LatLng vertB) { - double aY = vertA.latitude; - double bY = vertB.latitude; - double aX = vertA.longitude; - double bX = vertB.longitude; - double pY = point.latitude; - double pX = point.longitude; - - // Check if the point is horizontally aligned with the edge - if ((aY > pY && bY > pY) || (aY < pY && bY < pY) || (aX < pX && bX < pX)) { - return false; - } - - // Calculate the slope of the edge - double m = (aY - bY) / (aX - bX); - // Calculate the y-intercept of the edge - double bee = -aX * m + aY; - // Calculate the x-coordinate of the intersection point of the ray and the edge - double x = (pY - bee) / m; - - // Return true if the intersection point is to the right of the point - return x > pX; - } -} diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/PathView.java b/app/src/main/java/com/openpositioning/PositionMe/utils/PathView.java index 5a5efa8d..6627329f 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/utils/PathView.java +++ b/app/src/main/java/com/openpositioning/PositionMe/utils/PathView.java @@ -7,20 +7,17 @@ import android.graphics.Path; import android.util.AttributeSet; import android.view.View; - import com.openpositioning.PositionMe.presentation.fragment.CorrectionFragment; import com.openpositioning.PositionMe.sensors.SensorFusion; - import java.util.ArrayList; import java.util.Collections; /** - * This View class displays the path taken in the UI. - * A path of straight lines is drawn based on PDR coordinates. The coordinates are passed to - * PathView by calling method {@link PathView#drawTrajectory(float[])} in {@link SensorFusion}. - * The coordinates are scaled and centered in {@link PathView#scaleTrajectory()} to fill the - * device's screen. The scaling ratio is passed to the {@link CorrectionFragment} for calculating - * the Google Maps zoom ratio. + * This View class displays the path taken in the UI. A path of straight lines is drawn based on PDR + * coordinates. The coordinates are passed to PathView by calling method {@link + * PathView#drawTrajectory(float[])} in {@link SensorFusion}. The coordinates are scaled and + * centered in {@link PathView#scaleTrajectory()} to fill the device's screen. The scaling ratio is + * passed to the {@link CorrectionFragment} for calculating the Google Maps zoom ratio. * * @author Michal Dvorak * @author Virginia Cangelosi @@ -41,18 +38,18 @@ public class PathView extends View { private CorrectionFragment correctionFragment = new CorrectionFragment(); // Boolean flag to avoid rescaling trajectory when view is redrawn private static boolean firstTimeOnDraw = true; - //Variable to only draw when the variable is true + // Variable to only draw when the variable is true private static boolean draw = true; - //Variable to only draw when the variable is true + // Variable to only draw when the variable is true private static boolean reDraw = false; /** * Public default constructor for PathView. The constructor initialises the view with a context - * and attribute set, sets the view as focusable and focusable in touch mode and calls - * {@link PathView#setupPaint()} to initialise the paint object with colour and style. + * and attribute set, sets the view as focusable and focusable in touch mode and calls {@link + * PathView#setupPaint()} to initialise the paint object with colour and style. * - * @param context Application Context to be used for permissions and device accesses. - * @param attrs The attribute set of the view. + * @param context Application Context to be used for permissions and device accesses. + * @param attrs The attribute set of the view. */ public PathView(Context context, AttributeSet attrs) { super(context, attrs); @@ -83,56 +80,56 @@ private void setupPaint() { /** * {@inheritDoc} * - * Method drawing the created path with our paint. + *

Method drawing the created path with our paint. * * @param canvas The canvas on which the path will be drawn */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); - //If drawing for first time scale trajectory to fit screen - if(this.draw){ + // If drawing for first time scale trajectory to fit screen + if (this.draw) { // If there are no coordinates, don't draw anything - if (xCoords.size() == 0) - return; + if (xCoords.size() == 0) return; - //Scale trajectory to fit screen + // Scale trajectory to fit screen scaleTrajectory(); // Start a new path at the center of the view - path.moveTo(getWidth()/2, getHeight()/2); + path.moveTo(getWidth() / 2, getHeight() / 2); // Draw line between last point and this point for (int i = 1; i < xCoords.size(); i++) { path.lineTo(xCoords.get(i), yCoords.get(i)); } - //Draw path + // Draw path canvas.drawPath(path, drawPaint); - //Ensure path not redrawn + // Ensure path not redrawn draw = false; } - //If redrawing due to scaling of the average step length - else if(reDraw){ + // If redrawing due to scaling of the average step length + else if (reDraw) { // If there are no coordinates, don't draw anything - if (xCoords.size() == 0) - return; + if (xCoords.size() == 0) return; - //Clear old path + // Clear old path path.reset(); - // Iterate over all coordinates, shifting to the center and scaling then returning to original location + // Iterate over all coordinates, shifting to the center and scaling then returning to + // original location for (int i = 0; i < xCoords.size(); i++) { - float newXCoord = (xCoords.get(i) - getWidth()/2) * scalingRatio + getWidth()/2; + float newXCoord = (xCoords.get(i) - getWidth() / 2) * scalingRatio + getWidth() / 2; xCoords.set(i, newXCoord); - float newYCoord = (yCoords.get(i) - getHeight()/2) * scalingRatio + getHeight()/2; + float newYCoord = + (yCoords.get(i) - getHeight() / 2) * scalingRatio + getHeight() / 2; yCoords.set(i, newYCoord); } // Start a new path at the center of the view - path.moveTo(getWidth()/2, getHeight()/2); + path.moveTo(getWidth() / 2, getHeight() / 2); // Draw line between last point and this point for (int i = 1; i < xCoords.size(); i++) { @@ -141,17 +138,15 @@ else if(reDraw){ canvas.drawPath(path, drawPaint); - //Ensure path not redrawn when screen is resized + // Ensure path not redrawn when screen is resized reDraw = false; - } - else{ + } else { // If there are no coordinates, don't draw anything - if (xCoords.size() == 0) - return; + if (xCoords.size() == 0) return; // Start a new path at the center of the view - path.moveTo(getWidth()/2, getHeight()/2); + path.moveTo(getWidth() / 2, getHeight() / 2); // Draw line between last point and this point for (int i = 1; i < xCoords.size(); i++) { @@ -177,9 +172,8 @@ public void drawTrajectory(float[] newCords) { } /** - * Method used for scaling PDR coordinates to fill the screen. - * Center of the view is used as the origin, scaling ratio is calculated for the path to fit - * the screen with margins included. + * Method used for scaling PDR coordinates to fill the screen. Center of the view is used as the + * origin, scaling ratio is calculated for the path to fit the screen with margins included. */ private void scaleTrajectory() { // Get the center coordinates of the view @@ -193,7 +187,8 @@ private void scaleTrajectory() { float yBottomRange = (getHeight() / 2) / (Math.abs(Collections.min(yCoords))); // Take the minimum scaling ratio to ensure all points fit within the view - float minRatio = Math.min(Math.min(xRightRange, xLeftRange), Math.min(yTopRange, yBottomRange)); + float minRatio = + Math.min(Math.min(xRightRange, xLeftRange), Math.min(yTopRange, yBottomRange)); // Add margins to the scaling ratio scalingRatio = 0.9f * minRatio; @@ -217,8 +212,8 @@ private void scaleTrajectory() { } /** - * Method called when PathView is detached from its window. {@link PathView#xCoords} and - * {@link PathView#yCoords} are cleared so that path can start from 0 for next recording. + * Method called when PathView is detached from its window. {@link PathView#xCoords} and {@link + * PathView#yCoords} are cleared so that path can start from 0 for next recording. */ @Override protected void onDetachedFromWindow() { @@ -226,22 +221,21 @@ protected void onDetachedFromWindow() { // Reset trajectory xCoords.clear(); yCoords.clear(); - //New recording so must scale trajectory + // New recording so must scale trajectory draw = true; } /** - * Redraw trajectory to rescale the path. - * Called by {@link CorrectionFragment} through {@link SensorFusion} to reset the scaling ratio - * which will resize the path. It enables the redraw flag so new path is drawn. + * Redraw trajectory to rescale the path. Called by {@link CorrectionFragment} through {@link + * SensorFusion} to reset the scaling ratio which will resize the path. It enables the redraw + * flag so new path is drawn. * * @param newScale */ - public void redraw(float newScale){ - //Set scaling ratio based on user input + public void redraw(float newScale) { + // Set scaling ratio based on user input scalingRatio = newScale; - //Enable redrawing of path + // Enable redrawing of path reDraw = true; } - } diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/PdrProcessing.java b/app/src/main/java/com/openpositioning/PositionMe/utils/PdrProcessing.java index 9765b044..7a625f52 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/utils/PdrProcessing.java +++ b/app/src/main/java/com/openpositioning/PositionMe/utils/PdrProcessing.java @@ -3,21 +3,18 @@ import android.content.Context; import android.content.SharedPreferences; import android.hardware.SensorManager; - import androidx.preference.PreferenceManager; - import com.openpositioning.PositionMe.sensors.SensorFusion; - import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.OptionalDouble; import java.util.Objects; +import java.util.OptionalDouble; import java.util.stream.Collectors; /** - * Processes data recorded in the {@link SensorFusion} class and calculates live PDR estimates. - * It calculates the position from the steps and directions detected, using either estimated values + * Processes data recorded in the {@link SensorFusion} class and calculates live PDR estimates. It + * calculates the position from the steps and directions detected, using either estimated values * (eg. stride length from the Weiberg algorithm) or provided constants, calculates the elevation * and attempts to estimate the current floor as well as elevators. * @@ -26,7 +23,6 @@ */ public class PdrProcessing { - //region Static variables // Weiberg algorithm coefficient for stride calculations private static final float K = 0.364f; // Number of samples (seconds) to keep as memory for elevation calculation @@ -38,9 +34,7 @@ public class PdrProcessing { // Threshold under which movement is considered non-existent private static final float epsilon = 0.18f; private static final int MIN_REQUIRED_SAMPLES = 2; - //endregion - //region Instance variables // Settings for accessing shared variables private SharedPreferences settings; @@ -71,20 +65,19 @@ public class PdrProcessing { // Step sum and length aggregation variables private float sumStepLength = 0; private int stepCount = 0; - //endregion /** - * Public constructor for the PDR class. - * Takes context for variable access. Sets initial values based on settings. + * Public constructor for the PDR class. Takes context for variable access. Sets initial values + * based on settings. * - * @param context Application context for variable access. + * @param context Application context for variable access. */ public PdrProcessing(Context context) { // Initialise settings this.settings = PreferenceManager.getDefaultSharedPreferences(context); // Check if estimate or manual values should be used this.useManualStep = this.settings.getBoolean("manual_step_values", false); - if(useManualStep) { + if (useManualStep) { try { // Retrieve manual step length this.stepLength = this.settings.getInt("user_step_length", 75) / 100f; @@ -93,8 +86,7 @@ public PdrProcessing(Context context) { this.stepLength = 0.75f; this.settings.edit().putInt("user_step_length", 75).apply(); } - } - else { + } else { // Using estimated step length - set to zero this.stepLength = 0; } @@ -104,16 +96,20 @@ public PdrProcessing(Context context) { this.positionY = 0f; this.elevation = 0f; - - if(this.settings.getBoolean("overwrite_constants", false)) { + if (this.settings.getBoolean("overwrite_constants", false)) { // Capacity - pressure is read with 1Hz - store values of past 10 seconds - this.elevationList = new CircularFloatBuffer(Integer.parseInt(settings.getString("elevation_seconds", "4"))); + this.elevationList = + new CircularFloatBuffer( + Integer.parseInt(settings.getString("elevation_seconds", "4"))); // Buffer for most recent acceleration values - this.verticalAccel = new CircularFloatBuffer(Integer.parseInt(settings.getString("accel_samples", "4"))); - this.horizontalAccel = new CircularFloatBuffer(Integer.parseInt(settings.getString("accel_samples", "4"))); - } - else { + this.verticalAccel = + new CircularFloatBuffer( + Integer.parseInt(settings.getString("accel_samples", "4"))); + this.horizontalAccel = + new CircularFloatBuffer( + Integer.parseInt(settings.getString("accel_samples", "4"))); + } else { // Capacity - pressure is read with 1Hz - store values of past 10 seconds this.elevationList = new CircularFloatBuffer(elevationSeconds); @@ -131,32 +127,35 @@ public PdrProcessing(Context context) { } /** - * Function to calculate PDR coordinates from sensor values. - * Should be called from the step detector sensor's event with the sensor values since the last - * step. + * Function to calculate PDR coordinates from sensor values. Should be called from the step + * detector sensor's event with the sensor values since the last step. * - * @param currentStepEnd relative time in milliseconds since the start of the recording. - * @param accelMagnitudeOvertime recorded acceleration magnitudes since the last step. - * @param headingRad heading relative to magnetic north in radians. + * @param currentStepEnd relative time in milliseconds since the start of the recording. + * @param accelMagnitudeOvertime recorded acceleration magnitudes since the last step. + * @param headingRad heading relative to magnetic north in radians. */ - public float[] updatePdr(long currentStepEnd, List accelMagnitudeOvertime, float headingRad) { - if (accelMagnitudeOvertime == null || accelMagnitudeOvertime.size() < MIN_REQUIRED_SAMPLES) { - return new float[]{this.positionX, this.positionY}; // Return current position without update - // - TODO - temporary solution of the empty list issue + public float[] updatePdr( + long currentStepEnd, List accelMagnitudeOvertime, float headingRad) { + if (accelMagnitudeOvertime == null + || accelMagnitudeOvertime.size() < MIN_REQUIRED_SAMPLES) { + return new float[] { + this.positionX, this.positionY, 0.0f, 0.0f + }; // Return current position without update + // TODO - temporary solution of the empty list issue } // Change angle so zero rad is east - float adaptedHeading = (float) (Math.PI/2 - headingRad); + float adaptedHeading = (float) (Math.PI / 2 - headingRad); // check if accelMagnitudeOvertime is empty if (accelMagnitudeOvertime == null || accelMagnitudeOvertime.isEmpty()) { // return current position, do not update - return new float[]{this.positionX, this.positionY}; + return new float[] {this.positionX, this.positionY}; } - + // Calculate step length - if(!useManualStep) { - //ArrayList accelMagnitudeFiltered = filter(accelMagnitudeOvertime); + if (!useManualStep) { + // ArrayList accelMagnitudeFiltered = filter(accelMagnitudeOvertime); // Estimate stride this.stepLength = weibergMinMax(accelMagnitudeOvertime); // System.err.println("Step Length" + stepLength); @@ -167,39 +166,37 @@ public float[] updatePdr(long currentStepEnd, List accelMagnitudeOvertim stepCount++; // Translate to cartesian coordinate system - float x = (float) (stepLength * Math.cos(adaptedHeading)); - float y = (float) (stepLength * Math.sin(adaptedHeading)); + float dx = (float) (stepLength * Math.cos(adaptedHeading)); + float dy = (float) (stepLength * Math.sin(adaptedHeading)); // Update position values - this.positionX += x; - this.positionY += y; + this.positionX += dx; + this.positionY += dy; - // return current position - return new float[]{this.positionX, this.positionY}; + // return current position and delta values + return new float[] {this.positionX, this.positionY, dx, dy}; } /** - * Calculates the relative elevation compared to the start position. - * The start elevation is the median of the first three seconds of data to give the sensor time - * to settle. The sea level is irrelevant as only values relative to the initial position are - * reported. + * Calculates the relative elevation compared to the start position. The start elevation is the + * median of the first three seconds of data to give the sensor time to settle. The sea level is + * irrelevant as only values relative to the initial position are reported. * * @param absoluteElevation absolute elevation in meters compared to sea level. - * @return current elevation in meters relative to the start position. + * @return current elevation in meters relative to the start position. */ public float updateElevation(float absoluteElevation) { // Set start to median of first three values - if(setupIndex < 3) { + if (setupIndex < 3) { // Add values to buffer until it's full this.startElevationBuffer[setupIndex] = absoluteElevation; // When buffer is full, find median, assign as startElevation - if(setupIndex == 2) { + if (setupIndex == 2) { Arrays.sort(startElevationBuffer); startElevation = startElevationBuffer[1]; } this.setupIndex++; - } - else { + } else { // Get relative elevation in meters this.elevation = absoluteElevation - startElevation; // Add to buffer @@ -207,16 +204,16 @@ public float updateElevation(float absoluteElevation) { // Check if there was floor movement // Check if there is enough data to evaluate - if(this.elevationList.isFull()) { + if (this.elevationList.isFull()) { // Check average of elevation array List elevationMemory = this.elevationList.getListCopy(); OptionalDouble currentAvg = elevationMemory.stream().mapToDouble(f -> f).average(); float finishAvg = currentAvg.isPresent() ? (float) currentAvg.getAsDouble() : 0; // Check if we moved floor by comparing with start position - if(Math.abs(finishAvg - startElevation) > this.floorHeight) { + if (Math.abs(finishAvg - startElevation) > this.floorHeight) { // Change floors - 'floor' division - this.currentFloor += (finishAvg - startElevation)/this.floorHeight; + this.currentFloor += (finishAvg - startElevation) / this.floorHeight; } } // Return current elevation @@ -229,8 +226,8 @@ public float updateElevation(float absoluteElevation) { /** * Uses the Weiberg Stride Length formula to calculate step length from accelerometer values. * - * @param accelMagnitude magnitude of acceleration values between the last and current step. - * @return float stride length in meters. + * @param accelMagnitude magnitude of acceleration values between the last and current step. + * @return float stride length in meters. */ private float weibergMinMax(List accelMagnitude) { // if the list itself is null or empty, return 0 (or return other default values as needed) @@ -239,9 +236,8 @@ private float weibergMinMax(List accelMagnitude) { } // filter out null values from the list - List validAccel = accelMagnitude.stream() - .filter(Objects::nonNull) - .collect(Collectors.toList()); + List validAccel = + accelMagnitude.stream().filter(Objects::nonNull).collect(Collectors.toList()); if (validAccel.isEmpty()) { return 0f; } @@ -262,21 +258,19 @@ private float weibergMinMax(List accelMagnitude) { } /** - * Get the current X and Y coordinates from the PDR processing class. - * The coordinates are in meters, the start of the recording is the (0,0) + * Get the current X and Y coordinates from the PDR processing class. The coordinates are in + * meters, the start of the recording is the (0,0) * - * @return float array of size 2, with the X and Y coordinates respectively. + * @return float array of size 2, with the X and Y coordinates respectively. */ public float[] getPDRMovement() { - float [] pdrPosition= new float[] {positionX,positionY}; - return pdrPosition; - + return new float[] {positionX, positionY}; } /** * Get the current elevation as calculated by the PDR class. * - * @return current elevation in meters, relative to the start position. + * @return current elevation in meters, relative to the start position. */ public float getCurrentElevation() { return this.elevation; @@ -292,49 +286,55 @@ public int getCurrentFloor() { } /** - * Estimates if the user is currently taking an elevator. - * From the gravity and gravity-removed acceleration values the magnitude of horizontal and - * vertical acceleration is calculated and stored over time. Averaging these values and - * comparing with the thresholds set for this class, it estimates if the current movement - * matches what is expected from an elevator ride. + * Estimates if the user is currently taking an elevator. From the gravity and gravity-removed + * acceleration values the magnitude of horizontal and vertical acceleration is calculated and + * stored over time. Averaging these values and comparing with the thresholds set for this + * class, it estimates if the current movement matches what is expected from an elevator ride. * - * @param gravity array of size three, strength of gravity along the phone's x-y-z axis. - * @param acc array of size three, acceleration other than gravity detected by the phone. - * @return boolean true if currently in an elevator, false otherwise. + * @param gravity array of size three, strength of gravity along the phone's x-y-z axis. + * @param acc array of size three, acceleration other than gravity detected by the phone. + * @return boolean true if currently in an elevator, false otherwise. */ public boolean estimateElevator(float[] gravity, float[] acc) { // Standard gravity float g = SensorManager.STANDARD_GRAVITY; // get horizontal and vertical acceleration magnitude - float verticalAcc = (float) Math.sqrt( - Math.pow((acc[0] * gravity[0]/g),2) + - Math.pow((acc[1] * gravity[1]/g), 2) + - Math.pow((acc[2] * gravity[2]/g), 2)); - float horizontalAcc = (float) Math.sqrt( - Math.pow((acc[0] * (1 - gravity[0]/g)), 2) + - Math.pow((acc[1] * (1 - gravity[1]/g)), 2) + - Math.pow((acc[2] * (1 - gravity[2]/g)), 2)); + float verticalAcc = + (float) + Math.sqrt( + Math.pow((acc[0] * gravity[0] / g), 2) + + Math.pow((acc[1] * gravity[1] / g), 2) + + Math.pow((acc[2] * gravity[2] / g), 2)); + float horizontalAcc = + (float) + Math.sqrt( + Math.pow((acc[0] * (1 - gravity[0] / g)), 2) + + Math.pow((acc[1] * (1 - gravity[1] / g)), 2) + + Math.pow((acc[2] * (1 - gravity[2] / g)), 2)); // Save into buffer to compare with past values this.verticalAccel.putNewest(verticalAcc); this.horizontalAccel.putNewest(horizontalAcc); // Once buffer is full, evaluate data - if(this.verticalAccel.isFull() && this.horizontalAccel.isFull()) { + if (this.verticalAccel.isFull() && this.horizontalAccel.isFull()) { // calculate average vertical accel List verticalMemory = this.verticalAccel.getListCopy(); - OptionalDouble optVerticalAvg = verticalMemory.stream().mapToDouble(Math::abs).average(); - float verticalAvg = optVerticalAvg.isPresent() ? (float) optVerticalAvg.getAsDouble() : 0; - + OptionalDouble optVerticalAvg = + verticalMemory.stream().mapToDouble(Math::abs).average(); + float verticalAvg = + optVerticalAvg.isPresent() ? (float) optVerticalAvg.getAsDouble() : 0; // calculate average horizontal accel List horizontalMemory = this.horizontalAccel.getListCopy(); - OptionalDouble optHorizontalAvg = horizontalMemory.stream().mapToDouble(Math::abs).average(); - float horizontalAvg = optHorizontalAvg.isPresent() ? (float) optHorizontalAvg.getAsDouble() : 0; + OptionalDouble optHorizontalAvg = + horizontalMemory.stream().mapToDouble(Math::abs).average(); + float horizontalAvg = + optHorizontalAvg.isPresent() ? (float) optHorizontalAvg.getAsDouble() : 0; - //System.err.println("LIFT: Vertical: " + verticalAvg); - //System.err.println("LIFT: Horizontal: " + horizontalAvg); + // System.err.println("LIFT: Vertical: " + verticalAvg); + // System.err.println("LIFT: Horizontal: " + horizontalAvg); - if(this.settings.getBoolean("overwrite_constants", false)) { + if (this.settings.getBoolean("overwrite_constants", false)) { float eps = Float.parseFloat(settings.getString("epsilon", "0.18")); return horizontalAvg < eps && verticalAvg > movementThreshold; } @@ -342,17 +342,16 @@ public boolean estimateElevator(float[] gravity, float[] acc) { return horizontalAvg < epsilon && verticalAvg > movementThreshold; } return false; - } /** - * Resets all values stored in the PDR function and re-initialises all buffers. - * Used to reset to zero position and remove existing history. + * Resets all values stored in the PDR function and re-initialises all buffers. Used to reset to + * zero position and remove existing history. */ public void resetPDR() { // Check if estimate or manual values should be used this.useManualStep = this.settings.getBoolean("manual_step_values", false); - if(useManualStep) { + if (useManualStep) { try { // Retrieve manual step length this.stepLength = this.settings.getInt("user_step_length", 75) / 100f; @@ -361,8 +360,7 @@ public void resetPDR() { this.stepLength = 0.75f; this.settings.edit().putInt("user_step_length", 75).apply(); } - } - else { + } else { // Using estimated step length - set to zero this.stepLength = 0; } @@ -372,15 +370,20 @@ public void resetPDR() { this.positionY = 0f; this.elevation = 0f; - if(this.settings.getBoolean("overwrite_constants", false)) { + if (this.settings.getBoolean("overwrite_constants", false)) { // Capacity - pressure is read with 1Hz - store values of past 10 seconds - this.elevationList = new CircularFloatBuffer(Integer.parseInt(settings.getString("elevation_seconds", "4"))); + this.elevationList = + new CircularFloatBuffer( + Integer.parseInt(settings.getString("elevation_seconds", "4"))); // Buffer for most recent acceleration values - this.verticalAccel = new CircularFloatBuffer(Integer.parseInt(settings.getString("accel_samples", "4"))); - this.horizontalAccel = new CircularFloatBuffer(Integer.parseInt(settings.getString("accel_samples", "4"))); - } - else { + this.verticalAccel = + new CircularFloatBuffer( + Integer.parseInt(settings.getString("accel_samples", "4"))); + this.horizontalAccel = + new CircularFloatBuffer( + Integer.parseInt(settings.getString("accel_samples", "4"))); + } else { // Capacity - pressure is read with 1Hz - store values of past 10 seconds this.elevationList = new CircularFloatBuffer(elevationSeconds); @@ -395,23 +398,19 @@ public void resetPDR() { this.startElevationBuffer = new Float[3]; // Start floor - assumed to be zero this.currentFloor = 0; + this.stepCount = 0; + this.sumStepLength = 0f; } /** * Getter for the average step length calculated from the aggregated distance and step count. * - * @return average step length in meters. + * @return average step length in meters. */ - public float getAverageStepLength(){ - //Calculate average step length - float averageStepLength = sumStepLength/(float) stepCount; + public float getAverageStepLength() { + if (stepCount == 0) return 0f; - //Reset sum and number of steps - stepCount = 0; - sumStepLength = 0; - - //Return average step length - return averageStepLength; + // Return average step length + return sumStepLength / (float) stepCount; } - } diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/PermissionConstants.java b/app/src/main/java/com/openpositioning/PositionMe/utils/PermissionConstants.java new file mode 100644 index 00000000..63cdfddd --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/utils/PermissionConstants.java @@ -0,0 +1,44 @@ +package com.openpositioning.PositionMe.utils; + +import android.Manifest; +import android.annotation.SuppressLint; + +/** + * Centralised definitions of 'dangerous' permissions required by PositionMe. + * + *

Note that some permissions are unavailable in certain Android SDK versions. + * + * @see PermissionManager + */ +public class PermissionConstants { + public static final String[] PERMISSIONS_LOCATION = + new String[] { + Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION + }; + + @SuppressLint("InlinedApi") + public static final String[] PERMISSIONS_API_29 = + new String[] {Manifest.permission.ACTIVITY_RECOGNITION}; + + @SuppressLint("InlinedApi") + public static final String[] PERMISSIONS_API_33 = + new String[] {Manifest.permission.NEARBY_WIFI_DEVICES}; + + @SuppressLint("InlinedApi") + public static final String[] PERMISSIONS_API_34 = + new String[] {Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED}; + + @SuppressLint("InlinedApi") + public static final String[] PERMISSIONS_STORAGE_MODERN = + new String[] { + Manifest.permission.READ_MEDIA_AUDIO, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.READ_MEDIA_VIDEO + }; + + public static final String[] PERMISSIONS_STORAGE_LEGACY = + new String[] { + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE + }; +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/PermissionManager.java b/app/src/main/java/com/openpositioning/PositionMe/utils/PermissionManager.java index 40c937ab..45966320 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/utils/PermissionManager.java +++ b/app/src/main/java/com/openpositioning/PositionMe/utils/PermissionManager.java @@ -1,6 +1,10 @@ package com.openpositioning.PositionMe.utils; -import android.Manifest; +import static com.openpositioning.PositionMe.utils.PermissionConstants.PERMISSIONS_API_29; +import static com.openpositioning.PositionMe.utils.PermissionConstants.PERMISSIONS_API_33; +import static com.openpositioning.PositionMe.utils.PermissionConstants.PERMISSIONS_LOCATION; +import static com.openpositioning.PositionMe.utils.PermissionConstants.PERMISSIONS_STORAGE_LEGACY; + import android.app.Activity; import android.app.AlertDialog; import android.content.Intent; @@ -8,177 +12,209 @@ import android.net.Uri; import android.os.Build; import android.provider.Settings; -import android.widget.Toast; - -import androidx.annotation.RequiresApi; +import android.util.Log; +import androidx.activity.result.ActivityResultCaller; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; - +import com.openpositioning.PositionMe.presentation.activity.MainActivity; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.ListIterator; +import java.util.Set; /** - * A helper class responsible for checking and requesting all dangerous permissions - * that the application needs in order to function. + * A helper class responsible for checking and requesting all dangerous permissions that the + * application needs in order to function. + * + *

This class: + * + *

- Manages the permissions list. * - * This class: - * - Manages the permissions list. - * - Checks if all permissions are granted. - * - Requests missing permissions. - * - Handles both the first-time and permanent denial scenarios. + *

- Checks if all permissions are granted. * - * Usage from MainActivity: - * PermissionManager permissionManager = new PermissionManager(MainActivity.this, new PermissionManager.PermissionCallback() { - * @Override - * public void onAllPermissionsGranted() { - * // e.g. call allPermissionsObtained() in MainActivity - * allPermissionsObtained(); - * } - * }); - * permissionManager.checkAndRequestPermissions(); + *

- Requests missing permissions. + * + *

- Handles both the first-time and permanent denial scenarios. + * + * @see MainActivity MainActivity */ public class PermissionManager { - - private static final int ALL_PERMISSIONS_REQUEST = 100; + private static final String TAG = "PermissionManager"; private final Activity activity; - private final PermissionCallback callback; + private ActivityResultLauncher multiplePermissionsLauncher; + + boolean allPermissionsGranted = false; + // Flag to prevent overlapping AlertBoxes + boolean boxShowing = false; // The list of dangerous permissions needed by this app. private final List requiredPermissions = new ArrayList<>(); + private List missingPermissions = new ArrayList<>(); - @RequiresApi(api = Build.VERSION_CODES.Q) - public PermissionManager(Activity activity, PermissionCallback callback) { + public PermissionManager( + Activity activity, ActivityResultCaller caller, PermissionCallback callback) { this.activity = activity; - this.callback = callback; - - // Populate required permissions - requiredPermissions.add(Manifest.permission.ACCESS_FINE_LOCATION); - requiredPermissions.add(Manifest.permission.ACCESS_COARSE_LOCATION); - requiredPermissions.add(Manifest.permission.ACCESS_WIFI_STATE); - requiredPermissions.add(Manifest.permission.CHANGE_WIFI_STATE); - // For API < 29, also request broad storage permissions - // For API >= 29, also request ACTIVITY_RECOGNITION - // (We can do the check here or just always add them; the OS will skip as needed.) - requiredPermissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); - requiredPermissions.add(Manifest.permission.READ_EXTERNAL_STORAGE); - requiredPermissions.add(Manifest.permission.ACTIVITY_RECOGNITION); - } - /** - * Checks if all required permissions are already granted; if not, requests them. - */ - public void checkAndRequestPermissions() { - if (!hasAllPermissions()) { - ActivityCompat.requestPermissions( - activity, - requiredPermissions.toArray(new String[0]), - ALL_PERMISSIONS_REQUEST - ); + int buildSDK = Build.VERSION.SDK_INT; + requiredPermissions.addAll(Arrays.asList(PERMISSIONS_LOCATION)); + if (buildSDK >= Build.VERSION_CODES.Q) { + requiredPermissions.addAll(Arrays.asList(PERMISSIONS_API_29)); } else { - // Already granted - callback.onAllPermissionsGranted(); + requiredPermissions.addAll(Arrays.asList(PERMISSIONS_STORAGE_LEGACY)); + } + if (buildSDK >= Build.VERSION_CODES.TIRAMISU) { + requiredPermissions.addAll(Arrays.asList(PERMISSIONS_API_33)); } + + // Register multiple permissions launcher + multiplePermissionsLauncher = + caller.registerForActivityResult( + new ActivityResultContracts.RequestMultiplePermissions(), + results -> { + Log.d(TAG, "Now checking " + results.size() + " permissions"); + if (results.isEmpty()) { + allPermissionsGranted = false; + } else { + Set permissions = results.keySet(); + allPermissionsGranted = true; + for (String permission : permissions) { + boolean result = Boolean.TRUE.equals(results.get(permission)); + if (!result) { + Log.w(TAG, "Permission Denied: " + permission); + allPermissionsGranted = false; + if (!missingPermissions.contains(permission)) { + missingPermissions.add(permission); + } + } else if (missingPermissions.contains(permission)) { + missingPermissions.remove(permission); + } + } + } + callback.onAllPermissionsGranted( + allPermissionsGranted, missingPermissions); + }); } - /** - * Must be called from the Activity's onRequestPermissionsResult: - * - * @Override - * public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { - * super.onRequestPermissionsResult(requestCode, permissions, grantResults); - * permissionManager.handleRequestPermissionsResult(requestCode, permissions, grantResults); - * } - */ - public void handleRequestPermissionsResult(int requestCode, - String[] permissions, - int[] grantResults) { - if (requestCode == ALL_PERMISSIONS_REQUEST) { - boolean allGranted = true; - List deniedPermissions = new ArrayList<>(); - - for (int i = 0; i < permissions.length; i++) { - if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { - allGranted = false; - deniedPermissions.add(permissions[i]); - } - } + /** Checks if all required permissions are already granted; if not, requests them. */ + public void checkAndRequestPermissions() { + multiplePermissionsLauncher.launch(requiredPermissions.toArray(new String[0])); + } - if (allGranted) { - Toast.makeText(activity, "All permissions granted!", Toast.LENGTH_SHORT).show(); - callback.onAllPermissionsGranted(); - } else { - // Check if any denied permission is permanently denied. - boolean permanentlyDenied = false; - for (String perm : deniedPermissions) { - // If shouldShowRequestPermissionRationale returns false => permanently denied - if (!ActivityCompat.shouldShowRequestPermissionRationale(activity, perm)) { - permanentlyDenied = true; - break; - } - } - if (permanentlyDenied) { - showPermanentDenialDialog(); - } else { - showFirstDenialDialog(); - } + public void checkMissingPermissions() { + Log.d(TAG, "Checking " + missingPermissions.size() + " missing permissions"); + ListIterator iterator = missingPermissions.listIterator(); + while (iterator.hasNext()) { + String permission = iterator.next(); + if (ContextCompat.checkSelfPermission(activity, permission) + == PackageManager.PERMISSION_GRANTED) { + Log.d(TAG, "Permission " + permission + " now granted!"); + iterator.remove(); } } + Log.d(TAG, "Now missing " + missingPermissions.size() + " permissions"); + confirmDeniedPermissions(missingPermissions); } /** - * Checks if the app has all the required permissions granted. + * Must be called from the Activity's onRequestPermissionsResult + * + *

Override public void onRequestPermissionsResult( int requestCode, String[] permissions, + * int[] results) {super.onRequestPermissionsResult(requestCode, permissions, results); + * permissionManager.handleRequestPermissionsResult(requestCode, permissions, results); } */ - private boolean hasAllPermissions() { - for (String perm : requiredPermissions) { - if (ContextCompat.checkSelfPermission(activity, perm) != PackageManager.PERMISSION_GRANTED) { - return false; + public void confirmDeniedPermissions(List deniedPermissions) { + // Check if any denied permission is permanently denied. + ArrayList permanentlyDenied = new ArrayList<>(); + ArrayList tentativelyDenied = new ArrayList<>(); + for (String permission : deniedPermissions) { + // If shouldShowRequestPermissionRationale returns false => permanently denied + if (!ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) { + permanentlyDenied.add(permission); + } else { + tentativelyDenied.add(permission); } } - return true; + + if (!permanentlyDenied.isEmpty()) { + showPermanentDenialDialog(); + } + if (!tentativelyDenied.isEmpty()) { + showFirstDenialDialog(); + } } - /** - * Shows an AlertDialog if the user has denied permissions for the first time. - */ + /** Shows an AlertDialog if the user has denied permissions for the first time. */ private void showFirstDenialDialog() { - if (!activity.isFinishing()) { + if (!activity.isFinishing() && !activity.isDestroyed()) { + if (boxShowing) { + Log.w(TAG, "Box already showing. Skipping new first denial box"); + return; + } + boxShowing = true; + Log.i(TAG, "Displaying the first denial box"); new AlertDialog.Builder(activity) .setTitle("Permissions Denied") - .setMessage("Certain permissions are essential for this app to function.\n" + - "Tap GRANT to try again or EXIT to close the app.") + .setMessage( + "Certain permissions are essential for this app to function.\n" + + "Tap GRANT to try again or EXIT to close the app.") .setCancelable(false) - .setPositiveButton("Grant", (dialog, which) -> checkAndRequestPermissions()) - .setNegativeButton("Exit", (dialog, which) -> activity.finish()) + .setPositiveButton( + "Grant", + (dialog, which) -> { + boxShowing = false; + checkAndRequestPermissions(); + }) + .setNegativeButton( + "Exit", + (dialog, which) -> { + boxShowing = false; + activity.finish(); + }) .show(); } } - /** - * Shows an AlertDialog if the user has permanently denied the permissions. - */ + /** Shows an AlertDialog if the user has permanently denied the permissions. */ private void showPermanentDenialDialog() { - if (!activity.isFinishing()) { + if (!activity.isFinishing() && !activity.isDestroyed()) { + if (boxShowing) { + Log.w(TAG, "Box already showing. Skipping new permanent denial box"); + return; + } + boxShowing = true; + Log.i(TAG, "Displaying the permanent denial box"); new AlertDialog.Builder(activity) - .setTitle("Permission Permanently Denied") - .setMessage("Some permissions have been permanently denied. " + - "Please go to Settings to enable them manually.") + .setTitle("Permissions Permanently Denied") + .setMessage( + "Some permissions have been permanently denied. " + + "Please go to Settings to enable them manually.") .setCancelable(false) - .setPositiveButton("Settings", (dialog, which) -> { - Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); - Uri uri = Uri.fromParts("package", activity.getPackageName(), null); - intent.setData(uri); - activity.startActivity(intent); - }) - .setNegativeButton("Exit", (dialog, which) -> activity.finish()) + .setPositiveButton( + "Settings", + (dialog, which) -> { + boxShowing = false; + Intent intent = + new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + Uri uri = Uri.fromParts("package", activity.getPackageName(), null); + intent.setData(uri); + activity.startActivity(intent); + }) + .setNegativeButton( + "Exit", + (dialog, which) -> { + boxShowing = false; + activity.finish(); + }) .show(); } } - /** - * Callback to notify the calling Activity when all permissions have been granted. - */ + /** Callback to notify the calling Activity when all permissions have been granted. */ public interface PermissionCallback { - void onAllPermissionsGranted(); + void onAllPermissionsGranted(boolean allPermissionsGranted, List deniedPermissions); } } diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/UtilConstants.java b/app/src/main/java/com/openpositioning/PositionMe/utils/UtilConstants.java new file mode 100644 index 00000000..ad95a377 --- /dev/null +++ b/app/src/main/java/com/openpositioning/PositionMe/utils/UtilConstants.java @@ -0,0 +1,52 @@ +package com.openpositioning.PositionMe.utils; + +import com.openpositioning.PositionMe.BuildConfig; + +public class UtilConstants { + + public static final float LINE_WEIGHT_PATH = 5f; + + public static final float ZOOM_LEVEL_DEFAULT = 19f; + + public static final float POSITION_UOE_LAT = 55.944425f; + public static final float POSITION_UOE_LON = -3.188396f; + + // Credentials + public static final String CREDENTIALS_FILE_NAME = "login_details"; + public static final String CREDENTIALS_KEY_EMAIL = "email"; + public static final String CREDENTIALS_KEY_PASSWORD = "password"; + + // Source: https://openpositioning.org/docs + public static final String API_KEY_MASTER = BuildConfig.OPENPOSITIONING_MASTER_KEY; + public static final String URL_API = "https://openpositioning.org/api"; + public static final String API_GET_USER_TRAJECTORIES = "/live/users/trajectories"; + public static final String API_GET_TRAJECTORIES = "/live/trajectory/download"; + public static final String API_POST_TRAJECTORIES = "/live/trajectory/upload"; + public static final String API_POST_FLOORPLANS = "/live/floorplan/request"; + public static final String API_POST_SIGN_UP = "/users/signup"; + public static final String API_POST_LOGIN = "/users/login"; + public static final String API_POST_WIFI_COARSE = "/position/coarse"; + public static final String API_POST_WIFI_FINE = "/position/fine"; + + public static final String URL_GET_USER_TRAJECTORIES = URL_API + API_GET_USER_TRAJECTORIES; + + // URL is in two parts as user variable is inserted for number of entries to retrieve + public static final String URL_GET_TRAJECTORIES_HEAD = URL_API + API_GET_TRAJECTORIES; + public static final String URL_GET_TRAJECTORIES_TAIL = "&key=" + API_KEY_MASTER; + public static final String URL_POST_FLOORPLANS = URL_API + API_POST_FLOORPLANS; + public static final String PROTOCOL_MULTIPART = "multipart/form-data"; + public static final String PROTOCOL_APP_JSON = "application/json"; + + // Expected responses from floor plan API request + public static final String BUILDING_NAME_NUCLEUS = "nucleus_building"; + public static final String BUILDING_NAME_M_HOUSE = "murchison_house"; + public static final String BUILDING_NAME_OUTSIDE = "outside"; + + // The minimum time between sensor readings in milliseconds + public static final int SENSOR_POLL_TIME_MS = 20; + public static final int FLOOR_PLAN_POLL_TIME_MS = 1000; + public static final int ACCELERATION_MAGNITUDE_MAXIMUM_SIZE = 20000; + public static final float ALPHA_PRESSURE_DEFAULT = 0.2f; + + public static final String DEBUG_MODE_HEADER = "[Debug] "; +} diff --git a/app/src/main/java/com/openpositioning/PositionMe/utils/UtilFunctions.java b/app/src/main/java/com/openpositioning/PositionMe/utils/UtilFunctions.java index 56a88aa3..064ae645 100644 --- a/app/src/main/java/com/openpositioning/PositionMe/utils/UtilFunctions.java +++ b/app/src/main/java/com/openpositioning/PositionMe/utils/UtilFunctions.java @@ -4,80 +4,94 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.Drawable; - import androidx.core.content.ContextCompat; - import com.google.android.gms.maps.model.LatLng; import com.openpositioning.PositionMe.presentation.fragment.RecordingFragment; /** * Class containing utility functions which can used by other classes. + * * @see RecordingFragment Currently used by RecordingFragment */ public class UtilFunctions { // Constant 1degree of latitiude/longitude (in m) - private static final int DEGREE_IN_M=111111; + private static final int DEGREE_IN_M = 111111; + /** * Simple function to calculate the angle between two close points + * * @param pointA Starting point * @param pointB Ending point * @return Angle between the points */ public static double calculateAngleSimple(LatLng pointA, LatLng pointB) { // Simple formula for close-by points - return Math.toDegrees( Math.atan2(pointB.latitude-pointA.latitude, - (pointB.longitude- pointA.longitude)*Math.cos(Math.toRadians(pointA.latitude)))); + return Math.toDegrees( + Math.atan2( + pointB.latitude - pointA.latitude, + (pointB.longitude - pointA.longitude) + * Math.cos(Math.toRadians(pointA.latitude)))); } /** - * Calculate new coordinates based on net distance moved in PDR - * (as per WGS84 datum) + * Calculate new coordinates based on net distance moved in PDR (as per WGS84 datum) + * * @param initialLocation Current Location of user * @param pdrMoved Amount of movement along X and Y * @return new Coordinates based on the movement */ - public static LatLng calculateNewPos(LatLng initialLocation,float[] pdrMoved){ + public static LatLng calculateNewPos(LatLng initialLocation, float[] pdrMoved) { // Changes Euclidean movement into maps latitude and longitude as per WGS84 datum - double newLatitude=initialLocation.latitude+(pdrMoved[1]/(DEGREE_IN_M)); - double newLongitude = initialLocation.longitude + ( - pdrMoved[0] / (DEGREE_IN_M * Math.cos(Math.toRadians(initialLocation.latitude))) - ); + double newLatitude = initialLocation.latitude + (pdrMoved[1] / (DEGREE_IN_M)); + double newLongitude = + initialLocation.longitude + + (pdrMoved[0] + / (DEGREE_IN_M + * Math.cos(Math.toRadians(initialLocation.latitude)))); return new LatLng(newLatitude, newLongitude); } + /** - * Converts a degree value of Latitude into meters - * (as per WGS84 datum) + * Converts a degree value of Latitude into meters (as per WGS84 datum) + * * @param degreeVal Value in degrees to convert to meters * @return double corresponding to the value in meters. */ public static double degreesToMetersLat(double degreeVal) { - return degreeVal*DEGREE_IN_M; + return degreeVal * DEGREE_IN_M; } + /** - * Converts a degree value of Longitude into meters - * (as per WGS84 datum) + * Converts a degree value of Longitude into meters (as per WGS84 datum) + * * @param degreeVal Value in degrees to convert to meters * @param latitude the latitude of the current position * @return double corresponding to the value in meters. */ public static double degreesToMetersLng(double degreeVal, double latitude) { - return degreeVal*DEGREE_IN_M/Math.cos(Math.toRadians(latitude)); + return degreeVal * DEGREE_IN_M / Math.cos(Math.toRadians(latitude)); } /** - * Calculates the distance between two LatLng points A and B (in meters) - * (Note: approximation: for short distances) + * Calculates the distance between two LatLng points A and B (in meters) (Note: approximation: + * for short distances) + * * @param pointA initial point * @param pointB final point * @return the distance between the two points */ - public static double distanceBetweenPoints(LatLng pointA, LatLng pointB){ - return Math.sqrt(Math.pow(degreesToMetersLat(pointA.latitude-pointB.latitude),2) + - Math.pow(degreesToMetersLng(pointA.longitude-pointB.longitude,pointA.latitude),2)); + public static double distanceBetweenPoints(LatLng pointA, LatLng pointB) { + return Math.sqrt( + Math.pow(degreesToMetersLat(pointA.latitude - pointB.latitude), 2) + + Math.pow( + degreesToMetersLng( + pointA.longitude - pointB.longitude, pointA.latitude), + 2)); } /** * Creates a bitmap from a vector + * * @param context Context of activity being used * @param vectorResourceID Resource id whose vector get converted to a Bitmap * @return Bitmap of the resource vector @@ -86,7 +100,11 @@ public static Bitmap getBitmapFromVector(Context context, int vectorResourceID) // Get drawable vector Drawable vectorDrawable = ContextCompat.getDrawable(context, vectorResourceID); // Bitmap created to draw the vector in - Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + Bitmap bitmap = + Bitmap.createBitmap( + vectorDrawable.getIntrinsicWidth(), + vectorDrawable.getIntrinsicHeight(), + Bitmap.Config.ARGB_8888); // Canvas to draw the bitmap on Canvas canvas = new Canvas(bitmap); // Drawing on canvas @@ -94,5 +112,4 @@ public static Bitmap getBitmapFromVector(Context context, int vectorResourceID) vectorDrawable.draw(canvas); return bitmap; } - } diff --git a/app/src/main/proto/traj.proto b/app/src/main/proto/traj.proto index 95d8b0ac..03a0e464 100644 --- a/app/src/main/proto/traj.proto +++ b/app/src/main/proto/traj.proto @@ -1,149 +1,210 @@ syntax = "proto3"; message Trajectory { -string android_version = 1; -repeated Motion_Sample imu_data = 2; -repeated Pdr_Sample pdr_data = 3; -repeated Position_Sample position_data = 4; -repeated Pressure_Sample pressure_data = 5; -repeated Light_Sample light_data = 6; - -repeated GNSS_Sample gnss_data = 7; -repeated WiFi_Sample wifi_data = 8; -repeated AP_Data aps_data = 9; - -// UNIX timestamp (in milliseconds) recorded from the start of this -// trajectory data collection event. All future -// timestamps in sub classes are to be RELATIVE timestamps -// (in milliseconds) to this start time. -// E.g. -// start_timestamp = 1674819807315 (UTC 27 Jan 2023 in the morning) -// relative_timestamp = 3000 (3s) -int64 start_timestamp = 10; -string data_identifier = 11; -Sensor_Info accelerometer_info = 12; -Sensor_Info gyroscope_info = 13; -Sensor_Info rotation_vector_info = 14; -Sensor_Info magnetometer_info = 15; -Sensor_Info barometer_info = 16; -Sensor_Info light_sensor_info = 17; + string android_version = 1; + // version 2.0 + float trajectory_version = 2; + // trajectory id/name for identification + string trajectory_id = 3; + repeated IMUReading imu_data = 4; + repeated RelativePosition pdr_data = 5; + repeated MagnetometerReading magnetometer_data = 6; + repeated BarometerReading pressure_data = 7; + repeated LightReading light_data = 8; + repeated ProximityReading proximity_data = 9; + + repeated GNSSReading gnss_data = 10; + repeated Fingerprint wifi_fingerprints = 11; + repeated WiFiAPData aps_data = 12; + repeated WiFiRTTReading wifi_rtt_data = 13; + repeated Fingerprint ble_fingerprints = 14; + repeated BleData ble_data = 15; + + // UNIX timestamp (in milliseconds) recorded from the start of this + // trajectory data collection event. All future + // timestamps in sub classes are to be RELATIVE timestamps + // (in milliseconds) to this start time. + // E.g. + // start_timestamp = 1674819807315 (UTC 27 Jan 2023 in the morning) + // relative_timestamp = 3000 (3s) + int64 start_timestamp = 16; + GNSSPosition initial_position = 17; + repeated GNSSPosition corrected_positions = 18; + + SensorInfo accelerometer_info = 19; + SensorInfo gyroscope_info = 20; + SensorInfo rotation_vector_info = 21; + SensorInfo magnetometer_info = 22; + SensorInfo barometer_info = 23; + SensorInfo light_sensor_info = 24; + SensorInfo proximity_info = 25; + + repeated GNSSPosition test_points = 26; } -message Pdr_Sample { -// milliseconds from the start_timestamp -int64 relative_timestamp = 1; +message RelativePosition { + // milliseconds from the start_timestamp + int64 relative_timestamp = 1; -// Both in metres. You should implement an algorithm to estimate -// these values. The values are always relative to your start point -// so the first entry should always be x = 0.0, y = 0.0 -float x = 2; -float y = 3; + // Both in metres. You should implement an algorithm to estimate + // these values. The values are always relative to your start point + // so the first entry should always be x = 0.0, y = 0.0 + float x = 2; + float y = 3; } +message IMUReading { + // milliseconds + int64 relative_timestamp = 1; + // Accelerometer [m/s^2] + Vector3 acc = 2; + + // Gyroscope [radians/s] + Vector3 gyr = 3; -message Motion_Sample { - // milliseconds - int64 relative_timestamp = 1; - // m/s^2 - float acc_x = 2; - float acc_y = 3; - float acc_z = 4; + // Orientation [unitless], 4 components should square sum to ~1 + Quaternion rotation_vector = 4; - // radians/s - float gyr_x = 5; - float gyr_y = 6; - float gyr_z = 7; + // Number of steps so far + int32 step_count = 5; +} - // unitless, 4 components should sum to ~1 - float rotation_vector_x = 8; - float rotation_vector_y = 9; - float rotation_vector_z = 10; - float rotation_vector_w = 11; +message MagnetometerReading { + int64 relative_timestamp = 1; - // Integer - int32 step_count = 12; + // Magnetometer [uT] + Vector3 mag = 2; } -message Position_Sample { - int64 relative_timestamp = 1; +message BarometerReading { + int64 relative_timestamp = 1; - // uT - float mag_x = 2; - float mag_y = 3; - float mag_z = 4; + // mbar + float pressure = 2; } -message Pressure_Sample { - int64 relative_timestamp = 1; +message LightReading { + int64 relative_timestamp = 1; + // lux + float light = 2; +} - // mbar - float pressure = 2; +message ProximityReading { + int64 relative_timestamp = 1; + // cm + float distance = 2; +} +message GNSSPosition { + int64 relative_timestamp = 1; + + // degrees (minimum 6 significant figures) + // latitude between -90 and 90 + double latitude = 2; + // longitude between -180 and 180 + double longitude = 3; + //metres + double altitude = 4; + // floor name + optional string floor = 5; } -message Light_Sample { - int64 relative_timestamp = 1; - // lux - float light = 2; + +message GNSSReading { + GNSSPosition position = 1; + // metres + float accuracy = 2; + // m/s + float speed = 3; + // degrees + float bearing = 4; + + // e.g 'gps' or 'network' + string provider = 5; } -message GNSS_Sample { - int64 relative_timestamp = 1; - // degrees (minimum 6 significant figures) - // latitude between -90 and 90 - float latitude = 2; +message Fingerprint { + int64 relative_timestamp = 1; + repeated RFScan rf_scans = 2; - // longitude between -180 and 180 - float longitude = 3; +} - //metres - float altitude = 4; +message RFScan { + int64 relative_timestamp = 1; - // metres - float accuracy = 5; + // Integer encoding of the hex mac address (BSSID) + // e.g. 207394925843984 + int64 mac = 2; - // m/s - float speed = 6; + // rssi integer in dBm. + // typically between -120 and -10 + int32 rssi = 3; - // e.g 'gps' or 'network' - string provider = 7; + // returned position + optional GNSSPosition position = 4; } -message WiFi_Sample { - int64 relative_timestamp = 1; - repeated Mac_Scan mac_scans = 2; - +message WiFiRTTReading { + int64 relative_timestamp = 1; + // cm + // Integer encoding of the hex mac address (BSSID) + // e.g. 207394925843984 + int64 mac = 2; + + // in mm + float distance = 3; + // in mm + float distance_std = 4; + // rssi integer in dBm. + // typically between -120 and -10 + int32 rssi = 5; } -message Mac_Scan { - int64 relative_timestamp = 1; +message WiFiAPData { + // Integer encoding of the hex mac address (BSSID) + // e.g. 207394925843984 + int64 mac = 1; - // Integer encoding of the hex mac address - // e.g. 207394925843984 - int64 mac = 2; + // E.g. 'Eduroam' or 'Starbucks_free_wifi' + string ssid = 2; - // rssi integer in dBm. - // typically between -120 and -10 - int32 rssi = 3; + // Typically 2.4GHz or 5GHz + int64 frequency = 3; + + // Flag to indicate if the AP supports RTT measurements + bool rtt_enabled = 4; } -message AP_Data { - // Integer encoding of the hex mac address - // e.g. 207394925843984 - int64 mac = 1; +message BleData { + string mac_address = 1; + string name = 2; + int32 tx_power_level = 3; + int32 advertise_flags = 4; + repeated string service_uuids = 5; + bytes manufacturer_data = 6; +} - // E.g. 'Eduroam' or 'Starbucks_free_wifi' - string ssid = 2; + // --- Common Types --- +message Vector3 { + float x = 1; + float y = 2; + float z = 3; +} - // Typically 2.4GHz or 5GHz - int64 frequency = 3; +message Quaternion { + float x = 1; + float y = 2; + float z = 3; + float w = 4; } -message Sensor_Info { - string name = 1; - string vendor = 2; - float resolution = 3; - float power = 4; - int32 version = 5; - int32 type = 6; +message SensorInfo { + string name = 1; + string vendor = 2; + float resolution = 3; + float power = 4; + int32 version = 5; + int32 type = 6; + float max_range = 7; + float frequency = 8; } \ No newline at end of file diff --git a/app/src/main/res/drawable/floor_1.png b/app/src/main/res/drawable/floor_1.png deleted file mode 100644 index e72f6b1e..00000000 Binary files a/app/src/main/res/drawable/floor_1.png and /dev/null differ diff --git a/app/src/main/res/drawable/floor_2.png b/app/src/main/res/drawable/floor_2.png deleted file mode 100644 index 41f19d6b..00000000 Binary files a/app/src/main/res/drawable/floor_2.png and /dev/null differ diff --git a/app/src/main/res/drawable/floor_3.png b/app/src/main/res/drawable/floor_3.png deleted file mode 100644 index b54d83b4..00000000 Binary files a/app/src/main/res/drawable/floor_3.png and /dev/null differ diff --git a/app/src/main/res/drawable/floor_lg.png b/app/src/main/res/drawable/floor_lg.png deleted file mode 100644 index 75eb7014..00000000 Binary files a/app/src/main/res/drawable/floor_lg.png and /dev/null differ diff --git a/app/src/main/res/drawable/floor_ug.png b/app/src/main/res/drawable/floor_ug.png deleted file mode 100644 index 843d8f9a..00000000 Binary files a/app/src/main/res/drawable/floor_ug.png and /dev/null differ diff --git a/app/src/main/res/drawable/ic_baseline_add_timed_marker.xml b/app/src/main/res/drawable/ic_baseline_add_timed_marker.xml new file mode 100644 index 00000000..597344fc --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_add_timed_marker.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_bt_24.xml b/app/src/main/res/drawable/ic_baseline_bt_24.xml new file mode 100644 index 00000000..b67324a2 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_bt_24.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_baseline_navigation_25.xml b/app/src/main/res/drawable/ic_baseline_navigation_25.xml new file mode 100644 index 00000000..f2008ec8 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_navigation_25.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_expand_more_24.xml b/app/src/main/res/drawable/ic_expand_more_24.xml new file mode 100644 index 00000000..5c4ba3ef --- /dev/null +++ b/app/src/main/res/drawable/ic_expand_more_24.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/library1.png b/app/src/main/res/drawable/library1.png deleted file mode 100644 index d55850b8..00000000 Binary files a/app/src/main/res/drawable/library1.png and /dev/null differ diff --git a/app/src/main/res/drawable/library2.png b/app/src/main/res/drawable/library2.png deleted file mode 100644 index 27fa2b21..00000000 Binary files a/app/src/main/res/drawable/library2.png and /dev/null differ diff --git a/app/src/main/res/drawable/library3.png b/app/src/main/res/drawable/library3.png deleted file mode 100644 index a7eff2bc..00000000 Binary files a/app/src/main/res/drawable/library3.png and /dev/null differ diff --git a/app/src/main/res/drawable/libraryg.png b/app/src/main/res/drawable/libraryg.png deleted file mode 100644 index e7f185df..00000000 Binary files a/app/src/main/res/drawable/libraryg.png and /dev/null differ diff --git a/app/src/main/res/drawable/nucleus1.png b/app/src/main/res/drawable/nucleus1.png deleted file mode 100644 index 0c63ad5e..00000000 Binary files a/app/src/main/res/drawable/nucleus1.png and /dev/null differ diff --git a/app/src/main/res/drawable/nucleus2.png b/app/src/main/res/drawable/nucleus2.png deleted file mode 100644 index 5c9584eb..00000000 Binary files a/app/src/main/res/drawable/nucleus2.png and /dev/null differ diff --git a/app/src/main/res/drawable/nucleus3.png b/app/src/main/res/drawable/nucleus3.png deleted file mode 100644 index 4df9e09b..00000000 Binary files a/app/src/main/res/drawable/nucleus3.png and /dev/null differ diff --git a/app/src/main/res/drawable/nucleusg.png b/app/src/main/res/drawable/nucleusg.png deleted file mode 100644 index 6454a1f7..00000000 Binary files a/app/src/main/res/drawable/nucleusg.png and /dev/null differ diff --git a/app/src/main/res/drawable/nucleusground.png b/app/src/main/res/drawable/nucleusground.png deleted file mode 100644 index 11502ce1..00000000 Binary files a/app/src/main/res/drawable/nucleusground.png and /dev/null differ diff --git a/app/src/main/res/drawable/nucleuslg.png b/app/src/main/res/drawable/nucleuslg.png deleted file mode 100644 index 872c1dbc..00000000 Binary files a/app/src/main/res/drawable/nucleuslg.png and /dev/null differ diff --git a/app/src/main/res/layout-small/fragment_home.xml b/app/src/main/res/layout-small/fragment_home.xml index bd713b67..0451aad6 100644 --- a/app/src/main/res/layout-small/fragment_home.xml +++ b/app/src/main/res/layout-small/fragment_home.xml @@ -162,7 +162,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="16dp" - android:text="Indoor Positioning \n (In Development)" + android:text="@string/button_repo" android:textColor="@color/md_theme_onPrimary" android:backgroundTint="#9E9E9E" android:textSize="14sp" diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 00000000..6cf28d66 --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,24 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 0a3ceda2..90089889 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -3,9 +3,9 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:layout_width="match_parent" android:layout_height="match_parent" + android:theme="@style/Theme.AppCompat.Light.NoActionBar" tools:context=".presentation.activity.MainActivity"> @@ -22,19 +22,17 @@ app:layout_constraintEnd_toEndOf="parent" app:popupTheme="@style/Widget.MaterialComponents.PopupMenu" /> - - + app:layout_constraintEnd_toEndOf="parent" + app:defaultNavHost="true" + app:navGraph="@navigation/main_nav" /> diff --git a/app/src/main/res/layout/fragment_correction.xml b/app/src/main/res/layout/fragment_correction.xml index ce536570..06fbc135 100644 --- a/app/src/main/res/layout/fragment_correction.xml +++ b/app/src/main/res/layout/fragment_correction.xml @@ -27,7 +27,7 @@ + + + app:strokeColor="@android:color/transparent"> + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_files.xml b/app/src/main/res/layout/fragment_files.xml index 03de3f60..233df1bc 100644 --- a/app/src/main/res/layout/fragment_files.xml +++ b/app/src/main/res/layout/fragment_files.xml @@ -13,23 +13,21 @@ + app:layout_constraintTop_toTopOf="parent" + app:strokeColor="@color/md_theme_light_onPrimary"> + app:layout_constraintTop_toTopOf="parent" /> @@ -66,9 +64,46 @@ android:layout_height="0dp" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" - app:layout_constraintTop_toBottomOf="@id/uploadCard" app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" /> + app:layout_constraintTop_toBottomOf="@id/uploadCard" /> + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 99c1ef13..01e2f22c 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -159,15 +159,14 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="16dp" - android:text="Indoor Positioning \n (In Development)" + android:backgroundTint="@color/primaryBlue" + android:text="@string/button_repo" android:textColor="@color/md_theme_onPrimary" - android:backgroundTint="#9E9E9E" android:textSize="14sp" app:cornerRadius="14dp" - app:layout_constraintTop_toBottomOf="@id/buttonGrid" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" /> + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> diff --git a/app/src/main/res/layout/fragment_login.xml b/app/src/main/res/layout/fragment_login.xml new file mode 100644 index 00000000..36417b0f --- /dev/null +++ b/app/src/main/res/layout/fragment_login.xml @@ -0,0 +1,137 @@ + + + + + + + + + + +