欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android项目之利用手机传感器做惯性导航

程序员文章站 2022-03-07 13:09:18
...

利用手机的传感器做手机的姿态解算,利用扩展卡尔曼滤波算法获得手机的航向角、偏航角和滚转角。再进一步做人步行的惯性导航。

需要程序的源码请联系~~~

整体规划:

1.获得手机传感器的数据,实时发送到电脑。

加上时间戳——日期加精确的ms数。

2.在电脑端接收数据,并保存为指定格式

3.运用扩展卡尔曼滤波算法进行手机的姿态解算

4.做惯性导航的计算


1.Android使用到的技术

1.1 Android开发中保留两位小数

我用的是方法三。。。。

参考链接:https://blog.csdn.net/qq_36487432/article/details/81904207

方法一:

  BigDecimal bg = new BigDecimal(xx);
  double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

方法二:

   DecimalFormat df = new DecimalFormat("#.00");
   df.format(xx)

方法三:   

String.format("%.2f", xx);

方法四:

   NumberFormat nf = NumberFormat.getNumberInstance();
   nf.setMaximumFractionDigits(2);
   nf.format(xx);

1.2 Android传感器的使用

传感器的采样率
  a) SENSOR_DELAY_NOMAL    (200000微秒)       200ms
  b) SENSOR_DELAY_UI       (60000微秒)               60ms
  c) SENSOR_DELAY_GAME     (20000微秒)          20ms
  d) SENSOR_DELAY_FASTEST  (0微秒)               0ms

设置采样率方法:以下每个传感器函数的最后都有一个设置采样率的参数,如下面代码中的SensorManager.SENSOR_DELAY_NORMAL

传感器的属性

//传感器的名字

String sensorName=event.sensor.getName();

//传感器制造商的名字

String sensorVendor=event.sensor.getVendor();

//传感器的分辨率,传感器所能识别的最小的精度是多少

float sensorRevolution=event.sensor.getResolution();

//传感器的功率

float sensorPower=event.sensor.getPower();

//传感器取得数据的时间是多少

double timeStamp=event.timestamp;

第一、加速度传感器

SensorManager sm = (SensorManager) this.getSystemService(Context.SENSOR_SERVICE);//创建一个SensorManager对象,用来管理或者获取传感器

//加速度传感器
Sensor acc = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//为该传感器注册一个事件,直接使用内部类
sm.registerListener(new SensorEventListener() {
    @Override
    public void onSensorChanged(SensorEvent event) {
        txtx.setText("x方向的加速度为:" + String.format("%.2f", event.values[0]) + "m/s2");
        txty.setText("y方向的加速度为:" + String.format("%.2f", event.values[1]) + "m/s2");
        txtz.setText("z方向的加速度为:" + String.format("%.2f", event.values[2]) + "m/s2");
    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
}, acc, SensorManager.SENSOR_DELAY_NORMAL);

第二、方向传感器

//方向传感器
Sensor direc = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);
//为该传感器注册一个事件,直接使用内部类
sm.registerListener(new SensorEventListener() {
    @Override
    public void onSensorChanged(SensorEvent event) {
        txtxx.setText("x方向为:" + String.format("%.2f", event.values[0])+ "度");
        txtyy.setText("y方向为:" + String.format("%.2f", event.values[1])+ "度");
        txtzz.setText("z方向为:" + String.format("%.2f", event.values[2])+ "度");
    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
}, direc, SensorManager.SENSOR_DELAY_NORMAL);

第三、陀螺仪传感器

//陀螺仪传感器
Sensor tuoluo = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
//为该传感器注册一个事件,直接使用内部类
sm.registerListener(new SensorEventListener() {
    @Override
    public void onSensorChanged(SensorEvent event) {
        txtxxx.setText("x方向的陀螺仪为:" + String.format("%.2f", event.values[0])+ "rad/s");
        txtyyy.setText("y方向的陀螺仪为:" + String.format("%.2f", event.values[1])+ "rad/s");
        txtzzz.setText("z方向的陀螺仪为:" + String.format("%.2f", event.values[2])+ "rad/s");
    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
}, tuoluo, SensorManager.SENSOR_DELAY_NORMAL);

第四、线性加速度传感器

//线性加速度传感器
Sensor lineacc = sm.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
//为该传感器注册一个事件,直接使用内部类
sm.registerListener(new SensorEventListener() {
    @Override
    public void onSensorChanged(SensorEvent event) {
        txtxxxx.setText("x方向的线性加速度为:" + String.format("%.2f", event.values[0]) + "m/s2");
        txtyyyy.setText("y方向的线性加速度为:" + String.format("%.2f", event.values[1]) + "m/s2");
        txtzzzz.setText("z方向的线性加速度为:" + String.format("%.2f", event.values[2]) + "m/s2");
    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
}, lineacc, SensorManager.SENSOR_DELAY_NORMAL);

第五、重力传感器

//重力传感器
Sensor sr = sm.getDefaultSensor(Sensor.TYPE_GRAVITY);//根据Sensor下枚举获得对应的传感器对象
//为该传感器注册一个事件,直接使用内部类
sm.registerListener(new SensorEventListener() {
    @Override
    public void onSensorChanged(SensorEvent event) {
        txtxxxxx.setText("x方向的重力加速度为:" + String.format("%.2f", event.values[0]) + "m/s2");
        txtyyyyy.setText("y方向的重力加速度为:" + String.format("%.2f", event.values[1]) + "m/s2");
        txtzzzzz.setText("z方向的重力加速度为:" + String.format("%.2f", event.values[2]) + "m/s2");
    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
}, sr, SensorManager.SENSOR_DELAY_NORMAL);

1.3 手机利用socket作为TCP客户端发送数据给电脑

参考链接:https://www.cnblogs.com/zhangqie/p/8876059.html

步骤1:添加权限,在AndroidManife.xml中

<uses-permission android:name="android.permission.INTERNET"/>

Android项目之利用手机传感器做惯性导航

步骤2:开启新线程,现在要求TCP通信必须在非UI线程中开启

在最开始定义socket

Socket socket_my;

在onCreate中定义新线程,线程在syncRunnable函数中运行

//开网络通信线程
SyncRunnable syncRunnable = new SyncRunnable();//定义Runnable接口
Thread thread = new Thread(syncRunnable, "syncRunnable");//定义新线程
thread.start();//开启新线程

Android项目之利用手机传感器做惯性导航

在新线程执行函数中开启网络通信

public class SyncRunnable implements Runnable {
        @Override
        public void run() {
            synchronized (this) {
                //建立连接
                try {
                    socket_my = new Socket("192.168.1.5", 8086);
                } catch (IOException e) {
                    e.printStackTrace();
                }

//                try {
//                    socket = new DatagramSocket(4534);//本机的接收端口号
//                    serverAddress = InetAddress.getByName("192.168.1.5");//发送到的IP
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }

                while (true) {
                    String sendData = "12345";//发送的数据

                }
            }
        }
    }

Android项目之利用手机传感器做惯性导航

发送数据给服务端

try {
    // socket.getInputStream()
    DataOutputStream writer = new DataOutputStream(socket_my.getOutputStream());
    writer.writeUTF("嘿嘿,你好啊,服务器.."); // 写一个UTF-8的信息
    System.out.println("发送消息");
} catch (IOException e) {
    e.printStackTrace();
}

接收服务端发送的数据

//接收数据
byte[] buffer = new byte[10000];
InputStream inputStream = null;
try {
    inputStream = socket_my.getInputStream();
} catch (IOException e) {
    e.printStackTrace();
}
DataInputStream input = new DataInputStream(inputStream);
int length = 0;
try {
    length = input.read(buffer);
} catch (IOException e) {
    e.printStackTrace();
}
String Msg = null;
try {
    Msg = new String(buffer, 0, length, "gb2312");
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}
Log.e("data:", Msg);
System.out.println("***Msg***"+Msg);

 

 

 

 

未完待续~~~~