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

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

整体规划:

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

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

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

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

4.做惯性导航的计算


1.Android使用到的技术

1.1 Android开发中保留两位小数

我用的是方法三。。。。

参考链接:

方法一:

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客户端发送数据给电脑

参考链接:

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

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

android 惯导 20680移植 安卓惯性导航_陀螺仪

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

在最开始定义socket

Socket socket_my;

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

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

android 惯导 20680移植 安卓惯性导航_Android_02

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

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 惯导 20680移植 安卓惯性导航_android 惯导 20680移植_03

发送数据给服务端

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);

 

 

 

 

未完待续~~~~