Skip to content

Low-Level Communication

can_utils Module

Module Overview

The can_utils module provides general CAN interface utilities, including detection, enable/disable, verification, and bimanual channel pairing. Functions are designed for Linux systems and rely on the ip command and can-utils.

Feature Map

can_utils
├── CAN detection
│   ├── get_available_can_interfaces()
│   ├── get_all_can_interfaces()
│   ├── check_can_interface_type()
│   └── verify_can_interface()
├── CAN configuration
│   ├── enable_can_interface()
│   ├── disable_can_interface()
│   ├── enable_all_can_interfaces()
│   └── disable_all_can_interfaces()
└── CAN pairing
    └── pair_can_channels()

CAN Detection Functions

get_available_can_interfaces

get_available_can_interfaces(log=None) -> List[str]

Detects enabled and usable CAN interfaces.

  • Returns: e.g. ['can0', 'can1']
  • Notes: only interfaces in UP state are returned

get_all_can_interfaces

get_all_can_interfaces(log=None) -> List[str]

Detects all CAN interfaces including disabled ones.

check_can_interface_type

check_can_interface_type(interface, log=None) -> bool

Checks whether an interface is physical CAN (True) or virtual CAN/vcan (False).

verify_can_interface

verify_can_interface(interface, log=None) -> bool

Verifies whether the interface is successfully enabled.


CAN Configuration Functions

enable_can_interface

enable_can_interface(interface, bitrate=1000000, loopback=False, verbose=True, log=None, password=None) -> bool

Enables a single CAN interface.

  • bitrate: default 1 Mbps
  • password: optional sudo password for automatic privilege handling

disable_can_interface

disable_can_interface(interface, verbose=True, log=None, password=None) -> bool

Disables a single CAN interface.

enable_all_can_interfaces

enable_all_can_interfaces(bitrate=1000000, loopback=False, verbose=True, log=None, password=None) -> Dict[str, bool]

Batch-enables all detected CAN interfaces.

disable_all_can_interfaces

disable_all_can_interfaces(verbose=True, log=None, password=None) -> Dict[str, bool]

Batch-disables all detected CAN interfaces.


CAN Pairing Function

pair_can_channels

pair_can_channels(interfaces=None, require_even_pairs=True, log=None) -> List[Dict[str, str]]

Pairs available CAN channels for bimanual setups.

Example output:

✓ Found valid pair: right_arm can0 - left_arm can1
✓ Found valid pair: right_arm can2 - left_arm can3

Quick Function Table

Function Return Type Purpose
get_available_can_interfaces List[str] Enabled interfaces
get_all_can_interfaces List[str] All interfaces
check_can_interface_type bool Physical/virtual check
verify_can_interface bool Interface status check
enable_can_interface bool Enable one interface
disable_can_interface bool Disable one interface
enable_all_can_interfaces Dict[str, bool] Batch enable
disable_all_can_interfaces Dict[str, bool] Batch disable
pair_can_channels List[Dict[str, str]] Bimanual channel pairing

Usage Example

System initialization

from openarmx_arm_driver._lib.can_utils import (
    get_all_can_interfaces,
    enable_all_can_interfaces,
    pair_can_channels,
)

interfaces = get_all_can_interfaces()
print("CAN interfaces:", interfaces)

enable_results = enable_all_can_interfaces()
print("Enable results:", enable_results)

pairs = pair_can_channels()
print("Detected pairs:", pairs)

Safe cleanup

from openarmx_arm_driver._lib.can_utils import disable_all_can_interfaces

disable_all_can_interfaces()

Troubleshooting

Permission issue

Symptom: Permission denied

Solutions:

  1. Run with sudo
  2. Add current user to dialout group:
sudo usermod -aG dialout $USER

Log out and log back in for group changes to take effect.

Interface not found

ip link show | grep can
sudo modprobe can
sudo modprobe can_raw
sudo modprobe can_dev
dmesg | grep -i can

System Requirements

Software dependencies

sudo apt update
sudo apt install -y can-utils iproute2

Hardware requirements

  • Linux host with CAN support
  • Proper CAN adapter and driver
  • Correct wiring and termination for CAN bus

Complete Source Appendix (Chinese)

The full original Chinese content is included below to ensure no sections are missing in the English edition.

底层通信

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