Phase 1 complete. build Ok, apk OK

Signed-off-by: chaoq <chaoq@gxtech.ltd>
This commit is contained in:
2025-09-17 22:50:29 +08:00
parent 8875a5def1
commit 3bdc40df94
15 changed files with 2671 additions and 18 deletions

View File

@@ -25,6 +25,14 @@ object NetworkModule {
@Provides
@Singleton
fun provideGxrtcApi(retrofit: Retrofit): GxrtcApi = retrofit.create(GxrtcApi::class.java)
@Provides
@Singleton
fun provideArAnnotationApi(retrofit: Retrofit): ArAnnotationApi = retrofit.create(ArAnnotationApi::class.java)
@Provides
@Singleton
fun provideFeaturePointApi(retrofit: Retrofit): FeaturePointApi = retrofit.create(FeaturePointApi::class.java)
}
// data/remote/GxrtcApi.kt - 新增
@@ -44,6 +52,128 @@ interface GxrtcApi {
suspend fun getRooms(): Response<GxrtcResponse<List<RoomResponse>>>
}
// data/remote/ArAnnotationApi.kt - 新增
interface ArAnnotationApi {
@POST("ar/anchor/save")
suspend fun saveAnchor(@Body request: SaveAnchorRequest): Response<GxrtcResponse<Unit>>
@GET("ar/room/{roomId}/anchors")
suspend fun getRoomAnchors(@Path("roomId") roomId: String): Response<GxrtcResponse<AnchorListResponse>>
@POST("ar/annotation/save")
suspend fun saveAnnotation(@Body annotation: ArAnnotation): Response<GxrtcResponse<Unit>>
@GET("ar/room/{roomId}/annotations")
suspend fun getRoomAnnotations(@Path("roomId") roomId: String): Response<GxrtcResponse<AnnotationListResponse>>
@DELETE("ar/annotation/{annotationId}")
suspend fun deleteAnnotation(@Path("annotationId") annotationId: String): Response<GxrtcResponse<Unit>>
@POST("ar/spatial/validate")
suspend fun validateSpatialConsistency(@Body request: SpatialValidationRequest): Response<GxrtcResponse<SpatialValidationResult>>
@POST("ar/annotations/version")
suspend fun createAnnotationVersion(@Body request: CreateVersionRequest): Response<GxrtcResponse<VersionResponse>>
@GET("ar/annotations/{roomId}/versions")
suspend fun getAnnotationVersions(@Path("roomId") roomId: String): Response<GxrtcResponse<List<VersionResponse>>>
}
// data/remote/FeaturePointApi.kt - 新增
interface FeaturePointApi {
@POST("ar/feature-points/save")
suspend fun saveFeaturePoints(@Body request: SaveFeaturePointsRequest): Response<GxrtcResponse<Unit>>
@GET("ar/feature-points/{anchorId}")
suspend fun getAnchorFeatures(@Path("anchorId") anchorId: String): Response<GxrtcResponse<FeaturePointListResponse>>
@POST("ar/feature-points/match")
suspend fun matchFeaturePoints(@Body request: FeatureMatchRequest): Response<GxrtcResponse<FeatureMatchResponse>>
@POST("ar/feature-points/quality-assessment")
suspend fun assessFeatureQuality(@Body request: FeatureQualityRequest): Response<GxrtcResponse<FeatureQualityResponse>>
}
// 请求和响应数据模型
data class SaveAnchorRequest(
val roomId: String,
val anchorId: String,
val position: List<Float>,
val rotation: List<Float>,
val createdBy: String
)
data class AnchorListResponse(val anchors: List<AnchorData>)
data class AnnotationListResponse(val annotations: List<ArAnnotation>)
data class SaveFeaturePointsRequest(
val anchorId: String,
val roomId: String,
val featurePoints: List<FeaturePoint>,
val deviceInfo: DeviceInfo
)
data class FeaturePointListResponse(val featurePoints: List<FeaturePoint>)
data class SpatialValidationRequest(
val anchorId: String,
val currentPosition: List<Float>,
val currentRotation: List<Float>,
val deviceInfo: DeviceInfo
)
data class SpatialValidationResult(
val isValid: Boolean,
val confidence: Float,
val suggestedCorrection: SpatialTransform?,
val errorMessage: String?
)
data class FeatureMatchRequest(
val anchorId: String,
val queryFeatures: List<FeaturePoint>,
val maxResults: Int = 10
)
data class FeatureMatchResponse(
val matches: List<FeatureMatch>,
val confidence: Float
)
data class FeatureMatch(
val featurePoint: FeaturePoint,
val similarity: Float,
val spatialDistance: Float
)
data class FeatureQualityRequest(
val anchorId: String,
val featurePoints: List<FeaturePoint>
)
data class FeatureQualityResponse(
val overallQuality: Float,
val individualScores: Map<String, Float>,
val recommendations: List<String>
)
data class CreateVersionRequest(
val roomId: String,
val versionName: String,
val description: String,
val createdBy: String
)
data class VersionResponse(
val versionId: String,
val versionName: String,
val description: String,
val createdAt: Long,
val createdBy: String,
val annotationCount: Int
)
// 响应数据结构
data class GxrtcResponse<T>(
@SerializedName("meta") val meta: Meta,
@@ -423,35 +553,53 @@ data class AnchorData(
)
```
#### 4.2 AR标注持久化服务
#### 4.2 AR标注持久化服务(增强版)
```kotlin
// domain/service/ArAnnotationService.kt - 新增
class ArAnnotationService @Inject constructor(
private val arAnnotationApi: ArAnnotationApi
private val arAnnotationApi: ArAnnotationApi,
private val featurePointApi: FeaturePointApi,
private val userRepository: UserRepository
) {
suspend fun saveAnchor(
suspend fun saveAnchorWithFeatures(
roomId: String,
anchorId: String,
position: Pose
position: Pose,
featurePoints: List<FeaturePoint>,
deviceInfo: DeviceInfo
): Result<Unit> {
return try {
val request = SaveAnchorRequest(
// 保存锚点基本信息
val anchorRequest = SaveAnchorRequest(
roomId = roomId,
anchorId = anchorId,
position = listOf(position.tx(), position.ty(), position.tz()),
rotation = listOf(position.qx(), position.qy(), position.qz(), position.qw()),
createdBy = currentUserId
createdBy = userRepository.getCurrentUser()?.id ?: ""
)
arAnnotationApi.saveAnchor(anchorRequest)
// 保存特征点数据
val featureRequest = SaveFeaturePointsRequest(
anchorId = anchorId,
roomId = roomId,
featurePoints = featurePoints,
deviceInfo = deviceInfo
)
featurePointApi.saveFeaturePoints(featureRequest)
arAnnotationApi.saveAnchor(request)
Result.success(Unit)
} catch (e: Exception) {
Result.failure(e)
}
}
suspend fun loadRoomAnchors(roomId: String): List<AnchorData> {
return arAnnotationApi.getRoomAnchors(roomId).anchors
suspend fun loadRoomAnchorsWithFeatures(roomId: String): List<AnchorWithFeatures> {
val anchors = arAnnotationApi.getRoomAnchors(roomId).anchors
return anchors.map { anchor ->
val features = featurePointApi.getAnchorFeatures(anchor.anchorId).featurePoints
AnchorWithFeatures(anchor, features)
}
}
suspend fun saveAnnotation(annotation: ArAnnotation): Result<Unit> {
@@ -466,9 +614,59 @@ class ArAnnotationService @Inject constructor(
suspend fun loadRoomAnnotations(roomId: String): List<ArAnnotation> {
return arAnnotationApi.getRoomAnnotations(roomId).annotations
}
suspend fun validateSpatialConsistency(
anchorId: String,
currentPose: Pose,
deviceInfo: DeviceInfo
): Result<SpatialValidationResult> {
return try {
val request = SpatialValidationRequest(
anchorId = anchorId,
currentPosition = listOf(currentPose.tx(), currentPose.ty(), currentPose.tz()),
currentRotation = listOf(currentPose.qx(), currentPose.qy(), currentPose.qz(), currentPose.qw()),
deviceInfo = deviceInfo
)
val result = arAnnotationApi.validateSpatialConsistency(request)
Result.success(result)
} catch (e: Exception) {
Result.failure(e)
}
}
}
// data/model/ArAnnotation.kt - 新增
// 数据模型增强
data class AnchorWithFeatures(
val anchor: AnchorData,
val featurePoints: List<FeaturePoint>
)
data class FeaturePoint(
val position: List<Float>,
val descriptor: String, // base64编码的特征描述符
val qualityScore: Float,
val timestamp: Long = System.currentTimeMillis()
)
data class DeviceInfo(
val model: String,
val arCoreVersion: String,
val cameraCalibration: CameraCalibration?,
val imuCalibration: ImuCalibration?
)
data class CameraCalibration(
val focalLength: List<Float>,
val principalPoint: List<Float>,
val distortionCoefficients: List<Float>?
)
data class ImuCalibration(
val gyroBias: List<Float>?,
val accelBias: List<Float>?,
val magnetometerBias: List<Float>?
)
data class ArAnnotation(
val id: String,
val anchorId: String,
@@ -478,12 +676,21 @@ data class ArAnnotation(
val size: Float,
val roomId: String,
val createdBy: String,
val spatialTransform: SpatialTransform? = null,
val createdAt: Long = System.currentTimeMillis(),
val updatedAt: Long = System.currentTimeMillis()
val updatedAt: Long = System.currentTimeMillis(),
val version: Int = 1
)
data class SpatialTransform(
val position: List<Float>,
val rotation: List<Float>,
val scale: List<Float>,
val confidence: Float
)
enum class AnnotationType {
ARROW, CIRCLE, RECTANGLE, TEXT, HIGHLIGHT
ARROW, CIRCLE, RECTANGLE, TEXT, HIGHLIGHT, MEASUREMENT, NOTE
}
```
@@ -1025,6 +1232,139 @@ GET /ar/analytics/accuracy?room_id={roomId}
GET /ar/analytics/compatibility
```
### 7. 特征点管理API关键补充
```kotlin
// 保存ARCore特征点数据
POST /ar/feature-points/save
Content-Type: application/json
{
"anchor_id": "string",
"room_id": "string",
"feature_points": [
{
"position": [0.0, 0.0, 0.0],
"descriptor": "base64_encoded_descriptor",
"quality_score": 0.95
}
],
"device_info": {
"model": "Pixel 6",
"ar_core_version": "1.50.0",
"camera_calibration": {
"focal_length": [1000.0, 1000.0],
"principal_point": [500.0, 500.0]
}
}
}
// 获取特征点数据用于重定位
GET /ar/feature-points/{anchorId}
// 批量特征点匹配(跨设备空间对齐)
POST /ar/feature-points/match
{
"anchor_id": "string",
"query_features": [
{
"position": [0.0, 0.0, 0.0],
"descriptor": "base64_encoded_descriptor"
}
],
"max_results": 10
}
// 特征点质量评估
POST /ar/feature-points/quality-assessment
{
"anchor_id": "string",
"feature_points": [
{
"position": [0.0, 0.0, 0.0],
"descriptor": "base64_encoded_descriptor"
}
]
}
```
### 8. 空间一致性验证API
```kotlin
// 空间坐标转换验证
POST /ar/spatial/validate-transform
{
"source_anchor": "anchor_123",
"target_anchor": "anchor_456",
"transform_matrix": [
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[1.5, 2.0, 0.5, 1.0]
],
"confidence": 0.92
}
// 多设备空间对齐状态
GET /ar/spatial/alignment-status?room_id={roomId}
// 强制空间重新对齐
POST /ar/spatial/realign
{
"room_id": "string",
"anchor_ids": ["anchor1", "anchor2", "anchor3"]
}
```
### 9. 标注版本管理API
```kotlin
// 创建标注版本
POST /ar/annotations/version
{
"room_id": "string",
"version_name": "v1.0",
"description": "初始标注版本",
"created_by": "user123"
}
// 获取标注版本历史
GET /ar/annotations/{roomId}/versions
// 恢复到特定版本
POST /ar/annotations/{roomId}/restore/{versionId}
// 标注差异比较
GET /ar/annotations/{roomId}/diff?version1={v1}&version2={v2}
```
### 10. 设备性能优化API
```kotlin
// 设备性能基准上报
POST /ar/device/performance
{
"device_model": "Pixel 6",
"ar_core_version": "1.50.0",
"performance_metrics": {
"frame_rate": 60.0,
"tracking_quality": 0.95,
"memory_usage": 256,
"battery_drain": 15.0
},
"recommended_settings": {
"max_annotations": 50,
"feature_point_density": 0.8,
"texture_quality": "medium"
}
}
// 获取设备优化配置
GET /ar/device/{deviceModel}/optimization
// 性能问题诊断
POST /ar/device/diagnose
{
"device_info": {...},
"performance_issues": ["low_framerate", "high_memory"]
}
```
---
## 📋 阶段8优化和兼容性增强版

File diff suppressed because it is too large Load Diff