实现
1)界面绘制
? ? ?? ?
2)手机指南针功能调用
3)记录行进方向 // 创建实例时注册方向传感器
Button_Start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/* 定义手机传感器 */
// 获取传感器管理器
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
// 地磁传感器,单位是uT(微特斯拉),测量设备周围三个物理轴(x,y,z)的磁场
masensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
// 加速度传感器,单位是m/s2,测量应用于设备X、Y、Z轴上的加速度
accesensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
/* 注册传感器 */
// 注册地磁传感器
sensorManager.registerListener(sensorEventListener, masensor, SensorManager.SENSOR_DELAY_GAME);
// 注册加速度传感器
sensorManager.registerListener(sensorEventListener, accesensor,SensorManager.SENSOR_DELAY_GAME);
}
});
// 响应传感器监听
SensorEventListener sensorEventListener = new SensorEventListener() {
float[] acceleValues = new float[3]; //加速度传感器值
float[] magneticValues = new float[3]; //地磁传感器值
@Override
public void onSensorChanged(SensorEvent event) {
// 获得传感器值
if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
acceleValues = event.values.clone();
}else if(event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD){
magneticValues = event.values.clone();
}
float[] values = new float[3];
float[] R = new float[9];
SensorManager.getRotationMatrix(R, null, acceleValues, magneticValues);
SensorManager.getOrientation(R, values);
// 方向角,以北为正方向
degrees = -(float)Math.toDegrees(values[0]);
};
// 记录节点方向
if(diff >= timeinterval) { // 达到时间间隔
// 记录当前时间(日期+时间)和方向角,最新记录最前记录
String st = df.format(curDate.getTime()) + ": " + degrees + "\n" + etmout.getText().toString();
etmout.setText(st); // 显示在文本框中
curDate = new Date(System.currentTimeMillis());
ct = curDate.getTime();
// 显示时间间隔
tvtest.setText(String.valueOf(et) + " --- " + String.valueOf(ct));
}
4)记录关键行程点
? ? ? 手机不识别这是哪里?
? ? ? 好吧,停下自动记录,手工输入吧~~
5)保存行程记录
? ? ? 保存本机还要权限注册和申请,懒,先不做。
? ? ? 好吧,手工拷贝并保存到本机。
6)APP生成/发布 // build.gradle
// defaultConfig 增加以下节点,定义生成的APP应用名
android.applicationVariants.all {
variant ->
variant.outputs.all {
outputFileName = "CompassPath.apk"
}
}
?5)调用行程记录使用Python绘图 import math # 数据处理,主要是小数位数
import matplotlib.pyplot as plt # 画图
# 对方向角文件(手机获取并手动何存)进行解析
# 原文件格式:日期、时间、里程方向角、里程点名字
# 记录分解为:日期、时间(小时、分、秒)、里程点方向X轴坐标、里程点方向Y轴坐标、里程点名字
def get_direction(filename):
pdate = []
ptime = []
pdirect = []
pname = []
pall = [] # date, hour, min, sec, X_direct-cos, Y_direct-sin, name
# 读入文件
with open("./"+filename,"r", encoding='utf-8') as fp:
frls = fp.readlines()
for fl in frls:
pt = []
## replace all double blank
while fl.count(" ")>0:
fl = fl.replace(" "," ")
pf = fl.split(" ",2)
## NULL or there is no dirction data
if fl.strip() == "" or len(pf) < 3:
continue
else:
## get date
pdate.append(pf[0])
pt.append(pf[0])
## get time and split into hour, minute, second
ptime.append(pf[1][0:-1].split(":"))
ptpf = pf[1][0:-1].split(":")
pt.append(int(ptpf[0]))
pt.append(int(ptpf[1]))
pt.append(int(ptpf[2]))
## get direction and address point description
pdir = pf[2].replace("\n","").strip()
pp = 0
pn = ""
for i in pdir:
if i.isnumeric() or i == "." or i == "-":
continue
else:
pp = pdir.index(i)
break
if pp == 0:
pd = float(pdir) + 90
pname.append("?")
pn = "?"
else:
pd = float(pdir[0:pp]) + 90
pname.append(pdir[pp:len(pdir)].strip())
pn = pdir[pp:len(pdir)].strip()
## 方向角转成 X,Y轴坐标
pt.append(round(math.cos(math.pi*pd/180),2))
pt.append(round(math.sin(math.pi*pd/180),2))
pt.append(pn)
pall.append(pt)
pall.reverse()
return pall
def drawpath(points):
px = []
py = []
pname = []
ppx = 0 # perious node x value
pcx = 0 # current node x value
ppy = 0 # perious node y value
pcy = 0 # current node y value
ph = 0 # hour
pm = 0 # minutes
ps = 0 # seconds
totaltime = 0
for i in range(0,len(points)):
pi = points[i]
ph = pi[1]
pm = pi[2]
ps = pi[3]
ptime = 0 # time interval
## 累计路程 X, Y
if i > 0:
pcx = pi[4] + ppx
pcy = pi[5] + ppy
ptime = ((ph-points[i-1][1])*60*60 + (pm-points[i-1][2])*60 + (ps-points[i-1][3]))/60 # double length per 30 seconds
else:
pcx = pi[4]
pcy = pi[5]
ptime = 1.0
ppx = pcx
ppy = pcy
totaltime = round(totaltime+ptime,1)
px.append(pcx)
py.append(pcy)
pn = ""
if i == 0:
pn = "Start: " + pi[6]
elif i == len(points)-1:
pn = "End: " + pi[6]
else:
pn = pi[6]
pname.append(pn + ", " + str(math.ceil(ptime)) + "'" + ", " + str(totaltime) + "'")
## draw line with points address
waypoints = [px, py]
plt.plot(waypoints[0], waypoints[1], '^-b', MarkerEdgeColor='g',MarkerFaceColor='g')
## lable name
for i in range(0,len(pname)):
plt.text(px[i]+0.05,py[i]+0.1,pname[i],ha='center', va='center', color="blue",clip_on=True, fontsize=8)
plt.grid(False)
## 坐标轴
plt.tick_params(axis='x', which='both', bottom=False, top=False, labelbottom=False)
plt.tick_params(axis='y', which='both', left=False, right=False, labelleft=False)
## 解决乱码
plt.rcParams['font.sans-serif'] = ['SimHei'] # aovid wide code
## X,Y轴坐标起点 和 终点设置
plt.xlim(math.floor(min(px)) if min(px)>0 else math.floor(min(px)),math.ceil(max(px)) if max(px)>0 else math.ceil(max(px)))
plt.ylim(math.floor(min(py)) if min(py)>0 else math.floor(min(py)),math.ceil(max(py)) if max(py)>0 else math.ceil(max(py)))
plt.title(label='地点名,阶段耗时,总耗时(分钟)',loc='left',fontsize=8)
plt.show()
6)显示
大概就是这个样子吧,每隔5秒记录一次方向角。对吗?
实际操作时在关键里程点开始记录方向角,记录后停止,标记里程碑点名字,到下个关键里程点再次记录。
好处?不用手机实时的记录那么多方向点,而且还要标记名字。
似乎这个Time Interval有点鸡肋
? ? ? ? ? ? ? ?