Files
akmon/doc_chat/位置.md
2026-01-20 08:04:15 +08:00

9.2 KiB
Raw Permalink Blame History

明白了。你想把“2.4G 网关 + 手环 RSSI”估算出的位置信息接到地图里在 uni-app-xUTS Android上怎么做更稳当。下面给你一套实用建议和可直接复用的代码骨架包含精度圈、外部地图打开、国标坐标处理等

建议与实践路径

  • 定位算法侧(从 RSSI 到坐标)

    • 用对数路径损耗模型把 RSSI 转成距离d = 10^((RSSI0 RSSI) / (10·n))n 在室内一般 2.23.0,需要场地标定得到 RSSI0 和 n。
    • 融合多网关:
      • 简单稳健加权质心WCL权重用 1/d^p 或用 RSSI 线性/指数映射,抗多径比三边定位更鲁棒。
      • 条件好时:三边定位(最小二乘)+ RANSAC 剔除离群网关。
    • 平滑与抗抖动35 点中值滤波 + 指数滑动平均,或一维/二维卡尔曼滤波。
    • 场景约束将估算点“吸附”到建筑内合法区域、多边形map matching并给出不确定性半径例如距离方差/残差→半径)。
  • 坐标系问题(中国大陆必须重视)

    • 如果你算出的是 WGS84GPS 原生),大多数国内地图(高德/腾讯/微信小程序/原生 )使用 GCJ-02火星坐标。展示前请转换为 GCJ-02。
    • 反向地理编码(坐标→地址)可用高德/腾讯等服务,注意密钥与限频,不要在前端暴露密钥。
  • uni-app-xUTS Android地图接入的三种方式

    1. 快速方案uni.openLocation 打开系统/第三方地图
      • 最快、稳定;不在应用内嵌地图,适合查看/导航跳转。
    2. 应用内嵌地图:内置 <map> 组件
      • App-Android 通常可用 markers/circles/polyline在 uni-app-x 某些版本上功能覆盖可能比标准 uni 稍有限,如遇不支持的属性可退化或走插件方案。
    3. UTS 原生插件(高德/腾讯地图 SDK
      • 需要更高级能力(离线地图、室内图、海量点渲染、轨迹回放、热力图),建议用官方原生 SDK 的 UTS 插件。去 uni 原生插件市场搜索“高德地图 UTS/定位 UTS”等。
  • 工程与性能建议

    • 权限Android 申请 ACCESS_FINE_LOCATION在 manifest.json 的 app-plus 节点配置权限。
    • 绑定简化:模板里避免函数调用和复杂表达式,预先计算好 markers/circles 字段(已按 UTS 规范给出示例)。
    • 批量更新:频繁刷新时做节流/合并更新,避免每条数据都 setData。
    • 可视化:用 circle 显示“不确定性半径”;锚点颜色代表置信度;支持点击 marker 查看详情。

可复用代码片段

1) 坐标转换WGS84 → GCJ-02UTS 版)

// utils/coord.uts
export function wgs84ToGcj02(lat: number, lng: number): number[] {
  if (outOfChina(lat, lng)) return [lat, lng]
  const dLat = transformLat(lng - 105.0, lat - 35.0)
  const dLng = transformLng(lng - 105.0, lat - 35.0)
  const radLat = lat / 180.0 * Math.PI
  let magic = Math.sin(radLat)
  magic = 1 - 0.00669342162296594323 * magic * magic
  const sqrtMagic = Math.sqrt(magic)
  const dLat2 = (dLat * 180.0) / ((6335552.717000426 * magic) / (sqrtMagic) * Math.PI)
  const dLng2 = (dLng * 180.0) / ((6378245.0 / sqrtMagic * Math.cos(radLat)) * Math.PI)
  return [lat + dLat2, lng + dLng2]
}

function outOfChina(lat: number, lng: number): boolean {
  return (lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271)
}
function transformLat(x: number, y: number): number {
  let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x))
  ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0
  ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0
  ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0
  return ret
}
function transformLng(x: number, y: number): number {
  let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x))
  ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0
  ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0
  ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0
  return ret
}

使用建议:如果你算出来的是 WGS84就先 wgs84ToGcj02 再喂给地图组件/服务。

2) 最快路径外部地图打开openLocation

<!-- pages/location/open.uvue -->
<template>
  <view class="page">
    <button class="btn" @click="open">在地图中查看</button>
  </view>
</template>

<script lang="uts">
export default {
  data() { return { name: '手环估计位置', lat: 31.23037, lng: 121.4737 } },
  methods: {
    open() {
      // 确保已转换到 GCJ-02如果在中国大陆
      const name = this.name
      const latitude = this.lat
      const longitude = this.lng
      uni.openLocation({ latitude, longitude, name } as any)
    }
  }
}
</script>
<style scoped>
.page{ padding: 24rpx }
.btn{ padding: 16rpx 24rpx; border:1px solid #ddd; border-radius: 8rpx }
</style>
  • 优点:零集成、稳定、导航能力强。
  • 缺点:不在应用内展示。

3) 嵌入式地图(内置 <map> 组件,展示 marker + 精度圈)

注意:不同 uni-app-x 版本对 <map> 的支持程度略有差异。若你的环境不支持该组件,请选择 openLocation 或 UTS 插件路线。

<!-- pages/location/map.uvue -->
<template>
  <view class="page">
    <map class="map"
         :latitude="centerLat"
         :longitude="centerLng"
         :scale="18"
         :markers="markers"
         :circles="circles">
    </map>
    <view class="toolbar">
      <button @click="recenter">回到中心</button>
      <button @click="openSysMap">外部地图</button>
    </view>
  </view>
</template>

<script lang="uts">
import { wgs84ToGcj02 } from '@/utils/coord.uts'

type MapMarker = {
  id: number; latitude: number; longitude: number;
  iconPath: string; width: number; height: number; callout?: any
}

export default {
  data() {
    return {
      centerLat: 31.23037,
      centerLng: 121.4737,
      markers: [] as Array<MapMarker>,
      circles: [] as Array<any>,
      // 原始估算WGS84
      estLat: 31.23037,
      estLng: 121.4737,
      // 不确定性半径(米),可用 RSSI 残差/方差计算
      radius: 20
    }
  },
  onLoad() {
    this.refreshDisplay()
  },
  methods: {
    refreshDisplay() {
      // 估算坐标→ GCJ-02
      const r = wgs84ToGcj02(this.estLat, this.estLng)
      const lat = r[0] as number
      const lng = r[1] as number
      this.centerLat = lat
      this.centerLng = lng
      // 标点
      this.markers = [{
        id: 1,
        latitude: lat,
        longitude: lng,
        iconPath: '/static/marker.png',
        width: 32, height: 32,
        callout: { content: '手环估计位置', color: '#000', display: 'ALWAYS' }
      }]
      // 精度圈
      this.circles = [{
        latitude: lat,
        longitude: lng,
        radius: this.radius,
        color: '#3b82f680',
        fillColor: '#3b82f633',
        strokeWidth: 2
      }]
    },
    recenter() {
      this.refreshDisplay()
    },
    openSysMap() {
      uni.openLocation({ latitude: this.centerLat, longitude: this.centerLng, name: '手环估计位置' } as any)
    }
  }
}
</script>

<style scoped>
.page{ display:flex; flex-direction: column; height:100% }
.map{ flex:1; width:100% }
.toolbar{ padding: 12rpx; border-top:1px solid #eee; display:flex; gap: 12rpx }
</style>

要点UTS/uni-app-x 规范友好):

  • 模板里用简单绑定;数据在 data/方法中预先整理,不在模板做复杂表达式。
  • 属性名、数组结构与 <map> 组件文档保持一致;一次性替换 markers/circles,避免频繁小更新。

4) UTS 原生插件路线(当你需要更强能力)

  • 场景:内置 <map> 组件受限、需要室内图/离线地图/大量覆盖物/轨迹回放/热力图等。
  • 做法:在 uni 原生插件市场搜索“高德地图 UTS/定位 UTS”等选择维护活跃的插件。
  • 优点:更强渲染与能力接入;缺点:体积与集成复杂度上升。

权限与清单Android

  • manifest.json 中的 app-plus > android > permission 添加定位权限(通常 uni 默认已包含)。首次进入地图页或获取定位前提示授权。
  • 若做后台定位或持续上传,需额外前台服务与权限申明,注意隐私合规。

UI/交互建议

  • 展示“估计位置 + 不确定性半径”:用户能感知误差而非认为是“点精确到米”。
  • 支持点击 marker 查看当前 RSSI 源信息(网关数、残差、权重),便于排障。
  • 多手环时,颜色/形状区分,支持列表一键定位到某个手环。
  • 大量点位更新做节流(例如 500ms 合并一次),减少渲染压力。

如果你愿意,我可以在仓库里加一个 pages/location 示例页(含坐标转换工具 utils/coord.uts),并把你 RSSI 解算出的结果WGS84接上这个页面页面内展示 marker 与精度圈,同时提供“一键外部地图打开”。你只需要告诉我:页面路由名、是否用内置 <map> 还是先用 openLocation 路线即可。

Similar code found with 2 license types