跳转至

底层通信

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适配器等)