.. _py_line_tracking: 5. 线路追踪 ==================================== 本项目将使用灰度模块让 PiCar-X 沿着一条线向前移动。使用深色胶带制作一条尽可能直且 不太弯曲的线路。若 PiCar-X 偏离线路,可能需要进行一些实验调整。 **运行代码** .. raw:: html .. code-block:: cd ~/picar-x/example sudo python3 5.minecart_plus.py 运行代码后,PiCar-X 将沿着线路向前移动。 **代码** .. note:: 您可以 **修改/重置/复制/运行/停止** 以下代码。但在此之前,需进入源码路径,例如 ``picar-x/example``。修改代码后,您可以直接运行以查看效果。 .. raw:: html .. code-block:: python from picarx import Picarx from time import sleep px = Picarx() # px = Picarx(grayscale_pins=['A0', 'A1', 'A2']) # 请运行 ./calibration/grayscale_calibration.py 自动校准灰度值 # 或者通过以下代码手动修改参考值 # px.set_line_reference([1400, 1400, 1400]) current_state = None px_power = 10 offset = 20 last_state = "stop" def outHandle(): global last_state, current_state if last_state == 'left': px.set_dir_servo_angle(-30) px.backward(10) elif last_state == 'right': px.set_dir_servo_angle(30) px.backward(10) while True: gm_val_list = px.get_grayscale_data() gm_state = get_status(gm_val_list) print("outHandle gm_val_list: %s, %s"%(gm_val_list, gm_state)) currentSta = gm_state if currentSta != last_state: break sleep(0.001) def get_status(val_list): _state = px.get_line_status(val_list) # [bool, bool, bool], 0 表示线路,1 表示背景 if _state == [0, 0, 0]: return 'stop' elif _state[1] == 1: return 'forward' elif _state[0] == 1: return 'right' elif _state[2] == 1: return 'left' if __name__=='__main__': try: while True: gm_val_list = px.get_grayscale_data() gm_state = get_status(gm_val_list) print("gm_val_list: %s, %s"%(gm_val_list, gm_state)) if gm_state != "stop": last_state = gm_state if gm_state == 'forward': px.set_dir_servo_angle(0) px.forward(px_power) elif gm_state == 'left': px.set_dir_servo_angle(offset) px.forward(px_power) elif gm_state == 'right': px.set_dir_servo_angle(-offset) px.forward(px_power) else: outHandle() finally: px.stop() print("stop and exit") sleep(0.1) **工作原理** 该 Python 脚本使用灰度传感器控制 Picarx 机器人小车的导航。以下是其主要组成部分的说明: * 导入与初始化: 脚本导入了控制机器人小车的 Picarx 类以及 time 模块中的 sleep 函数,用于添加延时操作。 创建了 Picarx 的实例,注释行显示了一个使用特定灰度传感器引脚的初始化方法。 .. code-block:: python from picarx import Picarx from time import sleep px = Picarx() * 配置与全局变量: ``current_state`` 、 ``px_power`` 、 ``offset`` 和 ``last_state`` 是用于跟踪和控制小车运动的全局变量。 ``px_power`` 设置电机功率, ``offset`` 用于调整转向角度。 .. code-block:: python current_state = None px_power = 10 offset = 20 last_state = "stop" * ``outHandle`` 函数: 当小车需要处理“脱线”情况时调用此函数。 它根据 ``last_state`` 调整小车的方向,并检查灰度传感器值以确定新状态。 .. code-block:: python def outHandle(): global last_state, current_state if last_state == 'left': px.set_dir_servo_angle(-30) px.backward(10) elif last_state == 'right': px.set_dir_servo_angle(30) px.backward(10) while True: gm_val_list = px.get_grayscale_data() gm_state = get_status(gm_val_list) print("outHandle gm_val_list: %s, %s"%(gm_val_list, gm_state)) currentSta = gm_state if currentSta != last_state: break sleep(0.001) * ``get_status`` 函数: 此函数解释灰度传感器数据( ``val_list`` ),以确定小车的导航状态。 根据哪个传感器检测到线路,小车的状态可以是“forward”(前进)、“left”(左转)、“right”(右转)或“stop”(停止)。 .. code-block:: python def get_status(val_list): _state = px.get_line_status(val_list) # [bool, bool, bool], 0 表示线路,1 表示背景 if _state == [0, 0, 0]: return 'stop' elif _state[1] == 1: return 'forward' elif _state[0] == 1: return 'right' elif _state[2] == 1: return 'left' * 主循环: ``while True`` 循环不断检查灰度数据并相应调整小车的运动。 根据 ``gm_state``,它设置转向角度和运动方向。 .. code-block:: python if __name__=='__main__': try: while True: gm_val_list = px.get_grayscale_data() gm_state = get_status(gm_val_list) print("gm_val_list: %s, %s"%(gm_val_list, gm_state)) if gm_state != "stop": last_state = gm_state if gm_state == 'forward': px.set_dir_servo_angle(0) px.forward(px_power) elif gm_state == 'left': px.set_dir_servo_angle(offset) px.forward(px_power) elif gm_state == 'right': px.set_dir_servo_angle(-offset) px.forward(px_power) else: outHandle() * 安全与清理: ``try...finally`` 块确保脚本中断或结束时小车能够安全停止。 .. code-block:: python finally: px.stop() print("stop and exit") sleep(0.1) 总结,该脚本利用灰度传感器引导 Picarx 机器人小车沿线路导航。它通过连续读取传感器数据来确定方向,并相应调整小车的运动和转向。 ``outHandle`` 函数为小车在需要大幅调整路径时提供额外逻辑支持。