示例代码
本节包含一些使用 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 examples.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 * 2 # 2 是一个可调参数
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 界面实现代码
这个示例展示了:
如何创建图形界面展示车辆状态
如何解析和显示车辆传感器数据
如何实时更新界面中显示的内容
开发您的第一个应用
开发自己的应用程序时,建议按照以下流程进行:
引入所需的模块和类
初始化并连接 SceneAPI
设计车辆控制算法
在主循环中实时处理数据并发送控制指令
代码框架示例:
from metacar import SceneAPI, VehicleControl, GearMode
import logging
# 配置日志系统
logging.basicConfig(filename="myapp.log", level=logging.INFO)
logger = logging.getLogger(__name__)
def main():
# 初始化 API
api = SceneAPI()
# 建立仿真连接
api.connect()
logger.info("成功连接仿真环境")
# 获取场景静态信息
static_data = api.get_scene_static_data()
# 启动主循环
for sim_car_msg, frame in api.main_loop():
# 在此处实现控制算法
vc = VehicleControl()
# 向仿真环境发送控制指令
api.set_vehicle_control(vc)
logger.info("仿真任务完成")