示例代码
本节包含一些使用 MetaCar 库的示例和教程,帮助您更快地理解如何实现自己的应用。
基础控制示例
以下是一个基础的车辆控制示例,展示了如何使用键盘输入来控制车辆:
基础控制示例 (examples/main.py)
1import logging
2import keyboard
3import math
4from metacar import SceneAPI, GearMode, VehicleControl, Vector3, SimCarMsg
5
6USE_GUI = True
7
8if USE_GUI:
9 from gui import Dashboard
10
11logging.basicConfig(
12 filename="autodrive.log",
13 format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
14 level=logging.DEBUG,
15 encoding="utf-8",
16)
17logger = logging.getLogger(__name__)
18
19current_gear = GearMode.DRIVE
20use_keyboard = True
21
22
23def set_gear(gear: GearMode):
24 global current_gear
25 current_gear = gear
26
27
28def toggle_keyboard():
29 global use_keyboard
30 use_keyboard = not use_keyboard
31
32
33def get_vehicle_control_from_keyboard() -> VehicleControl:
34 vc = VehicleControl()
35 vc.gear = current_gear
36 if keyboard.is_pressed("up") or keyboard.is_pressed("w"):
37 value = 0.5 if keyboard.is_pressed("shift") else 1
38 if current_gear == GearMode.DRIVE:
39 vc.throttle = value
40 elif current_gear == GearMode.REVERSE:
41 vc.brake = value
42 elif keyboard.is_pressed("down") or keyboard.is_pressed("s"):
43 value = 0.5 if keyboard.is_pressed("shift") else 1
44 if current_gear == GearMode.DRIVE:
45 vc.brake = value
46 elif current_gear == GearMode.REVERSE:
47 vc.throttle = value
48 if keyboard.is_pressed("left") or keyboard.is_pressed("a"):
49 vc.steering = -1
50 elif keyboard.is_pressed("right") or keyboard.is_pressed("d"):
51 vc.steering = 1
52 return vc
53
54
55def calc_throttle_brake(
56 current_speed: float, target_speed: float
57) -> tuple[float, float]:
58 K = 0.2
59 B = 0.2
60 acceleration = (target_speed - current_speed) * K + B
61 if acceleration > 0:
62 return min(acceleration, 1), 0
63 return 0, min(-acceleration * 0.5, 1)
64
65
66# Stanley 算法
67def calc_steering(
68 pos: Vector3, yaw: float, speed: float, trajectory: list[Vector3]
69) -> float:
70 K = 0.5
71 for traj_pos in trajectory:
72 if math.dist(traj_pos, pos) > K * speed:
73 target_pos = traj_pos
74 break
75 else:
76 target_pos = trajectory[-1]
77 theta = (target_pos - pos).yaw_rad()
78 steering_angle = (theta - yaw) % (2 * math.pi)
79 if steering_angle > math.pi:
80 steering_angle -= 2 * math.pi
81 steering = math.degrees(-steering_angle) / 45
82 return max(min(steering, 1), -1)
83
84
85def get_vehicle_control_from_algorithm(msg: SimCarMsg) -> VehicleControl:
86 vc = VehicleControl()
87 vc.gear = GearMode.DRIVE
88 # 目前只支持固定速度
89 vc.throttle, vc.brake = calc_throttle_brake(msg.data_main_vehicle.speed, 15)
90 vc.steering = calc_steering(
91 Vector3(
92 msg.data_gnss.pose_gnss.pos_x,
93 msg.data_gnss.pose_gnss.pos_y,
94 msg.data_gnss.pose_gnss.pos_z,
95 ),
96 -math.radians(msg.data_gnss.pose_gnss.ori_z),
97 msg.data_main_vehicle.speed,
98 msg.trajectory,
99 )
100 return vc
101
102
103def main():
104 api = SceneAPI()
105
106 keyboard.add_hotkey("space", api.retry_level)
107 keyboard.add_hotkey("n", api.skip_level)
108
109 keyboard.add_hotkey("r", lambda: set_gear(GearMode.REVERSE))
110 keyboard.add_hotkey("f", lambda: set_gear(GearMode.DRIVE))
111 keyboard.add_hotkey("t", lambda: set_gear(GearMode.NEUTRAL))
112 keyboard.add_hotkey("g", lambda: set_gear(GearMode.PARKING))
113
114 keyboard.add_hotkey("c", toggle_keyboard)
115
116 api.connect()
117 static_data = api.get_scene_static_data()
118 if USE_GUI:
119 dashboard = Dashboard(static_data)
120 logger.info("启动 GUI 界面")
121 logger.info("开始场景")
122
123 for sim_car_msg, frame in api.main_loop():
124 if use_keyboard:
125 vehicle_control = get_vehicle_control_from_keyboard()
126 else:
127 vehicle_control = get_vehicle_control_from_algorithm(sim_car_msg)
128 api.set_vehicle_control(vehicle_control)
129 if USE_GUI:
130 dashboard.update(sim_car_msg)
131 logger.info("结束场景")
132 if USE_GUI:
133 dashboard.quit()
134 logger.info("关闭 GUI 界面")
135
136
137if __name__ == "__main__":
138 main()
这个例子展示了:
如何创建和连接 SceneAPI
如何使用键盘输入控制车辆
如何使用 Stanley 横向控制算法控制车辆
如何在主循环中不断获取车辆状态并发送控制命令
GUI 界面示例
MetaCar 库还包含了一个使用 GUI 界面展示车辆状态的示例。您可以在以下位置找到完整代码:
examples/gui.py- GUI 界面实现代码
这个示例展示了:
如何创建图形界面展示车辆状态
如何解析和显示车辆传感器数据
如何实时更新界面中显示的内容
高级开发技巧
在开发自己的应用程序时,以下是一些有用的高级技巧:
图像处理 - 使用 frame 图像数据实现计算机视觉算法,如车道线检测、交通标志识别等
路径规划 - 基于 static_data.route 和 sim_car_msg.trajectory 实现更复杂的路径规划
传感器融合 - 结合摄像头和其他传感器数据实现更准确的环境感知
状态机设计 - 为车辆控制创建状态机,处理不同场景下的行为转换
备注
关于基本用法和入门指南,请参阅 快速入门 文档。 本节示例侧重于展示更复杂的应用场景和实现技巧。