https://www.yahboom.com/build.html?id=10955&cid=66...

Tạo vào: 20 tháng 1, 2026

Trả lời bằng GPT-5.2 Thinking bởi Chat01

Suy nghĩ

Addressing Jupyter access issues

The user mentions being unable to access Jupyter after following steps. The Yahboom doc on Jupyter login and password, plus Jupyter docs on port defaults and token authentication, are good resources. We should approach this gently—it’s possible they’re using a different image or the auto-start feature wasn’t set up properly. To diagnose, checking for Jupyter installation with jupyter lab or jupyter --version should help.

Addressing JupyterLab Access Issues with Yahboom and IP

Make sure you're using the Yahboom image. If not, you'll need to install and configure JupyterLab manually, and set a password yourself. The password from the tutorial only works with Yahboom images. Also, verify your IP and port—use ifconfig or your router to check. If the default port 8888 is busy, JupyterLab might switch to another. Make sure you're using token-based authentication, unless a password is set.

Crafting diagnostic steps for JupyterLab access issues

The user may be on Jetson or Raspberry Pi, so let’s keep it general. We can’t use internal sources but will reference the Yahboom doc for login info, Jupyter server docs for token-based authentication, and Jupyter docs for the port issue. I’ll suggest steps like: 1) Check IP address and subnet; 2) Verify Jupyter service is running; 3) Confirm Jupyter listens on 0.0.0.0. I'll also offer help in debugging with error messages.

Diagnosing JupyterLab connection issues

To troubleshoot, here are a few categories:

  1. Network issues: If you get errors like "This site can't be reached" or timeout, there's a potential IP/network problem.
  2. Service not running: The "Connection refused" message means JupyterLab might not be running or the port isn’t available.
  3. Credential issues: If you’re seeing "invalid credentials," make sure you're using the correct password or token.

Details like checking IP with hostname -I or ping can help ensure you're on the same network. If there's a port conflict, Jupyter might automatically select a different port.

Thought for 3m 2s

Trả lời

你们按教程在浏览器输 IP:8888 进不去,一般就落在三类问题里:

  1. IP / 网络不对(最常见)
    教程里的 192.168.2.95:8888 只是示例;实际必须用你这台小车(树莓派/Jetson)的当前 IP,并且电脑要和它在同一局域网(同一个路由器/同一个 Wi-Fi),才能访问。(亚博智能科技官网)
    排查:
  • 在小车上看 IP:hostname -Iip -4 addr
  • 在电脑上 ping 小车IP
    • ping 不通 → 多半没在同一网段/连了“访客 Wi-Fi”/路由器开了“无线隔离(AP isolation)”
  1. 8888 端口上根本没起来 JupyterLab(服务没启动 / 端口换了)
    Jupyter 默认用 8888,但如果 8888 被占用,它可能会自动换到下一个可用端口(8889、8890…)。(Jupyter Documentation)
    排查(在小车上执行):
  • 看 8888 是否在监听:sudo ss -lntp | grep 8888
  • 看 Jupyter 实际开在哪个 URL/端口:jupyter server list(或 jupyter notebook list
  • 如果你用的是 YAHBOOM 的“出厂镜像”,文档说它通常已装好并配置自启动;但自启动服务偶尔会挂,需要手动启动/重启。(亚博智能科技官网)
    • 可尝试:sudo systemctl restart nano_jupyter.service(不同镜像服务名可能不同,也可以 systemctl | grep jupyter 找一下)
  1. 能打开登录页但登录不上(密码/Token 不对)
  • 文档里“密码是 yahboom”只对“他们提供的镜像/已配置好密码”的情况成立。(亚博智能科技官网)
  • 另外,Jupyter Server 默认是 Token 登录(不是固定密码),Token 会出现在启动输出或 jupyter server list 里。(jupyter-server.readthedocs.io)
  • 如果你/同事跑过 jupyter notebook password,那密码就被改成你们设置的新密码了。(亚博智能科技官网)

你们最快的定位方式(按现象选)

  • 浏览器直接“打不开/超时” → 先查 IP/同网段/无线隔离
  • 提示“拒绝连接 connection refused”Jupyter 没在 8888 监听(服务没起或端口变了)
  • 能到登录页但“Invalid credentials” → 用 jupyter server listtoken,或确认是否改过密码

如果你把下面两样信息贴出来(任意一种就行),我可以直接帮你判断是哪一类:
1)浏览器报错文字(超时/拒绝连接/密码错误)
2)在小车上执行 hostname -Ijupyter server list 的输出(打码也行)。

Câu hỏi

af54fb62a7e224fc8d217d985757c7d5.jpgaf54fb62a7e224fc8d217d985757c7d5.jpg

这是我打完这些命令后显示出来的结果,请你查看并进一步思考!!!

Câu hỏi

327047b62f1e3425ced80948e11b2760.jpg327047b62f1e3425ced80948e11b2760.jpg

Suy nghĩ

Examining file and case sensitivity issue

It looks like the error might be due to case sensitivity in Python, as module names are case-sensitive. The user could be dealing with a file named 'McLumk_Wheel_Sports', but the import might have been mistyped or differ slightly in case ('Mclumk' vs. 'McLunk'). I suggest checking the file names with ls to ensure the correct path and spelling.

Proposing a path fix and import check

It looks like the user may be using an incorrect path. To confirm, suggest they check for the correct directory using a simple loop in a Jupyter cell or by running !ls in the terminal. If needed, they should replace the problematic path with /project_demo/lib and reattempt the import. If issues persist, use !find to search for the file.

Troubleshooting Python environment issues

If the file exists but you still can't import, it might be due to multiple Python environments. In Jupyter, check your active Python version with import sys; print(sys.executable). Then install the package using pip with the correct Python executable. Don't forget to restart the kernel to resolve potential path issues.

Thought for 3m 30s

Trả lời

我看了你这张 JupyterLab 的截图,报错核心是这一句:

ModuleNotFoundError: No module named 'McLumk_Wheel_Sports'

这表示 Python 没有在“可搜索路径”里找到 McLumk_Wheel_Sports 这个库/文件。结合你截图里第一行:

python
sys.path.append('/home/pi/project_demo/lib')

而你左侧文件树的真实目录是在:

/project_demo/05.Comprehensive_gameplay/ ...

所以最大概率原因是:你机器上的 demo 实际放在 /project_demo,但代码却把库路径加成了 /home/pi/project_demo/lib(路径不对),导致导入失败。


先用 10 秒确认一下(在 Notebook 里新建一个 cell 直接跑)

python
import os print("exists /home/pi/project_demo/lib =", os.path.exists("/home/pi/project_demo/lib")) print("exists /project_demo/lib =", os.path.exists("/project_demo/lib")) !ls -l /project_demo | head !ls -l /project_demo/lib | head
  • 如果 /home/pi/project_demo/lib 是 False、/project_demo/lib 是 True,那就完全对上了:就是路径写错

解决方法 A(最常见、最快):把路径改对

把你那一格代码改成这样再运行一次:

python
import sys sys.path.append('/project_demo/lib') from McLumk_Wheel_Sports import *

然后 Kernel → Restart Kernel(或重启内核)再从头跑一遍。


解决方法 B:库文件名字不一致(大小写/拼写不同)

Linux 下导入是严格区分大小写的,文件名必须和 import 一模一样。

你在 Notebook 里跑这个找一下真实文件名:

python
!ls -1 /project_demo/lib | grep -i wheel
  • 如果你看到的是比如 McLunk_Wheel_Sports.pyMCLumk_Wheel_Sports.py 之类,就把 import 那行改成和文件名完全一致

解决方法 C:库根本没在 demo 里(需要安装驱动库)

如果你 ls /project_demo/lib 里压根没有 McLumk_Wheel_Sports.py,那就是驱动库没装/没拷贝完整

这时你可以在终端执行(有 setup.py 的情况下):

bash
cd /project_demo/lib sudo python3 setup.py install

装完回到 Jupyter 重启内核再试。


你现在回复我两行信息,我就能一口咬定是哪一种

  1. 你跑完后这两句输出是什么:
  • exists /home/pi/project_demo/lib = ?
  • exists /project_demo/lib = ?
  1. ls -1 /project_demo/lib | grep -i wheel 的输出(截图/复制都行)

Câu hỏi

import sys
import time

sys.path.append('/home/pi/project_demo/lib')

导入麦克纳姆小车驱动库 Import Mecanum Car Driver Library

from McLumk_Wheel_Sports import *

speed = 25#25

try:
while True:
# 从I2C读取巡线传感器数据 Read line sensor data from I2C
track_data = bot.read_data_array(0x0a, 1)
track = int(track_data[0])

# 解析巡线传感器的状态 Analyze the status of the line patrol sensor
x1 = (track >> 3) & 0x01
x2 = (track >> 2) & 0x01
x3 = (track >> 1) & 0x01
x4 = track & 0x01
"""
X2 X1 X3 X4
| | | |
L1 L2 R1 R2
"""
lineL1 = x2
lineL2 = x1
lineR1 = x3
lineR2 = x4

# 0000
if not lineL1 and not lineL2 and not lineR1 and not lineR2:
rotate_right(speed)
time.sleep(1)
# 1X00
elif lineL1 and not lineR1 and not lineR2:
rotate_left(speed-10)
time.sleep(1)
# 00X1
elif not lineL1 and not lineL2 and lineR2:
rotate_right(speed-10)
time.sleep(1)
# 10X1
elif lineL1 and not lineL2 and lineR2:
rotate_right(speed-10)
time.sleep(1)
# 1X01
elif lineL1 and not lineR1 and lineR2:
rotate_right(speed-10)
time.sleep(1)
# 0110
elif not lineL1 and lineL2 and lineR1 and not lineR2:
rotate_right(speed-10)
time.sleep(1)
# 0111
elif not lineL1 and lineL2 and lineR1 and lineR2:
rotate_right(speed-20)
time.sleep(1)
# 1110
elif lineL1 and lineL2 and lineR1 and not lineR2:
rotate_left(speed-20)
time.sleep(1)
# 1111
elif lineL1 and lineL2 and lineR1 and lineR2:
move_forward(speed)

# 等待一段时间再进行下一次检测 Wait for a while before the next test
time.sleep(0.01)

except KeyboardInterrupt:
# 当用户中断程序时,确保所有电机停止 Ensure that all motors stop when the user interrupts the program
stop_robot()
print("Ending")
stop_robot()

清理资源 Cleaning up resources

del bot现在我的这个代码,只能实现红外巡线,然后超声波避障,遇见障碍物后,蜂鸣器报警,之后就停下来了。但是他无法实现避开障碍物继续行驶,现在我想要实现避开障碍物继续行驶,请你帮我修改代码,实现这个功能,给我修正后的完整代码!!!

Suy nghĩ

Considering code adjustments for obstacle avoidance

The user wants to modify robot car code to incorporate obstacle avoidance while line tracking with infrared sensors. It looks like they've already dealt with some compilation issues. Although their code includes line-following actions, it doesn’t yet have ultrasonic or buzzer functionality. I’ll need to figure out how to integrate those, possibly using functions from a product library like Yahboom Raspbot V2.

Modifying code for obstacle avoidance and line following

I see a variable bot, likely defining the movement and actions of the robot. For obstacle avoidance, I’ll need to check the ultrasonic distance in the main loop. If it’s below a threshold, the robot should stop, back up, turn, and return to line following. I’ll implement a function to check for available ultrasonic methods and provide a fallback.

Handling buzzer and path setup

For the buzzer, I'll check if the method names like beep or Ctrl_beep are available. I'll also update the path to /project_demo/lib or try /home/pi/project_demo/lib if the path is wrong. I'll incorporate the obstacle avoidance logic and ensure that the necessary functions (rotate_right, move_forward, etc.) from the library are included. Additionally, I’ll set ultrasonic switch at the start if it’s available.

Implementing obstacle avoidance in loop

I’ll put the obstacle detection inside the while True loop to constantly check if it's too close, and if so, the robot will stop, beep, and perform the avoidance maneuver. To keep it simple, I'll start with backing up and turning left, then right, before resuming line following. The avoidance logic will continue cycling until the robot is clear.

Implementing obstacle avoidance and line reacquisition

For the avoidance routine, I'll have the robot back up, rotate, and then re-acquire the line after avoiding the obstacle with some zig-zag tracking. I'll adjust the parameters to ensure the robot can reacquire the line correctly.

I’ll also make sure it handles obstacles better by using a continue instead of break. I'll provide the full code with necessary adjustments, including handling KeyboardInterrupt safely, and will explain it in Chinese as requested.

Refining obstacle avoidance and line following logic

I’m constructing the code to avoid obstacles and follow the line. The obstacle avoidance function stops the robot, beeps, backs up slightly, and turns to find the path again. After that, the robot performs the line-following logic. I’m also ensuring some parameters are configurable for flexibility.

Providing full adjusted code and setup instructions

I’ll create the full script with added comments, making sure the user can easily tweak paths and function names. I’ll ensure the ultrasonic sensor methods, like get_ultrasonic_cm(), are flexible by adding candidate names to check. I'll also include some explanations in Chinese, as requested, and provide clear guidance on making adjustments.

Explaining obstacle avoidance and ultrasonic integration

Since the user’s code likely stops after encountering an obstacle, we need to modify the logic to detect obstacles, bypass them, and continue the loop. I'll provide two versions of the code: one using common ultrasonic method names and another where the user can plug in their existing method. I'll also suggest checking the bot's available methods with dir(bot).

Thought for 2m 6s

Trả lời

你现在之所以“遇到障碍物报警后就停住不再走”,本质上是避障逻辑执行完没有回到巡线循环(或者避障里直接 stop/break 了)。下面我给你一份完整可用的“巡线 + 避障绕开后继续巡线”代码:遇到障碍物 → 停车蜂鸣 → 后退 → 左绕 → 前进通过 → 右回正 → 继续跑,并且加了“重新找线”的小搜索过程。

说明:你们这套 Yahboom 库里,超声波/蜂鸣器函数名可能有差异。我在代码里做了“自动尝试常见函数名”的兼容;如果你们的函数名不同,只需要改 get_ultrasonic_cm()beep() 里那一行即可(我也在注释里标了)。


python
import sys import time import os # 兼容两种常见 demo 路径(你之前路径经常会不一致) for p in ("/project_demo/lib", "/home/pi/project_demo/lib"): if os.path.isdir(p) and p not in sys.path: sys.path.append(p) # 导入麦克纳姆小车驱动库 from McLumk_Wheel_Sports import * # ===================== 可调参数(建议先用默认) ===================== SPEED_FWD = 25 # 正常巡线速度 SPEED_TURN = 25 # 转向速度 SPEED_SLOW = 18 # 慢速(找线/后退用) OBSTACLE_CM = 20 # 障碍物阈值:小于该距离触发避障(cm) BACK_TIME = 0.35 # 后退时长(秒) TURN_TIME = 0.42 # 原地转向时长(秒) PASS_TIME = 0.75 # 绕行直行时长(秒) BEEP_TIME = 0.15 # 蜂鸣时长(秒) # ================================================================ def _try_call(obj, names, *args): """尝试调用 obj 的多个可能方法名,成功就返回结果;都不行返回 None""" for n in names: fn = getattr(obj, n, None) if callable(fn): try: return fn(*args) except TypeError: # 有些函数签名不一样就略过 continue except Exception: continue return None def beep(duration=BEEP_TIME): """ 蜂鸣器:不同镜像/库函数名可能不同,这里尽量自动适配。 如果你们知道准确函数名,直接在这里改成一行最稳。 """ if "bot" not in globals(): return # 常见:on/off 风格 if _try_call(bot, ["Ctrl_Beep", "Ctrl_beep", "Ctrl_buzzer", "buzzer", "beep"], 1) is not None: time.sleep(duration) _try_call(bot, ["Ctrl_Beep", "Ctrl_beep", "Ctrl_buzzer", "buzzer", "beep"], 0) return # 常见:传毫秒 _try_call(bot, ["beep_ms", "Beep"], int(duration * 1000)) def get_ultrasonic_cm(): """ 读取超声波距离(cm)。 你们当前“能避障并报警”的那份代码里,肯定有一行获取距离的函数; 如果这里读不到(返回 None),把下面 _try_call(...) 里的名字替换成你们实际的那个即可。 """ if "bot" not in globals(): return None val = _try_call( bot, [ "get_ultrasonic_distance", "get_distance", "ultrasonic_distance", "Ultrasonic_read", "read_ultrasonic", "Ultrasonic_cm", "GetUltrasonicDistance", "get_ultrasonic" ] ) if val is None: return None try: dist = float(val) # 有的库返回 mm,这里做个粗略兼容 if dist > 300: dist = dist / 10.0 return dist except Exception: return None def read_line_bits(): """ 从I2C读取巡线传感器数据,并解析成 4 个探头状态 """ track_data = bot.read_data_array(0x0a, 1) track = int(track_data[0]) x1 = (track >> 3) & 0x01 x2 = (track >> 2) & 0x01 x3 = (track >> 1) & 0x01 x4 = track & 0x01 # 按你原代码映射: # X2 X1 X3 X4 -> L1 L2 R1 R2 lineL1 = x2 lineL2 = x1 lineR1 = x3 lineR2 = x4 return lineL1, lineL2, lineR1, lineR2 def follow_line_once(speed=SPEED_FWD): """ 单次巡线控制(不在这里写长 sleep,否则反应会很慢) """ lineL1, lineL2, lineR1, lineR2 = read_line_bits() # 0000:全丢线,原代码是右转找线 if not lineL1 and not lineL2 and not lineR1 and not lineR2: rotate_right(speed) # 1X00:偏左(按你原逻辑) elif lineL1 and not lineR1 and not lineR2: rotate_left(max(speed - 10, 10)) # 00X1:偏右 elif (not lineL1) and (not lineL2) and lineR2: rotate_right(max(speed - 10, 10)) # 10X1 / 1X01 / 0110 / 0111:你原逻辑都偏向右转纠正 elif (lineL1 and (not lineL2) and lineR2) or (lineL1 and (not lineR1) and lineR2) \ or ((not lineL1) and lineL2 and lineR1 and (not lineR2)) \ or ((not lineL1) and lineL2 and lineR1 and lineR2): rotate_right(max(speed - 15, 8)) # 1110:偏左纠正 elif lineL1 and lineL2 and lineR1 and (not lineR2): rotate_left(max(speed - 20, 8)) # 1111:正中,前进 elif lineL1 and lineL2 and lineR1 and lineR2: move_forward(speed) else: # 兜底:前进 move_forward(speed) def move_backward_safe(speed=SPEED_SLOW): """ 有的库叫 move_backward,有的叫 move_back,这里做兼容 """ if "move_backward" in globals(): move_backward(speed) elif "move_back" in globals(): move_back(speed) else: # 实在没有就停一下 stop_robot() def reacquire_line(timeout_s=4.0): """ 绕障后重新找线:慢速前进 + 轻微左右摆动,直到任一探头检测到线 """ t0 = time.time() i = 0 while time.time() - t0 < timeout_s: bits = read_line_bits() if any(bits): return True move_forward(SPEED_SLOW) time.sleep(0.05) # 每隔一小段做一下“摆动”帮助找线 i += 1 if i % 12 == 6: rotate_left(SPEED_SLOW) time.sleep(0.08) elif i % 12 == 0: rotate_right(SPEED_SLOW) time.sleep(0.08) return False def avoid_obstacle(): """ 避障动作:停车->蜂鸣->后退->左绕->前进->右回->前进->找线->继续巡线 """ stop_robot() beep() # 1) 后退离开障碍物 move_backward_safe(SPEED_SLOW) time.sleep(BACK_TIME) stop_robot() time.sleep(0.05) # 2) 左转绕开 rotate_left(SPEED_TURN) time.sleep(TURN_TIME) move_forward(SPEED_FWD) time.sleep(PASS_TIME) # 3) 右转回正 rotate_right(SPEED_TURN) time.sleep(TURN_TIME) move_forward(SPEED_FWD) time.sleep(PASS_TIME) stop_robot() time.sleep(0.05) # 4) 重新找线(找不到就继续慢慢找一会儿) reacquire_line(timeout_s=4.0) # ================================ 主循环 ================================ # 有些镜像需要先打开超声波测距功能;你之前截图里出现过 Ctrl_Ulratist_switch _try_call(bot, ["Ctrl_Ulratist_switch", "Ctrl_Ultrasound_switch", "Ultrasonic_switch"], 1) try: while True: dist = get_ultrasonic_cm() # 有距离值且小于阈值 -> 避障绕开,然后继续 while(继续巡线) if dist is not None and 0 < dist < OBSTACLE_CM: avoid_obstacle() continue # 正常巡线 follow_line_once(SPEED_FWD) time.sleep(0.01) except KeyboardInterrupt: print("Ending") finally: _try_call(bot, ["Ctrl_Ulratist_switch", "Ctrl_Ultrasound_switch", "Ultrasonic_switch"], 0) stop_robot() try: del bot except Exception: pass # =======================================================================

你跑起来后如果仍然“绕一下又停住”

通常是这两个参数不合适(不同车体/地面差别很大):

  • OBSTACLE_CM:太大/太小都会影响行为(一般 15~25cm 调)
  • TURN_TIME / PASS_TIME:绕行幅度不够会“绕不开”,过大又会偏离太远找不到线

如果你愿意,把你们“超声波测距那一行代码(获取距离的那行)”贴出来,我可以把 get_ultrasonic_cm() 改成完全匹配你们镜像的写法,这样就不会因为函数名差异导致 dist 读不到。

Câu hỏi

import sys
import time

sys.path.append('/home/pi/project_demo/lib')

导入麦克纳姆小车驱动库 Import Mecanum Car Driver Library

from McLumk_Wheel_Sports import *

speed = 25#25

try:
while True:
# 从I2C读取巡线传感器数据 Read line sensor data from I2C
track_data = bot.read_data_array(0x0a, 1)
track = int(track_data[0])

# 解析巡线传感器的状态 Analyze the status of the line patrol sensor
x1 = (track >> 3) & 0x01
x2 = (track >> 2) & 0x01
x3 = (track >> 1) & 0x01
x4 = track & 0x01
"""
X2 X1 X3 X4
| | | |
L1 L2 R1 R2
"""
lineL1 = x2
lineL2 = x1
lineR1 = x3
lineR2 = x4

# 0000
if not lineL1 and not lineL2 and not lineR1 and not lineR2:
rotate_right(speed)
time.sleep(1)
# 1X00
elif lineL1 and not lineR1 and not lineR2:
rotate_left(speed-10)
time.sleep(1)
# 00X1
elif not lineL1 and not lineL2 and lineR2:
rotate_right(speed-10)
time.sleep(1)
# 10X1
elif lineL1 and not lineL2 and lineR2:
rotate_right(speed-10)
time.sleep(1)
# 1X01
elif lineL1 and not lineR1 and lineR2:
rotate_right(speed-10)
time.sleep(1)
# 0110
elif not lineL1 and lineL2 and lineR1 and not lineR2:
rotate_right(speed-10)
time.sleep(1)
# 0111
elif not lineL1 and lineL2 and lineR1 and lineR2:
rotate_right(speed-20)
time.sleep(1)
# 1110
elif lineL1 and lineL2 and lineR1 and not lineR2:
rotate_left(speed-20)
time.sleep(1)
# 1111
elif lineL1 and lineL2 and lineR1 and lineR2:
move_forward(speed)

# 等待一段时间再进行下一次检测 Wait for a while before the next test
time.sleep(0.01)

except KeyboardInterrupt:
# 当用户中断程序时,确保所有电机停止 Ensure that all motors stop when the user interrupts the program
stop_robot()
print("Ending")
stop_robot()

清理资源 Cleaning up resources

del bot现在我的这个代码,只能实现红外巡线,然后超声波避障,遇见障碍物后,蜂鸣器报警,之后就停下来了。但是他无法实现避开障碍物继续行驶,现在我想要实现避开障碍物继续行驶,请你帮我修改代码,实现这个功能,给我修正后的完整代码!!!现在我的这个代码,只能实现红外巡线,然后超声波避障,遇见障碍物后,蜂鸣器报警,之后就停下来了。但是他无法实现避开障碍物继续行驶,现在我想要实现避开障碍物继续行驶,请你帮我修改代码,实现这个功能,给我修正后的完整代码!!!现在我的这个代码,只能实现红外巡线,然后超声波避障,遇见障碍物后,蜂鸣器报警,之后就停下来了。但是他无法实现避开障碍物继续行驶,现在我想要实现避开障碍物继续行驶,请你帮我修改代码,实现这个功能,给我修正后的完整代码!!!

Suy nghĩ

Providing corrected code with path and ultrasonic integration

The user needs corrected code to avoid obstacles and continue moving. They’re using the McLumk_Wheel_Sports library, but their code lacks ultrasonic or buzzer readings. I’ll provide full code that integrates ultrasonic detection, avoidance, and returns the robot to line-following. I’ll ensure correct paths and include proper function calls without unnecessary steps. Without mentioning “wait,” I’ll ensure robustness in the code provided.

Improving line-following and integrating ultrasonic detection

The user has a time.sleep(1) in their line-following code, causing delays. We’ll reduce it. For ultrasonic detection, I'll try common function names and placeholders for reading, and ask the user to replace if needed. I'll include obstacle avoidance logic, beeping, backing up, turning, and reacquiring the line. We'll ensure bot is instantiated from the library.

Thought for 17s

Trả lời

下面给你一份“红外巡线 + 超声波检测到障碍物就绕开,然后自动回到巡线继续走”的完整代码(可直接替换你当前 Notebook 里的代码运行)。

它的逻辑是:

  • 正常情况下:一直按红外 4 路巡线行驶(用很短的 sleep,反应更快)
  • 一旦超声波距离 < 阈值:停车→蜂鸣→后退→左绕→前进通过→右回正→找线→继续巡线
  • 找线过程:短时间左右摆动 + 慢速前进,直到重新检测到线

说明:Yahboom 不同镜像/库里,超声波距离蜂鸣器的函数名可能不一样。代码里做了“自动尝试常见函数名”的兼容;如果你跑起来发现 dist 一直是 None(或者蜂鸣器不响),只需要按注释把那一行换成你们库里真实函数名即可。


python
import sys import time import os # ====== 1) 路径兼容:你之前经常是 /project_demo,而不是 /home/pi/project_demo ====== for p in ("/project_demo/lib", "/home/pi/project_demo/lib"): if os.path.isdir(p) and p not in sys.path: sys.path.append(p) # 导入麦克纳姆小车驱动库 from McLumk_Wheel_Sports import * # ===================== 可调参数(先用默认,跑通后再微调) ===================== SPEED_FWD = 25 # 正常巡线速度 SPEED_TURN = 25 # 转向速度 SPEED_SLOW = 18 # 慢速(找线/后退用) OBSTACLE_CM = 20 # 障碍物阈值:小于该距离触发避障(cm) BACK_TIME = 0.35 # 后退时长(秒) TURN_TIME = 0.42 # 原地转向时长(秒) PASS_TIME = 0.75 # 绕行直行时长(秒) BEEP_TIME = 0.15 # 蜂鸣时长(秒) LOOP_DT = 0.01 # 主循环周期 # ============================================================================ def _try_call(obj, names, *args): """尝试调用 obj 的多个可能方法名,成功就返回结果;都不行返回 None""" for n in names: fn = getattr(obj, n, None) if callable(fn): try: return fn(*args) except Exception: pass return None def beep(duration=BEEP_TIME): """ 蜂鸣器:自动尝试常见函数名 如果你知道你们准确蜂鸣器接口,建议直接替换成那一行最稳。 """ if "bot" not in globals(): return # 常见开关风格:1/0 ok = _try_call(bot, ["Ctrl_Beep", "Ctrl_beep", "Ctrl_buzzer", "Ctrl_Buzzer", "buzzer", "beep"], 1) if ok is not None: time.sleep(duration) _try_call(bot, ["Ctrl_Beep", "Ctrl_beep", "Ctrl_buzzer", "Ctrl_Buzzer", "buzzer", "beep"], 0) return # 另一类:传毫秒 _try_call(bot, ["beep_ms", "Beep"], int(duration * 1000)) def get_ultrasonic_cm(): """ 读取超声波距离(cm) 若你们库里有明确函数名(例如 bot.Ultrasonic_read()), 把下面 names 列表里加上/改成那个即可。 """ if "bot" not in globals(): return None val = _try_call( bot, [ "get_ultrasonic_distance", "get_distance", "ultrasonic_distance", "Ultrasonic_read", "read_ultrasonic", "Ultrasonic_cm", "GetUltrasonicDistance", "get_ultrasonic" ] ) if val is None: return None try: dist = float(val) # 有的库返回 mm,这里做粗略兼容 if dist > 300: dist = dist / 10.0 return dist except Exception: return None def read_line_bits(): """从I2C读取巡线传感器数据,并解析 4 个探头状态""" track_data = bot.read_data_array(0x0a, 1) track = int(track_data[0]) x1 = (track >> 3) & 0x01 x2 = (track >> 2) & 0x01 x3 = (track >> 1) & 0x01 x4 = track & 0x01 # 你原始映射: # X2 X1 X3 X4 -> L1 L2 R1 R2 lineL1 = x2 lineL2 = x1 lineR1 = x3 lineR2 = x4 return lineL1, lineL2, lineR1, lineR2 def follow_line_step(speed=SPEED_FWD): """ 单次巡线控制(不要像你原来那样每次 sleep(1),否则反应会很慢) """ lineL1, lineL2, lineR1, lineR2 = read_line_bits() # 0000:丢线 -> 轻微右转找线 if not lineL1 and not lineL2 and not lineR1 and not lineR2: rotate_right(speed) # 1X00:偏左 -> 左转纠正 elif lineL1 and (not lineR1) and (not lineR2): rotate_left(max(speed - 10, 10)) # 00X1:偏右 -> 右转纠正 elif (not lineL1) and (not lineL2) and lineR2: rotate_right(max(speed - 10, 10)) # 10X1 / 1X01 / 0110 / 0111:按你原逻辑偏向右纠正 elif (lineL1 and (not lineL2) and lineR2) or (lineL1 and (not lineR1) and lineR2) \ or ((not lineL1) and lineL2 and lineR1 and (not lineR2)) \ or ((not lineL1) and lineL2 and lineR1 and lineR2): rotate_right(max(speed - 15, 8)) # 1110:偏左纠正 elif lineL1 and lineL2 and lineR1 and (not lineR2): rotate_left(max(speed - 20, 8)) # 1111:在线上 -> 前进 elif lineL1 and lineL2 and lineR1 and lineR2: move_forward(speed) else: move_forward(speed) def move_backward_safe(speed=SPEED_SLOW): """兼容不同库的后退函数名""" if "move_backward" in globals(): move_backward(speed) elif "move_back" in globals(): move_back(speed) else: stop_robot() def reacquire_line(timeout_s=4.0): """绕障后重新找线:慢速前进 + 左右摆动,直到任一探头检测到线""" t0 = time.time() i = 0 while time.time() - t0 < timeout_s: bits = read_line_bits() if any(bits): return True move_forward(SPEED_SLOW) time.sleep(0.05) i += 1 if i % 12 == 6: rotate_left(SPEED_SLOW) time.sleep(0.08) elif i % 12 == 0: rotate_right(SPEED_SLOW) time.sleep(0.08) return False def avoid_obstacle(): """ 避障动作(绕开后继续巡线): 停车->蜂鸣->后退->左绕->前进->右回正->前进->找线->继续 """ stop_robot() beep() # 1) 后退离开障碍物 move_backward_safe(SPEED_SLOW) time.sleep(BACK_TIME) stop_robot() time.sleep(0.05) # 2) 左转绕开 rotate_left(SPEED_TURN) time.sleep(TURN_TIME) move_forward(SPEED_FWD) time.sleep(PASS_TIME) # 3) 右转回正 rotate_right(SPEED_TURN) time.sleep(TURN_TIME) move_forward(SPEED_FWD) time.sleep(PASS_TIME) stop_robot() time.sleep(0.05) # 4) 重新找线(找不到也不会卡死,超时返回) reacquire_line(timeout_s=4.0) # ================================ 主循环 ================================ # 有些镜像需要先打开超声波测距功能(你之前截图里出现过 Ctrl_Ulratist_switch) _try_call(bot, ["Ctrl_Ulratist_switch", "Ctrl_Ultrasound_switch", "Ultrasonic_switch"], 1) try: while True: dist = get_ultrasonic_cm() # 检测到障碍物 -> 绕开后继续 while(继续巡线) if dist is not None and 0 < dist < OBSTACLE_CM: avoid_obstacle() continue # 正常巡线 follow_line_step(SPEED_FWD) time.sleep(LOOP_DT) except KeyboardInterrupt: print("Ending") finally: _try_call(bot, ["Ctrl_Ulratist_switch", "Ctrl_Ultrasound_switch", "Ultrasonic_switch"], 0) stop_robot() try: del bot except Exception: pass # =======================================================================

如果你跑起来“仍然绕不开/绕开后找不到线”

你只需要优先调这 3 个参数(很关键):

  • OBSTACLE_CM:一般 15~25cm 之间试(太大容易频繁触发;太小会撞上)
  • TURN_TIME:绕不开就 增大(比如 0.42 → 0.50)
  • PASS_TIME:绕过障碍需要更远就 增大(比如 0.75 → 1.00)

另外,如果你发现 dist 一直是 None(避障从不触发),告诉我你们库里“读取超声波距离”的那一行到底叫什么(或把你们避障那段代码截图/贴出来),我就把 get_ultrasonic_cm() 精确改成你们那套镜像的函数名,保证触发。

Chia sẻ Q&A này