일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 라즈베리파이
- 미국주식
- 엔비디아
- 빅데이터분석기사
- 주식
- RS-485
- Apple
- 애플
- raspberry pi
- Python
- MQTT
- 힐스테이트 광교산
- 퀄컴
- homebridge
- 나스닥
- ConnectedHomeIP
- 국내주식
- 해외주식
- 매터
- Espressif
- Bestin
- 파이썬
- 월패드
- 배당
- matter
- cluster
- esp32
- Home Assistant
- 공모주
- 홈네트워크
- Today
- Total
YOGYUI
EtherCAT Driver ROS2 Stack SDO Async exchange service - ioctl magic difference 문제 해결 방법 본문
EtherCAT Driver ROS2 Stack SDO Async exchange service - ioctl magic difference 문제 해결 방법
요겨 2023. 9. 18. 13:00
EtherCAT Driver ROS2 Stack SDO Async exchange service - ioctl magic difference issue
ROS2 중급 개발자 이상을 대상으로 작성된 글 (workspace, colcon 등 기초적인 내용은 다루지 않음)
1. 문제 상황
회사에서 자체적으로 만든 EtherCAT 모터 드라이버 기반 6축 다관절 로봇 제어 솔루션 구현을 위해 ROS2(Humble) / ros2_control / IgH EtherCAT Master(EtherLAB)를 설치한 뒤 ICube-Robotics의 EtherCAT Driver ROS2 Stack 패키지를 사용하고 있다
document page: https://icube-robotics.github.io/ethercat_driver_ros2
github repository: https://github.com/ICube-Robotics/ethercat_driver_ros2
PDO 통신은 다양한 통신 주기 (1ms, 2ms, 4ms, 10ms)에서 문제없이 동작해 로봇 제어가 잘 되는데, SDO 통신을 위해 ethercat_manager 패키지의 ethercat_sdo_src_server 서비스 호출 시 다음과 같이 ioctl() 매직넘버 미스매치 문제가 발생했다
[ERROR] [...] [ethercat_manager]: ioctl() version magic is differing: /dev/EtherCAT0: 32, ethercat tool: 31
Ubuntu 22.04.03 LTS에 Real-time을 위한 PREEMPT_RT 커널 5.15.113-rt64 버전을 패치해서 사용중인데, 이를 기반으로 빌드한 IgH EtherCAT Master (1.5 stable) 바이너리의 ioctl 매직버전은 32라 미스매치가 발생한 것 같다
※ 커널 버전때문인지, IgH 소스코드 문제인지는 좀 더 파봐야 할 듯?.. 문제 해결책이 워낙에 간단하다보니 문제 발생 근본 원인에 대해서는 깊게 생각하고 싶지가 않다 ㅎㅎ
※ ROS 버전 문제인 것으로 파악 완료! 나도 모르게 Iron 버전을 활성화한게 문제였다 -_- Humble 버전에서는 magic 넘버가 31이어야 한다
2. 문제 해결
EtherCAT Driver ROS2 의 ethercat_manager 소스코드를 좀 까보니 금방 해결책을 찾을 수 있었다
ethercat_driver_ros2/ethercat_manager/include/ethercat_manager/ec_master_async_io.hpp 파일을 열어보면 매크로 상수 EC_IOCTL_VERSION_MAGIC가 31로 하드코딩된 것을 알 수 있다
#define EC_IOCTL_TYPE 0xa4
#define EC_IO(nr) _IO(EC_IOCTL_TYPE, nr)
#define EC_IOR(nr, type) _IOR(EC_IOCTL_TYPE, nr, type)
#define EC_IOW(nr, type) _IOW(EC_IOCTL_TYPE, nr, type)
#define EC_IOWR(nr, type) _IOWR(EC_IOCTL_TYPE, nr, type)
#define EC_IOCTL_VERSION_MAGIC 31
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
#define EC_IOCTL_SLAVE_SDO_UPLOAD EC_IOWR(0x0e, ec_ioctl_slave_sdo_upload_t)
#define EC_IOCTL_SLAVE_SDO_DOWNLOAD EC_IOWR(0x0f, ec_ioctl_slave_sdo_download_t)
같은 경로 내에 있는 ec_master_async.hpp 파일의 EcMasterAsync 클래스 내부 코드를 보면 오류가 발생하는 구문을 확인할 수 있다
class EcMasterAsync
{
/* ... */
void open(Permissions perm)
{
/* ... */
getModule(&module_data);
if (module_data.ioctl_version_magic != EC_IOCTL_VERSION_MAGIC) {
std::stringstream err;
err << "ioctl() version magic is differing: "
<< deviceName.str() << ": " << module_data.ioctl_version_magic
<< ", ethercat tool: " << EC_IOCTL_VERSION_MAGIC;
throw MasterException(err.str());
}
mcount_ = module_data.master_count;
}
/* ... */
};
손쉽게 해결하기 위해 EC_IOCTL_VERSION_MAGIC 값을 바꾼 뒤 colcon으로 다시 빌드해주자
// #define EC_IOCTL_VERSION_MAGIC 31
#define EC_IOCTL_VERSION_MAGIC 32
$ colcon build --packages-select ethercat_manager
빌드 후 asyclic SDO exchange 서비스를 실행해준다 (여기서는 간단히 read 기능만 데모)
서비스/인터페이스 명세는 아래와 같다
$ ros2 run ethercat_manager ethercat_sdo_srv_server
서비스 호출 시 SDO Read하려면 ethercat_manager/get_sdo를, Write하려면 ethercat_manager/set_sdo를 호출하면 되며, 인터페이스는 ROS2 사용하듯이 dictionary 형태로 입력해주면 된다
3. DEMO
특정 slave의 원하는 object 값을 읽어보자
로봇 손목에 장착한 ATI사의 force-torque 센서 Axia80의 vendor ID와 product code를 SDO 통신으로 읽어와보자 (ethercat_sdo_srv_server 서비스 서버가 구동중이어야 한다)
$ ros2 service call /ethercat_manager/get_sdo ethercat_msgs/srv/GetSdo\
"{\
master_id: 0,\
slave_position: 6,\
sdo_index: 0x2019,\
sdo_subindex: 0x01,\
sdo_data_type: uint32\
}"
requester: making request: ethercat_msgs.srv.GetSdo_Request(master_id=0, slave_position=6, sub_index=8217, sdo_subindex=1, sdo_data_type='uitn32')
response:
ethercat_msgs.srv.GetSdo_Response(success=True, sdo_return_message='SDO upload done succesfully', sdo_return_value_string='0x00000732', sdo_return_value=1842.0)
$ ros2 service call /ethercat_manager/get_sdo ethercat_msgs/srv/GetSdo\
"{\
master_id: 0,\
slave_position: 6,\
sdo_index: 0x2019,\
sdo_subindex: 0x02,\
sdo_data_type: uint32\
}"
requester: making request: ethercat_msgs.srv.GetSdo_Request(master_id=0, slave_position=6, sub_index=8217, sdo_subindex=2, sdo_data_type='uitn32')
response:
ethercat_msgs.srv.GetSdo_Response(success=True, sdo_return_message='SDO upload done succesfully', sdo_return_value_string='0x26483053', sdo_return_value=642265171.0)
response를 보면 vendor ID는 0x00000732, product code는 0x26483053으로 제대로 읽히는 것을 알 수 있다
끝~!
'Software > ROS' 카테고리의 다른 글
IgH EtherCAT Master SDO 음수값 입력하기 (0) | 2024.07.26 |
---|---|
ROS2 - Multiple Robots 환경을 위한 Namespace 설정 방법 (10) | 2024.07.23 |
ROS2 EtherCAT Beckhoff Digital I/O Slave 구동 예제 (2) | 2023.11.10 |
ROS2 + IgH EtherCAT Master 구동 환경 구축 (0) | 2023.11.10 |
EtherCAT Master 환경 구축 - Ubuntu 22.04 LTS + PREEMPT_RT 커널 패치 (2) | 2023.11.01 |