mqtt 多线程根据里程计建设道路
from math import atan2
import cv2
import numpy as np
import argparse
import os
import sys
import datetime
from paho.mqtt import client as mqtt_client
import random
import time
import threading
import json
import math
MQTT相关
broker = '127.0.0.1'
broker = 'www.woyilian.com'
port = 1883
odomxyz_topic = "/odom/xyz"
raw_odom_topic ="/sensors/odom"
bno_topic = "/sensors/bno085"
client_id = 'python-mqtt-{}'.format(random.randint(0, 1000))
控制指令topic
cmd_vel_topic = "/cmd/vel"
vr =0
vl =0
vel =0.4
ang =0.1
start_flg =0
glat =0
glnt =0
gpsvelocity =0
ang_bias =0
_gPosition_x =0
_gPosition_y =0
class caculate_baidu_map:
def init(self):
self.lat1 =None
self.lon1 = None
self.lat2 = None
self.lon2 = None
def calculate_distance(self):
# 将经纬度转换为弧度
_lat1, _lon1, _lat2, _lon2 = map(math.radians, [self.lat1, self.lon1, self.lat2, self.lon2])
# 根据Haversine公式计算距离
dlon = _lon2 - _lon1
dlat = _lat2 - _lat1
a = math.sin(dlat/2)**2 + math.cos(_lat1) * math.cos(_lat2) * math.sin(dlon/2)**2
c = 2 * math.asin(math.sqrt(a))
r = 6371393 # 地球平均半径,单位为meters
distance = c * r
return distance
def calculate_bearing(self):
# 将经纬度转换为弧度
_lat1, _lon1, _lat2, _lon2 = map(math.radians, [self.lat1, self.lon1, self.lat2, self.lon2])
# 计算两个点在二维平面上的向量
dx = _lon2 - _lon1
dy = _lat2 - _lat1
# 计算该向量的角度
bearing = math.atan2(dy, dx)
# 将角度转换为0-360度
bearing = math.degrees(bearing)
# 确保航向角在0-360度之间
if bearing < -180:
bearing += 360
elif bearing > 180:
bearing -= 360
return bearing
def conver2wheel(v,w):
global vr,vl
vr = (2v + w10)/2
vl = (2v - w10)/2
def getdatas(x,y):
data = {"x":"%.2f"%(x),"y":"%.2f"%(y)
}
return data
def loop():
global vel,ang,start_flg,glnt,glat,gpsvelocity
last_time =0
init_x =800/2
init_y =800/2
pix_di =0
start_x =0
start_y =0
first_flg =0
g_img =None
g_img = np.ones((800,800), np.uint8)
g_img.fill(0)
geocood = caculate_baidu_map()
f_index = "waypoints.csv"
road_file = "roadpoints.csv"
while True:
time.sleep(0.1)
if glat == 0:
continue
if(first_flg ==0) :
first_flg =1
geocood.lat1 = glat
geocood.lon1 = glnt
continue
#判断是否行驶超过2.5m的误差3m
geocood.lat2 =glat
geocood.lon2 = glnt
dis = geocood.calculate_distance()
#print(f"dis:{dis} \n")
if(dis >= (0.1)):
#print(str(x) + ' '+ str(y))
bearing = geocood.calculate_bearing()
print(f"dis:{dis},bearing:{bearing} \n")
rad = math.radians(bearing)
#print(f"rad:{rad} \n")
img =None
img = np.ones((800,800), np.uint8)
img.fill(0)
pix_di = (dis)/1;
start_x = (init_x + (pix_di*math.cos(rad)))*100/100
start_y = (init_y + (pix_di*math.sin(rad)))*100/100
print(str(init_x)+" "+str(init_y)+" "+str(start_x)+" "+str(start_y))
with open(f_index, "a") as findex:
findex.write(str(glat)+","+str(glnt)+","+str(start_x)+","+str(start_y)+"\n")
cv2.line(img,(int(init_x),int(init_y)), (int(start_x),int(start_y)),(255),10)
cv2.line(g_img,(int(init_x),int(init_y)), (int(start_x),int(start_y)),(255),10)
#找到临时的道路为白色点位
idx = cv2.findNonZero( img )
#cv2.imshow('img', img)
#cv2.waitKey(500)
#byteArr = bytearray(idx)#1xN维的数据
response_2d = None
response_2d = idx.reshape(-1, idx.shape[-1])
with open(road_file, "ab") as f:
np.savetxt(f, response_2d, fmt='%d',delimiter=',') # 整数
jsondata =getdatas(start_x,start_y)
print(jsondata)
d = json.dumps(jsondata)
result = client.publish(roads_topic,d,0)
status = result[0]
if status == 0:
print(f"Send to topic `{roads_topic}`")
else:
print(f"Failed to send message to topic {roads_topic}")
cv2.imwrite('road.png', g_img)
geocood.lat1 = glat
geocood.lon1 = glnt
init_x = start_x
init_y = start_y
作为子线程开启
th = threading.Thread(target=loop)
th.setDaemon(True)
th.start()
定义mqtt的client
client = mqtt_client.Client(client_id)
last_time =0
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe("test")
def on_message(client, userdata, msg):
global glat,glnt,ang_bias,first_in,_gPosition_x,_gPosition_y
if (msg.topic == odomxyz_topic):
data = json.loads(msg.payload.decode("utf-8"))
glat = data['x']
glnt = data['y']
gpsvelocity = data['z']
if (msg.topic == raw_odom_topic):
data = json.loads(msg.payload.decode("utf-8"))
glat = data['le']
glnt = data['re']
Compute distance moved by each wheel
Dl = data['le']*0.1326 *1.1#/mm
Dr = data['re']*0.1326 *1.1#mm
Dc = (Dl+Dr)/2.0
theta =(Dr-Dl)/200 #theta 车宽度为l=0.2m
o_x = Dc *cos(ang*3.1415926/180)#转换成mm
o_y = Dc *sin(ang*3.1415926/180)
_gPosition_x = _gPosition_x + o_x
_gPosition_y = _gPosition_y + o_y
#gpsvelocity = data['z']
if (msg.topic == bno_topic):
data = json.loads(msg.payload.decode("utf-8"))
if first_in ==0:
first_in =1
ang_bias = data['yaw']
else:
glnt = data['roll']
ang = data['yaw'] -ang_bias
if(ang < -180) #Note:numpy and OpenCV X and Y reversed
ang = ang + 360
else if( ang > 180)
ang = ang - 360
暂时保留
def publish(client):
print(" datetime")
if name == 'main':
print("gps connected!")
client.on_connect = on_connect
client.on_message = on_message
client.connect(broker, port, 60)
publish(client)
# 订阅来自定位
client.subscribe(odomxyz_topic)
# 订阅来自里程计定位
client.subscribe(raw_odom_topic)
# 订阅来自bno
client.subscribe(bno_topic)
client.loop_forever()