mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Add sensor fusion implementation to presence C++
PiperOrigin-RevId: 555676715
This commit is contained in:
committed by
Copybara-Service
parent
cce7cf59b9
commit
85bf78ef70
+36
-1
@@ -30,7 +30,22 @@ cc_library(
|
||||
"//presence/implementation:sensor_fusion",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/types:optional",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "sensor_fusion_impl",
|
||||
srcs = [
|
||||
"sensor_fusion_impl.cc",
|
||||
],
|
||||
hdrs = ["sensor_fusion_impl.h"],
|
||||
visibility = [
|
||||
"//presence:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":fpp_manager",
|
||||
"//presence/implementation:sensor_fusion",
|
||||
"@com_google_absl//absl/status",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -53,3 +68,23 @@ cc_test(
|
||||
],
|
||||
}),
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "sensor_fusion_test",
|
||||
size = "small",
|
||||
srcs = ["sensor_fusion_test.cc"],
|
||||
deps = [
|
||||
":sensor_fusion_impl",
|
||||
"//presence/implementation:sensor_fusion",
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
] + select({
|
||||
"@platforms//os:windows": [
|
||||
"//internal/platform/implementation/windows",
|
||||
],
|
||||
"//conditions:default": [
|
||||
"//internal/platform/implementation/g3",
|
||||
],
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -35,29 +35,31 @@ pub struct PresenceDetectorHandle {
|
||||
handle: u64,
|
||||
}
|
||||
|
||||
/// Error enum class representing possible errors
|
||||
/// Enum class representing possible outputs of proximity data processing call
|
||||
#[repr(C)]
|
||||
pub enum ProximityEstimateError {
|
||||
/// Returned if the handle is invalid
|
||||
InvalidPresenceDetectorHandle,
|
||||
/// Returned if the output parameter is null
|
||||
NullOutputParameter,
|
||||
pub enum ComputationStatus {
|
||||
/// Returned if the proximity estimate calculation was successful
|
||||
Success,
|
||||
/// Returned if there is no computed proximity estimate
|
||||
NoComputedProximityEstimate,
|
||||
/// Returned if the handle is invalid
|
||||
InvalidPresenceDetectorHandleError,
|
||||
/// Returned if the output parameter is null
|
||||
NullOutputParameterError,
|
||||
}
|
||||
|
||||
impl ProximityEstimateError {
|
||||
fn to_error_code(&self) -> i32 {
|
||||
impl ComputationStatus {
|
||||
fn to_status_code(&self) -> i32 {
|
||||
match self {
|
||||
Self::InvalidPresenceDetectorHandle => -1,
|
||||
Self::NullOutputParameter => -2,
|
||||
Self::NoComputedProximityEstimate => -3,
|
||||
/// Status codes 100+ are considered errors
|
||||
Self::Success => 1,
|
||||
Self::NoComputedProximityEstimate => 2,
|
||||
Self::InvalidPresenceDetectorHandleError => 101,
|
||||
Self::NullOutputParameterError => 102,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SUCCESS: i32 = 0;
|
||||
|
||||
/// Creates a new presence detector object and returns the handle for the new
|
||||
/// object
|
||||
#[no_mangle]
|
||||
@@ -86,15 +88,15 @@ pub unsafe extern "C" fn update_ble_scan_result(
|
||||
{
|
||||
if let Some(proximity_estimate) = proximity_estimate.as_mut() {
|
||||
*proximity_estimate = current_proximity_estimate;
|
||||
SUCCESS
|
||||
ComputationStatus::Success.to_status_code()
|
||||
} else {
|
||||
ProximityEstimateError::NullOutputParameter.to_error_code()
|
||||
ComputationStatus::NullOutputParameterError.to_status_code()
|
||||
}
|
||||
} else {
|
||||
ProximityEstimateError::NoComputedProximityEstimate.to_error_code()
|
||||
ComputationStatus::NoComputedProximityEstimate.to_status_code()
|
||||
}
|
||||
} else {
|
||||
ProximityEstimateError::InvalidPresenceDetectorHandle.to_error_code()
|
||||
ComputationStatus::InvalidPresenceDetectorHandleError.to_status_code()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,13 +117,13 @@ pub unsafe extern "C" fn get_proximity_estimate(
|
||||
presence_detector.get_proximity_estimate(device_id).map(|current_proximity_estimate| {
|
||||
if let Some(proximity_estimate) = proximity_estimate.as_mut() {
|
||||
*proximity_estimate = current_proximity_estimate;
|
||||
return SUCCESS;
|
||||
return ComputationStatus::Success.to_status_code();
|
||||
}
|
||||
ProximityEstimateError::NullOutputParameter.to_error_code()
|
||||
ComputationStatus::NullOutputParameterError.to_status_code()
|
||||
});
|
||||
}
|
||||
|
||||
ProximityEstimateError::InvalidPresenceDetectorHandle.to_error_code()
|
||||
ComputationStatus::InvalidPresenceDetectorHandleError.to_status_code()
|
||||
}
|
||||
|
||||
/// De-allocates memory for a presence detector object
|
||||
@@ -133,7 +135,7 @@ pub extern "C" fn presence_detector_free(
|
||||
get_presence_detector_handle_map().remove(&presence_detector_handle.handle)
|
||||
{
|
||||
let _ = *presence_detector;
|
||||
return SUCCESS;
|
||||
return ComputationStatus::Success.to_status_code();
|
||||
}
|
||||
ProximityEstimateError::InvalidPresenceDetectorHandle.to_error_code()
|
||||
ComputationStatus::InvalidPresenceDetectorHandleError.to_status_code()
|
||||
}
|
||||
|
||||
+33
-25
@@ -29,30 +29,22 @@ namespace nearby {
|
||||
namespace presence {
|
||||
|
||||
namespace {
|
||||
constexpr int kSuccess = 0;
|
||||
constexpr int kInvalidPresenceDetectorHandle = -1;
|
||||
constexpr int kNullOutputParameter = -2;
|
||||
constexpr int kNoComputedProximityEstimate = -3;
|
||||
// See
|
||||
// https://source.corp.google.com/piper///depot/google3/third_party/nearby/presence/fpp/fpp_c_ffi/src/lib.rs;l=49
|
||||
// for constants definition
|
||||
constexpr int kSuccess = 1;
|
||||
constexpr int kNoComputedProximityEstimate = 2;
|
||||
constexpr int kInvalidPresenceDetectorHandleError = 101;
|
||||
constexpr int kNullOutputParameterError = 102;
|
||||
|
||||
// Converts optional tx power to the rust api compatible equivalent
|
||||
MaybeTxPower ConvertTxPower(absl::optional<int8_t> txPower) {
|
||||
MaybeTxPower ConvertTxPower(std::optional<int8_t> txPower) {
|
||||
if (txPower.has_value()) {
|
||||
return {MaybeTxPower::Tag::Valid, {txPower.value()}};
|
||||
}
|
||||
return {MaybeTxPower::Tag::Invalid, {}};
|
||||
}
|
||||
|
||||
std::string GetStatusStringFromCode(int status_code) {
|
||||
switch (status_code) {
|
||||
case kInvalidPresenceDetectorHandle:
|
||||
return "INVALID_PRESENCE_DETECTOR_HANDLE";
|
||||
case kNullOutputParameter:
|
||||
return "NULL_OUTPUT_PARAMETER";
|
||||
default:
|
||||
return "UNKNOWN_ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
// Converts FPP ProximityState struct to NP RangeType struct
|
||||
PresenceZone::DistanceBoundary::RangeType ConvertProximityStateToRangeType(
|
||||
ProximityState proximity_state) {
|
||||
@@ -67,6 +59,7 @@ PresenceZone::DistanceBoundary::RangeType ConvertProximityStateToRangeType(
|
||||
return PresenceZone::DistanceBoundary::RangeType::kFar;
|
||||
case ProximityState::Unknown:
|
||||
default:
|
||||
NEARBY_LOGS(WARNING) << "Proximity state is unknown";
|
||||
return PresenceZone::DistanceBoundary::RangeType::kRangeUnknown;
|
||||
}
|
||||
}
|
||||
@@ -76,13 +69,16 @@ absl::Status FppManager::UpdateBleScanResult(uint64_t device_id,
|
||||
std::optional<int8_t> txPower,
|
||||
int rssi,
|
||||
uint64_t elapsed_realtime_millis) {
|
||||
if (zone_transition_callbacks_.empty()) {
|
||||
return absl::InternalError("No callback registered");
|
||||
}
|
||||
BleScanResult ble_scan_result = {device_id, ConvertTxPower(txPower), rssi,
|
||||
elapsed_realtime_millis};
|
||||
ProximityEstimate default_proximity_estimate =
|
||||
ProximityEstimate{device_id,
|
||||
0.0,
|
||||
/*distanceMeters=*/0.0,
|
||||
MeasurementConfidence::Unknown,
|
||||
0,
|
||||
/*elapsedRealtime=*/0,
|
||||
ProximityState::Unknown,
|
||||
PresenceDataSource::Ble};
|
||||
ProximityEstimate old_proximity_estimate =
|
||||
@@ -106,8 +102,7 @@ absl::Status FppManager::UpdateBleScanResult(uint64_t device_id,
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "Could not successfully update FPP with new scan result: Error code="
|
||||
<< status_code;
|
||||
return absl::Status(absl::StatusCode::kInternal,
|
||||
GetStatusStringFromCode(status_code));
|
||||
return absl::InternalError(GetStatusStringFromCode(status_code));
|
||||
}
|
||||
|
||||
void FppManager::RegisterZoneTransitionListener(
|
||||
@@ -132,12 +127,13 @@ std::optional<RangingData> FppManager::GetRangingData(uint64_t device_id) {
|
||||
RangingData FppManager::ConvertProximityEstimateToRangingData(
|
||||
ProximityEstimate estimate) {
|
||||
RangingMeasurement ranging_measurement = {
|
||||
0.0, static_cast<float>(estimate.distance_meters)};
|
||||
RangingPosition ranging_position = {ranging_measurement, absl::nullopt,
|
||||
absl::nullopt,
|
||||
estimate.elapsed_real_time_millis};
|
||||
/*confidenceLevel=*/0.0, static_cast<float>(estimate.distance_meters)};
|
||||
RangingPosition ranging_position = {
|
||||
ranging_measurement, /*azimuth=*/std::nullopt,
|
||||
/*elevation=*/std::nullopt, estimate.elapsed_real_time_millis};
|
||||
ZoneTransition zone_transition = {
|
||||
ConvertProximityStateToRangeType(estimate.proximity_state), 0.0};
|
||||
ConvertProximityStateToRangeType(estimate.proximity_state),
|
||||
/*confidenceLevel=*/0.0};
|
||||
return {DataSource::kBle, ranging_position, zone_transition,
|
||||
std::vector<DeviceMotion>()};
|
||||
}
|
||||
@@ -157,5 +153,17 @@ void FppManager::CheckPresenceZoneChanged(uint64_t device_id,
|
||||
}
|
||||
}
|
||||
|
||||
std::string FppManager::GetStatusStringFromCode(int status_code) {
|
||||
switch (status_code) {
|
||||
case kInvalidPresenceDetectorHandleError:
|
||||
return "INVALID_PRESENCE_DETECTOR_HANDLE";
|
||||
case kNullOutputParameterError:
|
||||
return "NULL_OUTPUT_PARAMETER";
|
||||
default:
|
||||
NEARBY_LOGS(WARNING) << "Error code is unknown";
|
||||
return "UNKNOWN_ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace presence
|
||||
} // namespace nearby
|
||||
|
||||
@@ -66,6 +66,11 @@ class FppManager {
|
||||
*/
|
||||
std::optional<RangingData> GetRangingData(uint64_t device_id);
|
||||
|
||||
/*
|
||||
* Converts a status code to a string representation
|
||||
*/
|
||||
std::string GetStatusStringFromCode(int status_code);
|
||||
|
||||
private:
|
||||
void CheckPresenceZoneChanged(uint64_t device_id,
|
||||
ProximityEstimate old_estimate,
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "gmock/gmock.h"
|
||||
#include "protobuf-matchers/protocol-buffer-matchers.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "presence/implementation/sensor_fusion.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -40,11 +41,11 @@ TEST(FppManager, UpdateBleScanResultSuccess) {
|
||||
PresenceZone::DistanceBoundary::RangeType range_type) {
|
||||
callback_called = true;
|
||||
}});
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/absl::nullopt,
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt,
|
||||
kReachRssi,
|
||||
/*elapsed_real_time_millis=*/0));
|
||||
// State is only computed after second consecutive scan is fulfilled
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/absl::nullopt,
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt,
|
||||
kReachRssi,
|
||||
/*elapsed_real_time_millis=*/2000));
|
||||
EXPECT_EQ(manager.GetRangingData(kDeviceId)
|
||||
@@ -66,10 +67,10 @@ TEST(FppManager, ZoneTransitionDetected) {
|
||||
callback_called = true;
|
||||
}});
|
||||
// ProximityEstimate is only computed after consecutive scans is fulfilled
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/absl::nullopt,
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt,
|
||||
kReachRssi,
|
||||
/*elapsed_real_time_millis=*/0));
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/absl::nullopt,
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt,
|
||||
kReachRssi,
|
||||
/*elapsed_real_time_millis=*/2000));
|
||||
EXPECT_EQ(manager.GetRangingData(kDeviceId)
|
||||
@@ -80,7 +81,7 @@ TEST(FppManager, ZoneTransitionDetected) {
|
||||
callback_called = false;
|
||||
|
||||
// Update with new zone
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/absl::nullopt,
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt,
|
||||
kShortRangeRssi,
|
||||
/*elapsed_real_time_millis=*/0));
|
||||
EXPECT_EQ(manager.GetRangingData(kDeviceId)
|
||||
@@ -89,7 +90,7 @@ TEST(FppManager, ZoneTransitionDetected) {
|
||||
PresenceZone::DistanceBoundary::RangeType::kWithinReach);
|
||||
EXPECT_FALSE(callback_called);
|
||||
// Update with consecutive scan of new zone
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/absl::nullopt,
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt,
|
||||
kShortRangeRssi,
|
||||
/*elapsed_real_time_millis=*/0));
|
||||
EXPECT_EQ(manager.GetRangingData(kDeviceId)
|
||||
@@ -172,10 +173,10 @@ TEST(FppManager, UnregisterZoneTransitionListener) {
|
||||
PresenceZone::DistanceBoundary::RangeType range_type) {
|
||||
callback_called = true;
|
||||
}});
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/absl::nullopt,
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt,
|
||||
kReachRssi,
|
||||
/*elapsed_real_time_millis=*/0));
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/absl::nullopt,
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt,
|
||||
kReachRssi,
|
||||
/*elapsed_real_time_millis=*/2000));
|
||||
EXPECT_TRUE(callback_called);
|
||||
@@ -183,15 +184,60 @@ TEST(FppManager, UnregisterZoneTransitionListener) {
|
||||
|
||||
// Unregister listener and update with new zone
|
||||
manager.UnregisterZoneTransitionListener(kCallbackId);
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/absl::nullopt,
|
||||
kShortRangeRssi,
|
||||
/*elapsed_real_time_millis=*/0));
|
||||
EXPECT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/absl::nullopt,
|
||||
kShortRangeRssi,
|
||||
/*elapsed_real_time_millis=*/0));
|
||||
EXPECT_EQ(manager
|
||||
.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt,
|
||||
kShortRangeRssi,
|
||||
/*elapsed_real_time_millis=*/0)
|
||||
.code(),
|
||||
absl::StatusCode::kInternal);
|
||||
EXPECT_EQ(manager
|
||||
.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt,
|
||||
kShortRangeRssi,
|
||||
/*elapsed_real_time_millis=*/0)
|
||||
.code(),
|
||||
absl::StatusCode::kInternal);
|
||||
EXPECT_FALSE(callback_called);
|
||||
}
|
||||
|
||||
TEST(FppManager, ResetProximityStateData) {
|
||||
FppManager manager;
|
||||
bool callback_called = false;
|
||||
manager.RegisterZoneTransitionListener(
|
||||
kCallbackId,
|
||||
{.on_proximity_zone_changed =
|
||||
[&callback_called](
|
||||
uint64_t device_id,
|
||||
PresenceZone::DistanceBoundary::RangeType range_type) {
|
||||
callback_called = true;
|
||||
}});
|
||||
ASSERT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt,
|
||||
kReachRssi,
|
||||
/*elapsed_real_time_millis=*/0));
|
||||
// State is only computed after second consecutive scan is fulfilled
|
||||
ASSERT_OK(manager.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt,
|
||||
kReachRssi,
|
||||
/*elapsed_real_time_millis=*/2000));
|
||||
EXPECT_EQ(manager.GetRangingData(kDeviceId)
|
||||
->zone_transition.value()
|
||||
.distance_range_type,
|
||||
PresenceZone::DistanceBoundary::RangeType::kWithinReach);
|
||||
EXPECT_TRUE(callback_called);
|
||||
|
||||
// Reset proximity state data
|
||||
manager.ResetProximityStateData();
|
||||
EXPECT_EQ(manager.GetRangingData(kDeviceId)
|
||||
->zone_transition.value()
|
||||
.distance_range_type,
|
||||
PresenceZone::DistanceBoundary::RangeType::kRangeUnknown);
|
||||
}
|
||||
|
||||
TEST(FppManager, GetStatusStringFromCode) {
|
||||
FppManager manager;
|
||||
EXPECT_EQ(manager.GetStatusStringFromCode(101),
|
||||
"INVALID_PRESENCE_DETECTOR_HANDLE");
|
||||
EXPECT_EQ(manager.GetStatusStringFromCode(102), "NULL_OUTPUT_PARAMETER");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace presence
|
||||
} // namespace nearby
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "presence/fpp/sensor_fusion_impl.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "presence/fpp/fpp_manager.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace presence {
|
||||
std::vector<DataSource> SensorFusionImpl::GetDataSources(
|
||||
uint64_t elapsed_realtime_millis,
|
||||
const std::vector<DataSource>& available_sources) {
|
||||
// TODO(b/264547688) - Implement
|
||||
return std::vector<DataSource>();
|
||||
}
|
||||
absl::Status SensorFusionImpl::UpdateBleScanResult(
|
||||
uint64_t device_id, std::optional<int8_t> txPower, int rssi,
|
||||
uint64_t elapsed_realtime_millis) {
|
||||
return fpp_manager_.UpdateBleScanResult(device_id, txPower, rssi,
|
||||
elapsed_realtime_millis);
|
||||
}
|
||||
void SensorFusionImpl::UpdateUwbRangingResult(uint64_t device_id,
|
||||
RangingPosition position) {
|
||||
// TODO(b/264547688) - Implement
|
||||
}
|
||||
|
||||
void SensorFusionImpl::RequestZoneTransitionUpdates(
|
||||
ZoneTransitionCallback callback) {
|
||||
int callback_id = ++id_generator_;
|
||||
callback.on_callback_id_generated(callback_id);
|
||||
fpp_manager_.RegisterZoneTransitionListener(callback_id, std::move(callback));
|
||||
}
|
||||
|
||||
void SensorFusionImpl::RequestDeviceMotionUpdates(
|
||||
SensorFusion::DeviceMotionCallback callback) {
|
||||
// TODO(b/264547688) - Implement
|
||||
}
|
||||
void SensorFusionImpl::RemoveDeviceMotionUpdates(
|
||||
SensorFusion::DeviceMotionCallback callback) {
|
||||
// TODO(b/264547688) - Implement
|
||||
}
|
||||
|
||||
void SensorFusionImpl::RemoveZoneTransitionUpdates(uint64_t callback_id) {
|
||||
fpp_manager_.UnregisterZoneTransitionListener(callback_id);
|
||||
}
|
||||
|
||||
std::optional<RangingData> SensorFusionImpl::GetRangingData(
|
||||
uint64_t device_id) {
|
||||
return fpp_manager_.GetRangingData(device_id);
|
||||
}
|
||||
} // namespace presence
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef THIRD_PARTY_NEARBY_PRESENCE_FPP_SENSOR_FUSION_IMPL_H_
|
||||
#define THIRD_PARTY_NEARBY_PRESENCE_FPP_SENSOR_FUSION_IMPL_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "presence/fpp/fpp_manager.h"
|
||||
#include "presence/implementation/sensor_fusion.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace presence {
|
||||
|
||||
class SensorFusionImpl : public SensorFusion {
|
||||
public:
|
||||
~SensorFusionImpl() = default;
|
||||
std::vector<DataSource> GetDataSources(
|
||||
uint64_t elapsed_realtime_millis,
|
||||
const std::vector<DataSource>& available_sources) override;
|
||||
absl::Status UpdateBleScanResult(uint64_t device_id,
|
||||
std::optional<int8_t> txPower, int rssi,
|
||||
uint64_t elapsed_realtime_millis) override;
|
||||
void UpdateUwbRangingResult(uint64_t device_id,
|
||||
RangingPosition position) override;
|
||||
void RequestZoneTransitionUpdates(ZoneTransitionCallback callback) override;
|
||||
void RemoveZoneTransitionUpdates(uint64_t callback_id) override;
|
||||
void RequestDeviceMotionUpdates(DeviceMotionCallback callback) override;
|
||||
void RemoveDeviceMotionUpdates(DeviceMotionCallback callback) override;
|
||||
std::optional<RangingData> GetRangingData(uint64_t device_id) override;
|
||||
|
||||
private:
|
||||
FppManager fpp_manager_;
|
||||
int id_generator_ = 0;
|
||||
};
|
||||
} // namespace presence
|
||||
} // namespace nearby
|
||||
|
||||
#endif // THIRD_PARTY_NEARBY_PRESENCE_FPP_SENSOR_FUSION_IMPL_H_
|
||||
@@ -0,0 +1,110 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "protobuf-matchers/protocol-buffer-matchers.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "presence/fpp/sensor_fusion_impl.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace presence {
|
||||
namespace {
|
||||
constexpr uint64_t kDeviceId = 1234;
|
||||
constexpr int kReachRssi = -40;
|
||||
|
||||
TEST(SensorFusion, RequestZoneTransitionUpdatesSuccess) {
|
||||
SensorFusionImpl sensor_fusion_impl;
|
||||
bool callback_called = false;
|
||||
bool callback2_called = false;
|
||||
sensor_fusion_impl.RequestZoneTransitionUpdates(
|
||||
{.on_callback_id_generated = [&callback_called](uint64_t callback_id) {
|
||||
callback_called = true;
|
||||
EXPECT_EQ(callback_id, 1);
|
||||
}});
|
||||
sensor_fusion_impl.RequestZoneTransitionUpdates(
|
||||
{.on_callback_id_generated = [&callback2_called](uint64_t callback_id2) {
|
||||
callback2_called = true;
|
||||
EXPECT_EQ(callback_id2, 2);
|
||||
}});
|
||||
EXPECT_TRUE(callback2_called);
|
||||
}
|
||||
|
||||
TEST(SensorFusion, RemoveZoneTransitionUpdates) {
|
||||
SensorFusionImpl sensor_fusion_impl;
|
||||
bool callback_called = false;
|
||||
sensor_fusion_impl.RequestZoneTransitionUpdates(
|
||||
{.on_callback_id_generated = [&callback_called](uint64_t callback_id) {
|
||||
callback_called = true;
|
||||
EXPECT_EQ(callback_id, 1);
|
||||
}});
|
||||
sensor_fusion_impl.RemoveZoneTransitionUpdates(1);
|
||||
EXPECT_EQ(
|
||||
sensor_fusion_impl
|
||||
.UpdateBleScanResult(kDeviceId, /*txPower=*/std::nullopt, kReachRssi,
|
||||
/*elapsed_real_time_millis=*/0)
|
||||
.code(),
|
||||
absl::StatusCode::kInternal);
|
||||
}
|
||||
|
||||
TEST(SensorFusion, UpdateBleScanResult) {
|
||||
SensorFusionImpl sensor_fusion_impl;
|
||||
bool proximity_zone_changed_called = false;
|
||||
sensor_fusion_impl.RequestZoneTransitionUpdates(
|
||||
{.on_proximity_zone_changed =
|
||||
[&proximity_zone_changed_called](
|
||||
uint64_t device_id,
|
||||
PresenceZone::DistanceBoundary::RangeType range_type) {
|
||||
proximity_zone_changed_called = true;
|
||||
}});
|
||||
EXPECT_OK(sensor_fusion_impl.UpdateBleScanResult(
|
||||
kDeviceId, /*txPower=*/std::nullopt, kReachRssi,
|
||||
/*elapsed_real_time_millis=*/0));
|
||||
EXPECT_OK(sensor_fusion_impl.UpdateBleScanResult(
|
||||
kDeviceId, /*txPower=*/std::nullopt, kReachRssi,
|
||||
/*elapsed_real_time_millis=*/0));
|
||||
|
||||
EXPECT_TRUE(proximity_zone_changed_called);
|
||||
}
|
||||
|
||||
TEST(SensorFusion, GetRangingData) {
|
||||
SensorFusionImpl sensor_fusion_impl;
|
||||
bool proximity_zone_changed_called = false;
|
||||
sensor_fusion_impl.RequestZoneTransitionUpdates(
|
||||
{.on_proximity_zone_changed =
|
||||
[&proximity_zone_changed_called](
|
||||
uint64_t device_id,
|
||||
PresenceZone::DistanceBoundary::RangeType range_type) {
|
||||
proximity_zone_changed_called = true;
|
||||
}});
|
||||
EXPECT_OK(sensor_fusion_impl.UpdateBleScanResult(
|
||||
kDeviceId, /*txPower=*/std::nullopt, kReachRssi,
|
||||
/*elapsed_real_time_millis=*/0));
|
||||
EXPECT_OK(sensor_fusion_impl.UpdateBleScanResult(
|
||||
kDeviceId, /*txPower=*/std::nullopt, kReachRssi,
|
||||
/*elapsed_real_time_millis=*/0));
|
||||
|
||||
EXPECT_TRUE(proximity_zone_changed_called);
|
||||
|
||||
EXPECT_EQ(sensor_fusion_impl.GetRangingData(kDeviceId)
|
||||
->zone_transition.value()
|
||||
.distance_range_type,
|
||||
PresenceZone::DistanceBoundary::RangeType::kWithinReach);
|
||||
}
|
||||
} // namespace
|
||||
} // namespace presence
|
||||
} // namespace nearby
|
||||
@@ -126,6 +126,7 @@ cc_library(
|
||||
deps = [
|
||||
"//presence:types",
|
||||
"@com_google_absl//absl/functional:any_invocable",
|
||||
"@com_google_absl//absl/status",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "presence/device_motion.h"
|
||||
#include "presence/presence_zone.h"
|
||||
|
||||
@@ -92,7 +93,7 @@ class SensorFusion {
|
||||
*/
|
||||
virtual std::vector<DataSource> GetDataSources(
|
||||
uint64_t elapsed_realtime_millis,
|
||||
const std::vector<DataSource>& available_sources);
|
||||
const std::vector<DataSource>& available_sources) = 0;
|
||||
|
||||
/**
|
||||
* Updates BLE scanned results to Sensor Fusion.
|
||||
@@ -104,10 +105,9 @@ class SensorFusion {
|
||||
* @param elapsed_realtime_millis Elapsed timestamp since boot when the
|
||||
* scan result is discovered.
|
||||
*/
|
||||
virtual void UpdateBleScanResult(uint64_t device_id,
|
||||
std::optional<int8_t> txPower, int rssi,
|
||||
uint64_t elapsed_realtime_millis);
|
||||
|
||||
virtual absl::Status UpdateBleScanResult(
|
||||
uint64_t device_id, std::optional<int8_t> txPower, int rssi,
|
||||
uint64_t elapsed_realtime_millis) = 0;
|
||||
/**
|
||||
* Updates UWB ranging results to Sensor Fusion.
|
||||
*
|
||||
@@ -115,27 +115,28 @@ class SensorFusion {
|
||||
* @param position UWB ranging result (distance and optionally angle)
|
||||
*/
|
||||
virtual void UpdateUwbRangingResult(uint64_t device_id,
|
||||
RangingPosition position);
|
||||
RangingPosition position) = 0;
|
||||
|
||||
/**
|
||||
* Adds callback for updates of proximity zone transitions.
|
||||
*/
|
||||
virtual void RequestZoneTransitionUpdates(ZoneTransitionCallback callback);
|
||||
virtual void RequestZoneTransitionUpdates(
|
||||
ZoneTransitionCallback callback) = 0;
|
||||
|
||||
/**
|
||||
* Removes callback for updates of proximity zone transitions.
|
||||
*/
|
||||
virtual void RemoveZoneTransitionUpdates(ZoneTransitionCallback callback);
|
||||
virtual void RemoveZoneTransitionUpdates(uint64_t callback_id) = 0;
|
||||
|
||||
/**
|
||||
* Adds callback for updates of device motion events.
|
||||
*/
|
||||
virtual void RequestDeviceMotionUpdates(DeviceMotionCallback callback);
|
||||
virtual void RequestDeviceMotionUpdates(DeviceMotionCallback callback) = 0;
|
||||
|
||||
/**
|
||||
* Remove callback for updates of device motion events.
|
||||
*/
|
||||
virtual void RemoveDeviceMotionUpdates(DeviceMotionCallback callback);
|
||||
virtual void RemoveDeviceMotionUpdates(DeviceMotionCallback callback) = 0;
|
||||
|
||||
/**
|
||||
* Returns the best ranging estimate to a given device. Returns {@code
|
||||
@@ -143,7 +144,7 @@ class SensorFusion {
|
||||
*
|
||||
* @param device_id Id of the peer device.
|
||||
*/
|
||||
virtual std::optional<RangingData> GetRangingData(uint64_t device_id);
|
||||
virtual std::optional<RangingData> GetRangingData(uint64_t device_id) = 0;
|
||||
};
|
||||
|
||||
} // namespace presence
|
||||
|
||||
Reference in New Issue
Block a user