From 7fc660c798fdd9ba1acec45494de63583fc031ab Mon Sep 17 00:00:00 2001 From: cxh Date: Thu, 12 Jun 2025 14:41:07 +0800 Subject: [PATCH] Auto commit at 2025-06-12 14:41:07 --- src/mc/CMakeLists.txt | 13 ++++ src/mc/include/mc/controlcan.h | 104 ++++++++++++++++++++++++++++++ src/mc/lib/libcontrolcan.a | Bin 0 -> 59294 bytes src/mc/lib/libcontrolcan.so | Bin 0 -> 89152 bytes src/mc/src/can_driver.cpp | 92 +++++++++++++------------- src/radio_ctrl/src/radio_ctrl.cpp | 5 +- 6 files changed, 166 insertions(+), 48 deletions(-) create mode 100755 src/mc/include/mc/controlcan.h create mode 100755 src/mc/lib/libcontrolcan.a create mode 100755 src/mc/lib/libcontrolcan.so diff --git a/src/mc/CMakeLists.txt b/src/mc/CMakeLists.txt index ed4d78f..07a65e1 100644 --- a/src/mc/CMakeLists.txt +++ b/src/mc/CMakeLists.txt @@ -5,6 +5,8 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() +link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib) + # Find dependencies find_package(sweeper_interfaces REQUIRED) find_package(ament_cmake REQUIRED) @@ -19,6 +21,8 @@ add_executable(mc_node ${SRC_FILES}) ament_target_dependencies(mc_node rclcpp std_msgs sweeper_interfaces) +target_link_libraries(mc_node controlcan pthread) + # Set include directories for the target target_include_directories( mc_node @@ -31,6 +35,15 @@ target_compile_features(mc_node PUBLIC c_std_99 cxx_std_17) install(TARGETS mc_node DESTINATION lib/${PROJECT_NAME}) install(DIRECTORY config DESTINATION share/${PROJECT_NAME}) +set(LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lib) + +# 安装libcontrolcan动态库(.so) +install( + FILES + ${LIB_DIR}/libcontrolcan.so + DESTINATION lib +) + # Handle testing if needed if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) diff --git a/src/mc/include/mc/controlcan.h b/src/mc/include/mc/controlcan.h new file mode 100755 index 0000000..93bc5cc --- /dev/null +++ b/src/mc/include/mc/controlcan.h @@ -0,0 +1,104 @@ +#ifndef CONTROLCAN_H +#define CONTROLCAN_H + +////文件版本:v2.02 20190609 +//接口卡类型定义 + +#define VCI_USBCAN1 3 +#define VCI_USBCAN2 4 +#define VCI_USBCAN2A 4 + +#define VCI_USBCAN_E_U 20 +#define VCI_USBCAN_2E_U 21 + +//函数调用返回状态值 +#define STATUS_OK 1 +#define STATUS_ERR 0 + +#define USHORT unsigned short int +#define BYTE unsigned char +#define CHAR char +#define UCHAR unsigned char +#define UINT unsigned int +#define DWORD unsigned int +#define PVOID void* +#define ULONG unsigned int +#define INT int +#define UINT32 UINT +#define LPVOID void* +#define BOOL BYTE +#define TRUE 1 +#define FALSE 0 + +//1.ZLGCAN系列接口卡信息的数据类型。 +typedef struct _VCI_BOARD_INFO{ + USHORT hw_Version; + USHORT fw_Version; + USHORT dr_Version; + USHORT in_Version; + USHORT irq_Num; + BYTE can_Num; + CHAR str_Serial_Num[20]; + CHAR str_hw_Type[40]; + USHORT Reserved[4]; +} VCI_BOARD_INFO,*PVCI_BOARD_INFO; + +//2.定义CAN信息帧的数据类型。 +typedef struct _VCI_CAN_OBJ{ + UINT ID; + UINT TimeStamp; + BYTE TimeFlag; + BYTE SendType; + BYTE RemoteFlag;//是否是远程帧 + BYTE ExternFlag;//是否是扩展帧 + BYTE DataLen; + BYTE Data[8]; + BYTE Reserved[3]; +}VCI_CAN_OBJ,*PVCI_CAN_OBJ; + +//3.定义初始化CAN的数据类型 +typedef struct _INIT_CONFIG{ + DWORD AccCode; + DWORD AccMask; + DWORD Reserved; + UCHAR Filter; + UCHAR Timing0; + UCHAR Timing1; + UCHAR Mode; +}VCI_INIT_CONFIG,*PVCI_INIT_CONFIG; + +///////// new add struct for filter ///////// +typedef struct _VCI_FILTER_RECORD{ + DWORD ExtFrame; //是否为扩展帧 + DWORD Start; + DWORD End; +}VCI_FILTER_RECORD,*PVCI_FILTER_RECORD; + +#ifdef __cplusplus +#define EXTERN_C extern "C" +#else +#define EXTERN_C +#endif + +EXTERN_C DWORD VCI_OpenDevice(DWORD DeviceType,DWORD DeviceInd,DWORD Reserved); +EXTERN_C DWORD VCI_CloseDevice(DWORD DeviceType,DWORD DeviceInd); +EXTERN_C DWORD VCI_InitCAN(DWORD DeviceType, DWORD DeviceInd, DWORD CANInd, PVCI_INIT_CONFIG pInitConfig); + +EXTERN_C DWORD VCI_ReadBoardInfo(DWORD DeviceType,DWORD DeviceInd,PVCI_BOARD_INFO pInfo); + +EXTERN_C DWORD VCI_SetReference(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,DWORD RefType,PVOID pData); + +EXTERN_C ULONG VCI_GetReceiveNum(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd); +EXTERN_C DWORD VCI_ClearBuffer(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd); + +EXTERN_C DWORD VCI_StartCAN(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd); +EXTERN_C DWORD VCI_ResetCAN(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd); + +EXTERN_C ULONG VCI_Transmit(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_OBJ pSend,UINT Len); +EXTERN_C ULONG VCI_Receive(DWORD DeviceType,DWORD DeviceInd,DWORD CANInd,PVCI_CAN_OBJ pReceive,UINT Len,INT WaitTime); + +EXTERN_C DWORD VCI_UsbDeviceReset(DWORD DevType,DWORD DevIndex,DWORD Reserved); +EXTERN_C DWORD VCI_FindUsbDevice2(PVCI_BOARD_INFO pInfo); + +#endif + diff --git a/src/mc/lib/libcontrolcan.a b/src/mc/lib/libcontrolcan.a new file mode 100755 index 0000000000000000000000000000000000000000..bb8aee08d7440672544349650eb883ca471610b5 GIT binary patch literal 59294 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 OkMr_FP3~CfU>MCf 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 E0br9G=Kufz literal 0 HcmV?d00001 diff --git a/src/mc/src/can_driver.cpp b/src/mc/src/can_driver.cpp index 3af1f9f..d6d4ffb 100644 --- a/src/mc/src/can_driver.cpp +++ b/src/mc/src/can_driver.cpp @@ -9,6 +9,11 @@ #include #include #include +#include "mc/controlcan.h" + +DWORD deviceType = VCI_USBCAN2; // 或 VCI_USBCAN_2E_U 等 +DWORD deviceIndex = 0; // 通常为 0(第一个设备) +DWORD channelIndex = 0; // 通道号:0 表示 CAN1,1 表示 CAN2 CANDriver::CANDriver() = default; @@ -22,39 +27,39 @@ bool CANDriver::open(const std::string &interface) if (running) return false; - sockfd = socket(PF_CAN, SOCK_RAW, CAN_RAW); - if (sockfd < 0) + // 参数可解析 interface 设定 channelIndex,例如 interface="can0" => channelIndex=0 + deviceType = VCI_USBCAN2; + deviceIndex = 0; + channelIndex = (interface == "can1") ? 1 : 0; + + if (VCI_OpenDevice(deviceType, deviceIndex, 0) != STATUS_OK) { - perror("socket"); + std::cerr << "VCI_OpenDevice failed" << std::endl; return false; } - struct ifreq ifr; - std::strncpy(ifr.ifr_name, interface.c_str(), IFNAMSIZ - 1); - ifr.ifr_name[IFNAMSIZ - 1] = '\0'; + VCI_INIT_CONFIG config{}; + config.AccCode = 0; + config.AccMask = 0xFFFFFFFF; + config.Filter = 0; // 接收所有 + config.Timing0 = 0x00; // 500Kbps 示例(需查文档确认 Timing) + config.Timing1 = 0x1C; + config.Mode = 0; // 正常模式 - if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0) + if (VCI_InitCAN(deviceType, deviceIndex, channelIndex, &config) != STATUS_OK) { - perror("ioctl"); - ::close(sockfd); + std::cerr << "VCI_InitCAN failed" << std::endl; + VCI_CloseDevice(deviceType, deviceIndex); return false; } - struct sockaddr_can addr{}; - addr.can_family = AF_CAN; - addr.can_ifindex = ifr.ifr_ifindex; - - if (bind(sockfd, reinterpret_cast(&addr), sizeof(addr)) < 0) + if (VCI_StartCAN(deviceType, deviceIndex, channelIndex) != STATUS_OK) { - perror("bind"); - ::close(sockfd); + std::cerr << "VCI_StartCAN failed" << std::endl; + VCI_CloseDevice(deviceType, deviceIndex); return false; } - // 设置为非阻塞 - int flags = fcntl(sockfd, F_GETFL, 0); - fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); - running = true; receiveThread = std::thread(&CANDriver::receiveThreadFunc, this); return true; @@ -69,11 +74,8 @@ void CANDriver::close() if (receiveThread.joinable()) receiveThread.join(); - if (sockfd >= 0) - { - ::close(sockfd); - sockfd = -1; - } + VCI_ResetCAN(deviceType, deviceIndex, channelIndex); + VCI_CloseDevice(deviceType, deviceIndex); } bool CANDriver::sendFrame(const CANFrame &frame) @@ -81,18 +83,17 @@ bool CANDriver::sendFrame(const CANFrame &frame) if (!running) return false; - struct can_frame raw_frame{}; - raw_frame.can_id = frame.id; - if (frame.ext) - raw_frame.can_id |= CAN_EFF_FLAG; - if (frame.rtr) - raw_frame.can_id |= CAN_RTR_FLAG; - raw_frame.can_dlc = frame.dlc; - std::memcpy(raw_frame.data, frame.data, frame.dlc); + VCI_CAN_OBJ obj{}; + obj.ID = frame.id; + obj.RemoteFlag = frame.rtr ? 1 : 0; + obj.ExternFlag = frame.ext ? 1 : 0; + obj.SendType = 0; // 普通发送 + obj.DataLen = frame.dlc; + std::memcpy(obj.Data, frame.data, frame.dlc); - if (write(sockfd, &raw_frame, sizeof(raw_frame)) != sizeof(raw_frame)) + if (VCI_Transmit(deviceType, deviceIndex, channelIndex, &obj, 1) != 1) { - perror("write"); + std::cerr << "VCI_Transmit failed" << std::endl; return false; } @@ -149,25 +150,24 @@ bool CANDriver::applyFilters() void CANDriver::receiveThreadFunc() { - struct can_frame raw_frame; while (running) { - ssize_t nbytes = read(sockfd, &raw_frame, sizeof(raw_frame)); - if (nbytes < 0) + VCI_CAN_OBJ rec[100]; + ULONG len = VCI_Receive(deviceType, deviceIndex, channelIndex, rec, 100, 10); + if (len == 0) { - if (errno != EAGAIN) - perror("read"); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); continue; } - if (nbytes == sizeof(raw_frame) && callback) + for (ULONG i = 0; i < len && callback; ++i) { CANFrame frame; - frame.id = raw_frame.can_id & CAN_EFF_MASK; - frame.ext = static_cast(raw_frame.can_id & CAN_EFF_FLAG); - frame.rtr = static_cast(raw_frame.can_id & CAN_RTR_FLAG); - frame.dlc = raw_frame.can_dlc; - std::memcpy(frame.data, raw_frame.data, raw_frame.can_dlc); + frame.id = rec[i].ID; + frame.ext = rec[i].ExternFlag != 0; + frame.rtr = rec[i].RemoteFlag != 0; + frame.dlc = rec[i].DataLen; + std::memcpy(frame.data, rec[i].Data, frame.dlc); callback(frame, userData); } } diff --git a/src/radio_ctrl/src/radio_ctrl.cpp b/src/radio_ctrl/src/radio_ctrl.cpp index c3017d7..367b302 100644 --- a/src/radio_ctrl/src/radio_ctrl.cpp +++ b/src/radio_ctrl/src/radio_ctrl.cpp @@ -8,7 +8,8 @@ namespace sweeperMsg = sweeper_interfaces::msg; -constexpr float EPS_GEAR_RATIO = 16.5f; +constexpr float DEG_PER_SEC_TO_RPM = 1.0f / 6.0f; +constexpr float GEAR_RATIO = 7.0f; constexpr float DELTA_T = 0.02f; // 20ms const uint16_t speed[3] = {192, 992, 1792}; @@ -128,7 +129,7 @@ private: float angle_speed = fabs(target_angle - current_feedback_angle) / DELTA_T; // 电机转速(单位:rpm) - float motor_rpm = angle_speed * EPS_GEAR_RATIO; + float motor_rpm = angle_speed * DEG_PER_SEC_TO_RPM * GEAR_RATIO; // 限制电机转速到 [120, 1500] 范围,防止过小/过大 uint16_t can_speed = std::clamp(