Android项目之利用手机传感器做惯性导航
利用手机的传感器做手机的姿态解算,利用扩展卡尔曼滤波算法获得手机的航向角、偏航角和滚转角。再进一步做人步行的惯性导航。
需要程序的源码请联系~~~
整体规划:
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"/>
步骤2:开启新线程,现在要求TCP通信必须在非UI线程中开启
在最开始定义socket
Socket socket_my;
在onCreate中定义新线程,线程在syncRunnable函数中运行
//开网络通信线程
SyncRunnable syncRunnable = new SyncRunnable();//定义Runnable接口
Thread thread = new Thread(syncRunnable, "syncRunnable");//定义新线程
thread.start();//开启新线程
在新线程执行函数中开启网络通信
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";//发送的数据
}
}
}
}
发送数据给服务端
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);
未完待续~~~~
上一篇: Docker部署应用
下一篇: Neon指令集优化快速入门教程