cameradecision.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. import proto.cameraobjectarray_pb2 as cameraobjectarray_pb2
  2. import proto.decitionspeedlimit_pb2 as decitionspeedlimit_pb2
  3. import proto.lightarray_pb2 as lightarray_pb2
  4. import proto.objectarray_pb2 as objectarray_pb2
  5. import proto.chassis_pb2 as chassis_pb2
  6. import math
  7. from typing import List
  8. from datetime import datetime, timedelta
  9. import time
  10. from xdg.Config import setIconSize
  11. class Point2D:
  12. def __init__(self, x, y,hdg):
  13. self.mx = x
  14. self.my = y
  15. self.mhdg = hdg
  16. while self.mhdg < 0:
  17. self.mhdg = self.mhdg + 2.0* math.pi
  18. while self.mhdg >= 2.0*math.pi:
  19. self.mhdg = self.mhdg - 2.0* math.pi
  20. def __str__(self):
  21. return f"Point2D({self.mx}, {self.my})"
  22. class CameraDecision:
  23. def __init__(self):
  24. self.mendacc = -0.7 # 抵达终点时的减速度为 -0.7 m/s²
  25. self.mmaxwheel = 430 # 最大方向盘角度
  26. self.mdefaultacc = 1.0 # 加速时的默认加速度
  27. self.mspeed = 10.0 # 目标速度 10 km/h
  28. self.cspeed = self.mspeed
  29. self.mstopdistoobs = 6.0 # 距离障碍物6米时停车
  30. self.mstopdisacc = -1.0 # 障碍物检测时的减速度
  31. self.mvehwidth = 2.3 # 车辆宽度
  32. self.speed5_nodetect = 0
  33. self.is_stop = False
  34. pass
  35. def CalcDecision(self, x_chassis, xobjarray_sign, xobjarray_light, xobjarray_lidar):
  36. acc = 0.0 # 加速度,m/s² (>0 加速, <0 制动)
  37. wheel = 0.0 # 方向盘转角 (>0 左转, <0 右转, 范围: -430 ~ 430)
  38. speed = 0.0 # 车速
  39. leftLamp = False # 左转向灯
  40. rightLamp = False # 右转向灯
  41. # 获取当前车辆速度
  42. veh_speed = x_chassis.vel
  43. print("veh speed: ",veh_speed)
  44. # 控制加速度,使车速维持在目标速度 mspeed 附近
  45. if not self.is_stop:
  46. if veh_speed < self.cspeed:
  47. acc = min(0.5, self.cspeed - veh_speed) # 根据差值调整加速度,最大为0.5 m/s²
  48. elif veh_speed > self.cspeed:
  49. acc = max(-0.5, self.cspeed - veh_speed) # 根据差值调整减速度,最小为-0.5 m/s²
  50. ######################决策逻辑代码########################
  51. if self.speed5_nodetect < 20:
  52. self.speed5_nodetect += 1
  53. # 基于标志物的决策
  54. for pobj in xobjarray_sign.obj:
  55. print("sign type: ",pobj.type)
  56. if pobj.type == "Left": # 左转标志
  57. wheel = min(self.mmaxwheel, 30) # 控制转角
  58. leftLamp = True # 打开右转向灯
  59. if pobj.type == "Right": # 右转标志
  60. wheel = max(-self.mmaxwheel, -30) # 控制转角
  61. rightLamp = True # 打开左转向灯
  62. if pobj.type == "Speed5": # 限速5 km/h标志
  63. self.cspeed = 5 # 将目标速度调整为 5 km/h
  64. self.speed5_nodetect = 0
  65. if self.speed5_nodetect > 10:
  66. self.cspeed = self.mspeed
  67. # 基于交通信号灯的决策
  68. for light in xobjarray_light.light:
  69. if light.type == 1: # 绿灯,加速通过
  70. self.is_stop = False
  71. acc = 0.5 # 加速
  72. elif light.type == 2: # 红灯,停止
  73. self.is_stop = True
  74. acc = -1.0 # 大幅减速
  75. ############################################################
  76. # 创建并返回决策对象
  77. xdecisiion = decitionspeedlimit_pb2.decitionspeedlimit()
  78. xdecisiion.wheelAngle = wheel
  79. xdecisiion.accelerator = acc
  80. xdecisiion.brake = 0
  81. xdecisiion.speed = speed
  82. xdecisiion.leftLamp = leftLamp
  83. xdecisiion.rightLamp = rightLamp
  84. print("acc: ",acc)
  85. # 制动决策
  86. if acc < 0:
  87. xdecisiion.brake = abs(acc) # 将负加速度转换为制动值
  88. xdecisiion.torque = 0 # 加速度为负时,无需扭矩输出
  89. else:
  90. xdecisiion.brake = 0 # 没有制动
  91. fVehWeight = 1800 # 车辆重量,单位:kg
  92. fRollForce = 50 # 滚动阻力
  93. fRatio = 2.5 # 扭矩比例因子
  94. fNeed = fRollForce + fVehWeight * acc # 计算所需的动力
  95. xdecisiion.torque = 100 # 计算输出扭矩
  96. if acc == 0:
  97. xdecisiion.torque = 0
  98. return xdecisiion
  99. def is_point_in_rotated_rectangle(self,x, y, x1, y1, yaw, l, w):
  100. # 将长方形的左下角坐标转换到原点
  101. x_rel = x - x1
  102. y_rel = y - y1
  103. # 计算旋转矩阵(逆时针旋转)
  104. # | cos(yaw) -sin(yaw) |
  105. # | sin(yaw) cos(yaw) |
  106. cos_yaw = math.cos(yaw)
  107. sin_yaw = math.sin(yaw)
  108. # 应用旋转矩阵到相对坐标
  109. x_rotated = x_rel * cos_yaw + y_rel * sin_yaw
  110. y_rotated = -x_rel * sin_yaw + y_rel * cos_yaw
  111. # 判断点是否在旋转后的长方形内
  112. # 长方形的边界在旋转后的坐标系中是 [-l/2, l/2] x [-w/2, w/2]
  113. if -l/2 <= x_rotated <= l/2 and -w/2 <= y_rotated <= w/2:
  114. return True
  115. else:
  116. return False
  117. def GaussProj(self,lon,lat):
  118. iPI = 0.0174532925199433
  119. ZoneWide = 6
  120. a = 6378245.0
  121. f = 1.0 / 298.3
  122. ProjNo = int(lon / ZoneWide)
  123. longitude0 = ProjNo * ZoneWide + ZoneWide / 2
  124. longitude0 = longitude0 * iPI
  125. latitude0 = 0
  126. longitude1 = lon * iPI #经度转换为弧度
  127. latitude1 = lat * iPI #//纬度转换为弧度
  128. e2 = 2 * f - f * f
  129. ee = e2 * (1.0 - e2)
  130. NN = a / math.sqrt(1.0 - e2 * math.sin(latitude1)*math.sin(latitude1))
  131. T = math.tan(latitude1)*math.tan(latitude1)
  132. C = ee * math.cos(latitude1)*math.cos(latitude1)
  133. A = (longitude1 - longitude0)*math.cos(latitude1)
  134. M = a * ((1 - e2 / 4 - 3 * e2*e2 / 64 - 5 * e2*e2*e2 / 256)*latitude1 - (3 * e2 / 8 + 3 * e2*e2 / 32 + 45 * e2*e2*e2 / 1024)*math.sin(2 * latitude1)+ (15 * e2*e2 / 256 + 45 * e2*e2*e2 / 1024)*math.sin(4 * latitude1) - (35 * e2*e2*e2 / 3072)*math.sin(6 * latitude1))
  135. xval = NN * (A + (1 - T + C)*A*A*A / 6 + (5 - 18 * T + T * T + 72 * C - 58 * ee)*A*A*A*A*A / 120)
  136. yval = M + NN * math.tan(latitude1)*(A*A / 2 + (5 - T + 9 * C + 4 * C*C)*A*A*A*A / 24 + (61 - 58 * T + T * T + 600 * C - 330 * ee)*A*A*A*A*A*A / 720)
  137. X0 = 1000000 * (ProjNo + 1) + 500000
  138. Y0 = 0
  139. xval = xval + X0; yval = yval + Y0;
  140. X = xval
  141. Y = yval
  142. return X,Y
  143. def GaussProjInvCal(self,X,Y):
  144. iPI = 0.0174532925199433 #3.1415926535898/180.0;
  145. a = 6378245.0
  146. f = 1.0 / 298.3 # //54年北京坐标系参数
  147. #////a=6378140.0; f=1/298.257; //80年西安坐标系参数
  148. ZoneWide = 6 # ////6度带宽
  149. ProjNo = int(X / 1000000) # //查找带号
  150. longitude0 = (ProjNo - 1) * ZoneWide + ZoneWide / 2
  151. longitude0 = longitude0 * iPI # //中央经线
  152. X0 = ProjNo * 1000000 + 500000
  153. Y0 = 0
  154. xval = X - X0; yval = Y - Y0 #//带内大地坐标
  155. e2 = 2 * f - f * f
  156. e1 = (1.0 - math.sqrt(1 - e2)) / (1.0 + math.sqrt(1 - e2))
  157. ee = e2 / (1 - e2)
  158. M = yval
  159. u = M / (a*(1 - e2 / 4 - 3 * e2*e2 / 64 - 5 * e2*e2*e2 / 256))
  160. fai = u + (3 * e1 / 2 - 27 * e1*e1*e1 / 32)*math.sin(2 * u) + (21 * e1*e1 / 16 - 55 * e1*e1*e1*e1 / 32)*math.sin(4 * u)+ (151 * e1*e1*e1 / 96)*math.sin(6 * u) + (1097 * e1*e1*e1*e1 / 512)*math.sin(8 * u)
  161. C = ee * math.cos(fai)*math.cos(fai)
  162. T = math.tan(fai)*math.tan(fai)
  163. NN = a / math.sqrt(1.0 - e2 * math.sin(fai)*math.sin(fai))
  164. R = a * (1 - e2) / math.sqrt((1 - e2 * math.sin(fai)*math.sin(fai))*(1 - e2 * math.sin(fai)*math.sin(fai))*(1 - e2 * math.sin(fai)*math.sin(fai)))
  165. D = xval / NN
  166. #//计算经度(Longitude) 纬度(Latitude)
  167. longitude1 = longitude0 + (D - (1 + 2 * T + C)*D*D*D / 6 + (5 - 2 * C + 28 * T - 3 * C*C + 8 * ee + 24 * T*T)*D*D*D*D*D / 120) / math.cos(fai)
  168. latitude1 = fai - (NN*math.tan(fai) / R)*(D*D / 2 - (5 + 3 * T + 10 * C - 4 * C*C - 9 * ee)*D*D*D*D / 24 + (61 + 90 * T + 298 * C + 45 * T*T - 256 * ee - 3 * C*C)*D*D*D*D*D*D / 720)
  169. #//转换为度 DD
  170. longitude = longitude1 / iPI
  171. latitude = latitude1 / iPI
  172. return longitude,latitude