底层通信¶
can_utils 模块¶
模块概述¶
can_utils 模块提供CAN接口的通用工具函数,包括接口检测、启用、验证等功能。所有函数均设计为在Linux系统下运行,依赖标准的ip命令和can-utils工具包。
功能概览¶
can_utils
├── CAN接口检测
│ ├── get_available_can_interfaces() # 获取已启用接口
│ ├── get_all_can_interfaces() # 获取所有接口
│ ├── check_can_interface_type() # 检查接口类型(真实/虚拟)
│ └── verify_can_interface() # 验证接口状态
├── CAN接口配置
│ ├── enable_can_interface() # 启用单个接口
│ ├── disable_can_interface() # 禁用单个接口
│ ├── enable_all_can_interfaces() # 启用所有接口
│ └── disable_all_can_interfaces() # 禁用所有接口
└── CAN通道配对
└── pair_can_channels() # 双臂CAN通道配对
CAN接口检测函数¶
get_available_can_interfaces¶
get_available_can_interfaces(log=None) -> List[str]
自动检测系统中所有可用且已启用的CAN接口。
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
log |
callable |
None |
日志函数 |
返回值: List[str]
- 可用的CAN接口列表,例如
['can0', 'can1']
from openarmx_arm_driver._lib.can_utils import get_available_can_interfaces
# 获取所有可用CAN接口
can_interfaces = get_available_can_interfaces()
print(f"可用CAN接口: {can_interfaces}")
说明:
- 依赖Linux
ip命令 - 只返回状态为UP的接口
- 检测失败返回空列表
get_all_can_interfaces¶
get_all_can_interfaces(log=None) -> List[str]
检测系统中所有的CAN接口(包括未启用的)。
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
log |
callable |
None |
日志函数 |
返回值: List[str]
- 所有CAN接口列表,例如
['can0', 'can1', 'can2']
from openarmx_arm_driver._lib.can_utils import get_all_can_interfaces
all_interfaces = get_all_can_interfaces()
print(f"所有CAN接口: {all_interfaces}")
check_can_interface_type¶
check_can_interface_type(interface, log=None) -> bool
检查CAN接口类型,判断是否为虚拟接口。
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
interface |
str |
- | CAN接口名称,如 'can0' |
log |
callable |
None |
日志函数 |
返回值: bool
True表示真实硬件接口False表示虚拟接口(vcan)
from openarmx_arm_driver._lib.can_utils import check_can_interface_type
is_real = check_can_interface_type('can0')
print(f"can0 是真实接口: {is_real}")
verify_can_interface¶
verify_can_interface(interface, log=None) -> bool
验证CAN接口是否已成功启用。
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
interface |
str |
- | CAN接口名称,如 'can0' |
log |
callable |
None |
日志函数 |
返回值: bool
True表示接口已启用(UP状态)False表示未启用或不存在
from openarmx_arm_driver._lib.can_utils import verify_can_interface
if verify_can_interface('can0'):
print("can0 已启用")
else:
print("can0 未启用")
CAN接口配置函数¶
enable_can_interface¶
enable_can_interface(interface, bitrate=1000000, loopback=False, verbose=True, log=None, password=None) -> bool
启用单个CAN接口。
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
interface |
str |
- | CAN接口名称,如 'can0' |
bitrate |
int |
1000000 |
波特率(1Mbps) |
loopback |
bool |
False |
是否启用loopback模式 |
verbose |
bool |
True |
是否显示详细信息 |
log |
callable |
None |
日志函数 |
password |
str |
None |
sudo密码,用于自动输入密码 |
返回值: bool
True表示启用成功False表示启用失败
from openarmx_arm_driver._lib.can_utils import enable_can_interface
# 手动输入密码
success = enable_can_interface('can0', bitrate=1000000)
# 自动输入密码
success = enable_can_interface('can0', bitrate=1000000, password='your_password')
if success:
print("CAN接口启用成功")
注意: "权限要求"
此函数需要sudo权限。如果提供 password 参数,将自动输入密码;否则需要手动输入
disable_can_interface¶
disable_can_interface(interface, verbose=True, log=None, password=None) -> bool
禁用单个CAN接口。
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
interface |
str |
- | CAN接口名称,如 'can0' |
verbose |
bool |
True |
是否显示详细信息 |
log |
callable |
None |
日志函数 |
password |
str |
None |
sudo密码,用于自动输入密码 |
返回值: bool
True表示禁用成功False表示禁用失败
from openarmx_arm_driver._lib.can_utils import disable_can_interface
# 手动输入密码
disable_can_interface('can0')
# 自动输入密码
disable_can_interface('can0', password='your_password')
enable_all_can_interfaces¶
enable_all_can_interfaces(bitrate=1000000, loopback=False, verbose=True, log=None, password=None) -> Dict[str, bool]
启用所有检测到的CAN接口(批量操作)。
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
bitrate |
int |
1000000 |
波特率(1Mbps) |
loopback |
bool |
False |
是否启用loopback模式 |
verbose |
bool |
True |
是否显示详细信息 |
log |
callable |
None |
日志函数 |
password |
str |
None |
sudo密码,用于自动输入密码 |
返回值: Dict[str, bool]
- 每个接口的启用结果
from openarmx_arm_driver._lib.can_utils import enable_all_can_interfaces
# 手动输入密码
results = enable_all_can_interfaces()
# 自动输入密码
results = enable_all_can_interfaces(password='your_password')
for iface, success in results.items():
print(f"{iface}: {'成功' if success else '失败'}")
disable_all_can_interfaces¶
disable_all_can_interfaces(verbose=True, log=None, password=None) -> Dict[str, bool]
禁用所有检测到的CAN接口(批量操作)。
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
verbose |
bool |
True |
是否显示详细信息 |
log |
callable |
None |
日志函数 |
password |
str |
None |
sudo密码,用于自动输入密码 |
返回值: Dict[str, bool]
- 每个接口的禁用结果
from openarmx_arm_driver._lib.can_utils import disable_all_can_interfaces
# 手动输入密码
results = disable_all_can_interfaces()
# 自动输入密码
results = disable_all_can_interfaces(password='your_password')
CAN通道配对函数¶
pair_can_channels¶
pair_can_channels(available_channels) -> List[Tuple[str, str]]
将可用的CAN通道按固定规则配对为双臂机器人。
配对规则: 偶数通道(右臂) - 奇数通道(左臂)
can0(右) -can1(左)can2(右) -can3(左)can4(右) -can5(左)- ...
| 参数名 | 类型 | 说明 |
|---|---|---|
available_channels |
List[str] |
可用的CAN通道列表,如 ['can0', 'can1'] |
返回值: List[Tuple[str, str]]
- 有效的配对组列表,格式:
[(right_arm, left_arm), ...]
from openarmx_arm_driver._lib.can_utils import pair_can_channels, get_available_can_interfaces
# 获取可用接口
available = get_available_can_interfaces()
print(f"可用接口: {available}")
# 配对为双臂
pairs = pair_can_channels(available)
for right, left in pairs:
print(f"右臂: {right}, 左臂: {left}")
# 输出示例:
# ✓ Found valid pair: right_arm can0 - left_arm can1
# ✓ Found valid pair: right_arm can2 - left_arm can3
注意: "配对说明"
- 只有当一组中的两个通道都可用时,才保留该组
- 如果只有单个通道可用(如只有can0没有can1),会给出提示但不包含在返回结果中
- 适用于自动检测并初始化多组双臂机器人
使用场景示例:
from openarmx_arm_driver import Robot
from openarmx_arm_driver._lib.can_utils import pair_can_channels, get_available_can_interfaces
# 自动检测并创建多个双臂机器人
available = get_available_can_interfaces()
pairs = pair_can_channels(available)
robots = []
for right_channel, left_channel in pairs:
robot = Robot(right_can_channel=right_channel, left_can_channel=left_channel)
robots.append(robot)
print(f"创建机器人: 右臂={right_channel}, 左臂={left_channel}")
print(f"共创建 {len(robots)} 个双臂机器人")
函数速查表¶
| 函数 | 功能 | 返回类型 | 需要sudo |
|---|---|---|---|
get_available_can_interfaces() |
获取已启用接口 | List[str] |
否 |
get_all_can_interfaces() |
获取所有接口 | List[str] |
否 |
check_can_interface_type() |
检查接口类型 | bool |
否 |
verify_can_interface() |
验证接口状态 | bool |
否 |
enable_can_interface() |
启用单个接口 | bool |
是 |
disable_can_interface() |
禁用单个接口 | bool |
是 |
enable_all_can_interfaces() |
启用所有接口 | Dict[str, bool] |
是 |
disable_all_can_interfaces() |
禁用所有接口 | Dict[str, bool] |
是 |
pair_can_channels() |
CAN通道配对 | List[Tuple] |
否 |
使用示例¶
系统初始化¶
from openarmx_arm_driver._lib.can_utils import (
get_available_can_interfaces,
enable_all_can_interfaces,
verify_can_interface
)
def initialize_can_system():
"""初始化CAN系统"""
# 1. 检查现有接口
available = get_available_can_interfaces()
print(f"已启用接口: {available if available else '无'}")
# 2. 启用所有接口
results = enable_all_can_interfaces(bitrate=1000000)
# 3. 验证结果
if all(results.values()):
print("所有接口启用成功")
else:
failed = [iface for iface, success in results.items() if not success]
print(f"部分接口启用失败: {failed}")
安全清理¶
import atexit
from openarmx_arm_driver._lib.can_utils import disable_all_can_interfaces
@atexit.register
def safe_shutdown():
"""程序退出时安全关闭所有CAN接口"""
disable_all_can_interfaces(verbose=True)
故障排除¶
权限问题¶
# 错误: Permission denied
# 解决方案1: 使用sudo
sudo python your_script.py
# 解决方案2: 添加用户到dialout组
sudo usermod -a -G dialout $USER
# 重新登录生效
接口不存在¶
# 检查CAN驱动
lsmod | grep can
# 查看内核日志
dmesg | grep -i can
# 加载CAN驱动
sudo modprobe can_raw
系统要求¶
软件依赖¶
# Ubuntu/Debian
sudo apt-get install can-utils iproute2
# 验证安装
ip link help
candump -h
硬件要求¶
- Linux操作系统(推荐Ubuntu 18.04+)
- CAN接口硬件(PCIe CAN卡、USB CAN适配器等)