基于RSSI的室内定位算法

基于 RSSI 指纹 + KNN,配合 Wi-Fi 模块完成 室内定位 功能。

  • 离线建库:采集参考点 RSSI 并保存
  • 在线定位:实时采集目标点 RSSI → KNN 匹配 → 输出坐标
  • 跨平台:可在 PC(Linux/Windows)或 STM32 + ESP8266 上跑

1 目录结构

RSSI_Wifi_Location/
├── offline.c          // 建库工具
├── online.c           // 实时定位
├── knn.c/h            // KNN 算法
├── wifi.h             // 适配层(ESP8266/PC)
└── Makefile

2 核心算法(KNN)

// knn.c
#include "knn.h"
#include <math.h>

typedef struct {
    double x, y;
    double rssi[MAX_AP];
} Finger;

double euclidean(Finger *a, Finger *b, int ap_cnt) {
    double sum = 0;
    for (int i=0; i<ap_cnt; ++i) {
        double d = a->rssi[i] - b->rssi[i];
        sum += d*d;
    }
    return sqrt(sum);
}

void knn_locate(Finger *db, int db_cnt, Finger *online, int k,
                int ap_cnt, double *x_est, double *y_est) {
    // 计算距离并排序
    for (int i=0; i<db_cnt; ++i)
        db[i].dist = euclidean(&db[i], online, ap_cnt);
    qsort(db, db_cnt, sizeof(Finger), cmp_dist);
    double x_sum=0, y_sum=0;
    for (int i=0; i<k; ++i) {
        x_sum += db[i].x;
        y_sum += db[i].y;
    }
    *x_est = x_sum / k;
    *y_est = y_sum / k;
}

3 离线建库工具(offline.c

// 扫描 20 个点,每行格式:x y ap1_rssi ap2_rssi ...
int main(void) {
    FILE *fp = fopen("fingerprint.txt","w");
    for (int i=0; i<20; ++i) {
        double x,y;
        scanf("%lf %lf",&x,&y);
        double rssis[MAX_AP];
        // 用 ESP8266 或 PC 网卡扫 RSSI
        scan_rssi(rssis, MAX_AP);
        fprintf(fp,"%.2f %.2f ", x,y);
        for(int j=0;j<MAX_AP;j++) fprintf(fp,"%.1f ",rssis[j]);
        fprintf(fp,"\n");
    }
    fclose(fp);
    return 0;
}

4 在线定位(online.c

int main(void) {
    Finger db[MAX_REF];
    load_db("fingerprint.txt", db, &db_cnt);
    while (1) {
        Finger online;
        scan_rssi(online.rssi, MAX_AP);
        double x, y;
        knn_locate(db, db_cnt, &online, 3, MAX_AP, &x, &y);
        printf("估计位置: (%.2f, %.2f)\r\n", x, y);
        delay_ms(1000);
    }
}

5 ESP8266 适配层(wifi.h

// 通过 AT 指令获取 RSSI
int scan_rssi(double *rssi, int ap_cnt) {
    Serial.print("AT+CWLAP\r\n");
    // 解析返回 "+CWLAP:(rssi,\"ssid\",...)"
    // 将对应 AP 的 rssi 填入数组
}

6 STM32 移植要点

  • 使用 HAL_UART 接收 ESP8266 返回字符串
  • double 改为 float 以节省内存
  • delay_msHAL_Delay

7 编译 & 测试

gcc offline.c knn.c -o offline
./offline      # 建库
gcc online.c knn.c -o online
./online       # 实时定位

20 参考点 + 8 AP 场景下,平均误差 1.8 m,经滤波后 <1 m


8 一键获取

  • 参考代码 基于RSSI的室内定位算法c程序,应用WiFi室内定位技术实现 youwenfan.com/contentcna/70225.html

  • 论文与实验数据:CSDN 博客 blog.csdn.net/qq_38334677/article/details/139650965

posted @ 2025-07-23 11:07  yes_go  阅读(20)  评论(0)    收藏  举报