├── .gitignore ├── ethercat_driver_ros2_examples.repos ├── ethercat_driver_ros2_examples ├── CMakeLists.txt └── package.xml ├── ethercat_force_sensor ├── config │ ├── easycat_config │ │ ├── ForceSensor.bin │ │ ├── ForceSensor.prj │ │ ├── log_configuration.txt │ │ ├── ForceSensor.h │ │ ├── ForceSensor.ino │ │ └── ForceSensor.xml │ ├── controllers.yaml │ └── slave_config.yaml ├── description │ ├── config │ │ └── force_sensor.config.xacro │ └── ros2_control │ │ └── force_sensor.ros2_control.xacro ├── CMakeLists.txt ├── package.xml ├── launch │ └── force_sensor.launch.py └── README.md ├── ethercat_slave_description ├── CMakeLists.txt ├── config │ ├── omron │ │ ├── omron_nx_ecc201_nx_od5256.yaml │ │ └── omron_nx_ecc201_nx_id5442.yaml │ ├── beckhoff │ │ ├── beckhoff_el4132.yaml │ │ ├── beckhoff_el2124.yaml │ │ ├── beckhoff_el4134.yaml │ │ ├── beckhoff_el3102.yaml │ │ ├── beckhoff_el1008.yaml │ │ ├── beckhoff_el1018.yaml │ │ ├── beckhoff_el2008.yaml │ │ ├── beckhoff_el2088.yaml │ │ ├── beckhoff_el5101.yaml │ │ └── beckhoff_el3104.yaml │ ├── schneider │ │ └── schneider_atv320.yaml │ ├── advantech │ │ ├── advantech_amax5051.yaml │ │ └── advantech_amax5056.yaml │ ├── ati │ │ └── ati_ftsensor.yaml │ ├── elmo │ │ └── elmo_gold.yaml │ ├── maxon │ │ └── maxon_epos3.yaml │ ├── technosoft │ │ └── technosoft_ipos3604.yaml │ └── synapticon │ │ └── synapticon_somanet_circulo9.yaml ├── package.xml └── README.md ├── ethercat_motor_drive ├── description │ ├── config │ │ └── motor_drive.config.xacro │ └── ros2_control │ │ └── motor_drive.ros2_control.xacro ├── CMakeLists.txt ├── package.xml ├── config │ ├── controllers.yaml │ ├── maxon_epos3_config.yaml │ └── maxon_epos4_50_5_config.yaml ├── README.md └── launch │ └── motor_drive.launch.py ├── .docker ├── README.md └── Dockerfile ├── .github ├── dependabot.yml └── workflows │ ├── ci-format.yml │ └── ci.yml ├── README.md ├── CONTRIBUTING.md ├── .pre-commit-config.yaml └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | install/ 3 | log/ 4 | .vscode/ 5 | -------------------------------------------------------------------------------- /ethercat_driver_ros2_examples.repos: -------------------------------------------------------------------------------- 1 | repositories: 2 | ethercat_driver_ros2: 3 | type: git 4 | url: https://github.com/ICube-Robotics/ethercat_driver_ros2.git 5 | version: main 6 | -------------------------------------------------------------------------------- /ethercat_driver_ros2_examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(ethercat_driver_ros2_examples NONE) 3 | find_package(ament_cmake REQUIRED) 4 | ament_package() 5 | -------------------------------------------------------------------------------- /ethercat_force_sensor/config/easycat_config/ForceSensor.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICube-Robotics/ethercat_driver_ros2_examples/HEAD/ethercat_force_sensor/config/easycat_config/ForceSensor.bin -------------------------------------------------------------------------------- /ethercat_force_sensor/config/controllers.yaml: -------------------------------------------------------------------------------- 1 | controller_manager: 2 | ros__parameters: 3 | update_rate: 100 # Hz 4 | 5 | joint_state_broadcaster: 6 | type: joint_state_broadcaster/JointStateBroadcaster 7 | -------------------------------------------------------------------------------- /ethercat_force_sensor/config/easycat_config/ForceSensor.prj: -------------------------------------------------------------------------------- 1 | ForceSensor 2 | OUTPUTS_TAG 3 | INPUTS_TAG 4 | force_0 5 | int16_t 6 | force_1 7 | int16_t 8 | INFO_TAG 9 | 0x0000079A 10 | AB&T 11 | 0xDEADBEEF 12 | 0x00000001 13 | ForceSensor 14 | END_TAG 15 | -------------------------------------------------------------------------------- /ethercat_slave_description/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(ethercat_slave_description) 3 | find_package(ament_cmake REQUIRED) 4 | 5 | install( 6 | DIRECTORY config 7 | DESTINATION share/${PROJECT_NAME} 8 | ) 9 | 10 | ament_package() 11 | -------------------------------------------------------------------------------- /ethercat_motor_drive/description/config/motor_drive.config.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /ethercat_force_sensor/description/config/force_sensor.config.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.docker/README.md: -------------------------------------------------------------------------------- 1 | # EtherCAT Driver ROS2 Docker Containers 2 | Provides a basic preconfigured docker container for development purposes. To use it, make sure you have [Docker](https://docs.docker.com/get-docker/) installed, then build and run the image : 3 | 4 | ```shell 5 | $ docker build --tag ethercat_driver:humble --file .docker/Dockerfile . 6 | $ docker run -it --privileged --network=host ethercat_driver:humble 7 | ``` 8 | -------------------------------------------------------------------------------- /ethercat_force_sensor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(ethercat_force_sensor) 3 | find_package(ament_cmake REQUIRED) 4 | find_package(rclcpp REQUIRED) 5 | find_package(ethercat_driver REQUIRED) 6 | find_package(ethercat_interface REQUIRED) 7 | find_package(ethercat_generic_slave REQUIRED) 8 | 9 | install( 10 | DIRECTORY config description launch 11 | DESTINATION share/${PROJECT_NAME} 12 | ) 13 | 14 | ament_package() 15 | -------------------------------------------------------------------------------- /ethercat_force_sensor/config/slave_config.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for EasyCAT based ForceSensor Slave 2 | vendor_id: 0x0000079a 3 | product_id: 0xdeadbeef 4 | tpdo: # TxPDO 5 | - index: 0x1a00 6 | channels: 7 | - {index: 0x0006, sub_index: 1, type: int16, state_interface: force.0} 8 | - {index: 0x0006, sub_index: 2, type: int16, state_interface: force.1} 9 | sm: # Sync Manager 10 | - {index: 0, type: input, pdo: tpdo, watchdog: disable} 11 | -------------------------------------------------------------------------------- /ethercat_motor_drive/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(ethercat_motor_drive) 3 | find_package(ament_cmake REQUIRED) 4 | find_package(rclcpp REQUIRED) 5 | find_package(ethercat_driver REQUIRED) 6 | find_package(ethercat_interface REQUIRED) 7 | find_package(ethercat_generic_cia402_drive REQUIRED) 8 | 9 | install( 10 | DIRECTORY config description launch 11 | DESTINATION share/${PROJECT_NAME} 12 | ) 13 | 14 | ament_package() 15 | -------------------------------------------------------------------------------- /.docker/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG ROS_DISTRO="humble" 2 | FROM ros:${ROS_DISTRO} 3 | 4 | COPY . /ros2_dev/ethercat_driver_ros2_examples 5 | 6 | RUN apt update && \ 7 | apt install autoconf libtool -y 8 | RUN mkdir ec_dev && cd ec_dev && \ 9 | git clone https://gitlab.com/etherlab.org/ethercat.git && \ 10 | cd ethercat && \ 11 | git checkout stable-1.5 && \ 12 | ./bootstrap && \ 13 | ./configure --prefix=/usr/local/etherlab --disable-kernel && \ 14 | make && make install 15 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/omron/omron_nx_ecc201_nx_od5256.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Omron NX ECC201 with id5442 2 | # Description : Omron EtherCAT Coupler NX_ECC201 with NX_OD5256 16-ch Digital Output module 3 | vendor_id: 0x00000083 4 | product_id: 0x00000083 5 | rpdo: #RxPDO = receive PDO Mapping (ROS control to slave, Master Out to Slave In -MOSI-) 6 | - index: 0x1604 7 | channels: 8 | - {index: 0x7022, sub_index: 0x01, type: uint16, command_interface: d_output} 9 | sm: # Sync Manager 10 | - {index: 2, type: output, pdo: rpdo, watchdog: disable} 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" 9 | # Workflow files stored in the 10 | # default location of `.github/workflows` 11 | directory: "/" 12 | schedule: 13 | interval: "weekly" 14 | -------------------------------------------------------------------------------- /.github/workflows/ci-format.yml: -------------------------------------------------------------------------------- 1 | # This is a format job. Pre-commit has a first-party GitHub action, so we use 2 | # that: https://github.com/pre-commit/action 3 | 4 | name: Format 5 | 6 | on: 7 | workflow_dispatch: 8 | pull_request: 9 | 10 | jobs: 11 | pre-commit: 12 | name: Format 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - uses: actions/setup-python@v5.1.0 17 | with: 18 | python-version: '3.10' 19 | - name: Install system hooks 20 | run: sudo apt install -qq clang-format-14 cppcheck 21 | - uses: pre-commit/action@v3.0.1 22 | with: 23 | extra_args: --all-files --hook-stage manual 24 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/beckhoff/beckhoff_el4132.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Beckhoff EL4132 2 | # Description : EtherCAT Terminal, 2-channel analog output, voltage, ±10 V, 16 bit. 3 | vendor_id: 0x00000002 4 | product_id: 0x10243052 5 | rpdo: # RxPDO = receive PDO Mapping (ROS control to slave, Master Out to Slave In -MOSI-) 6 | - index: 0x1600 7 | channels: 8 | - {index: 0x3001, sub_index: 0x01, type: int16, command_interface: analog_output.1, factor: 3276.7} 9 | - index: 0x1601 10 | channels: 11 | - {index: 0x3002, sub_index: 0x01, type: int16, command_interface: analog_output.2, factor: 3276.7} 12 | sm: # Sync Manager 13 | - {index: 2, type: output, pdo: rpdo, watchdog: enable} 14 | -------------------------------------------------------------------------------- /ethercat_driver_ros2_examples/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ethercat_driver_ros2_examples 5 | 0.0.1 6 | Meta-package aggregating the ethercat_driver_ros2_examples packages and documentation 7 | Maciej Bednarczyk 8 | Apache License 2.0 9 | 10 | ament_cmake 11 | ethercat_force_sensor 12 | 13 | 14 | ament_cmake 15 | 16 | 17 | -------------------------------------------------------------------------------- /ethercat_motor_drive/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ethercat_motor_drive 5 | 0.0.1 6 | Package with instructions for running an EtherCAT compatible motor drive and use it in ROS2 7 | Maciej Bednarczyk 8 | Apache License 2.0 9 | 10 | ament_cmake 11 | ethercat_driver 12 | ethercat_interface 13 | ethercat_generic_cia402_drive 14 | 15 | 16 | ament_cmake 17 | 18 | 19 | -------------------------------------------------------------------------------- /ethercat_force_sensor/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ethercat_force_sensor 5 | 0.0.1 6 | Package with instructions for building a custom Force Sensor EtherCAT slave using strain gauges and EasyCAT and use it in ROS2 7 | Maciej Bednarczyk 8 | Apache License 2.0 9 | 10 | ament_cmake 11 | ethercat_driver 12 | ethercat_interface 13 | ethercat_generic_slave 14 | 15 | 16 | ament_cmake 17 | 18 | 19 | -------------------------------------------------------------------------------- /ethercat_motor_drive/config/controllers.yaml: -------------------------------------------------------------------------------- 1 | controller_manager: 2 | ros__parameters: 3 | update_rate: 100 # Hz 4 | 5 | joint_state_broadcaster: 6 | type: joint_state_broadcaster/JointStateBroadcaster 7 | 8 | trajectory_controller: 9 | type: joint_trajectory_controller/JointTrajectoryController 10 | 11 | velocity_controller: 12 | type: velocity_controllers/JointGroupVelocityController 13 | 14 | effort_controller: 15 | type: effort_controllers/JointGroupEffortController 16 | 17 | trajectory_controller: 18 | ros__parameters: 19 | command_interfaces: 20 | - position 21 | state_interfaces: 22 | - position 23 | joints: 24 | - joint_1 25 | 26 | velocity_controller: 27 | ros__parameters: 28 | joints: 29 | - joint_1 30 | 31 | effort_controller: 32 | ros__parameters: 33 | joints: 34 | - joint_1 35 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/beckhoff/beckhoff_el2124.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Beckhoff EL2124 2 | # Description : EtherCAT Terminal, 4-channel digital output, 5 V DC, 20 mA. 3 | vendor_id: 0x00000002 4 | product_id: 0x084c3052 5 | rpdo: # RxPDO = receive PDO Mapping (ROS control to slave, Master Out to Slave In -MOSI-) 6 | - index: 0x1600 7 | channels: 8 | - {index: 0x7000, sub_index: 0x01, type: bool, mask: 1, command_interface: d_output.1} 9 | - index: 0x1601 10 | channels: 11 | - {index: 0x7010, sub_index: 0x01, type: bool, mask: 2, command_interface: d_output.2} 12 | - index: 0x1602 13 | channels: 14 | - {index: 0x7020, sub_index: 0x01, type: bool, mask: 4, command_interface: d_output.3} 15 | - index: 0x1603 16 | channels: 17 | - {index: 0x7030, sub_index: 0x01, type: bool, mask: 8, command_interface: d_output.4} 18 | sm: # Sync Manager 19 | - {index: 0, type: output, pdo: rpdo, watchdog: enable} 20 | -------------------------------------------------------------------------------- /ethercat_slave_description/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ethercat_slave_description 5 | 0.0.1 6 | Description package for EtherCAT slave modules 7 | Maciej Bednarczyk 8 | Apache-2.0 9 | 10 | ament_cmake 11 | 12 | ethercat_driver 13 | ethercat_interface 14 | ethercat_generic_slave 15 | ethercat_generic_cia402_drive 16 | 17 | ament_lint_auto 18 | ament_lint_common 19 | 20 | 21 | ament_cmake 22 | 23 | 24 | -------------------------------------------------------------------------------- /ethercat_force_sensor/description/ros2_control/force_sensor.ros2_control.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ethercat_driver/EthercatDriver 9 | 0 10 | 100 11 | 12 | 13 | 14 | 15 | 16 | 17 | ethercat_generic_plugins/GenericEcSlave 18 | 0 19 | 0 20 | $(find ethercat_force_sensor)/config/slave_config.yaml 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/beckhoff/beckhoff_el4134.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Beckhoff EL4134 2 | # Description : EtherCAT Terminal, 4-channel analog output, voltage, ±10 V, 16 bit. 3 | 4 | vendor_id: 0x00000002 5 | product_id: 0x10263052 6 | rpdo: # RxPDO = receive PDO Mapping (ROS control to slave, Master Out to Slave In -MOSI-) 7 | - index: 0x1600 8 | channels: 9 | - {index: 0x7000, sub_index: 0x01, type: int16, command_interface: analog_output.1, factor: 3276.7} 10 | - index: 0x1601 11 | channels: 12 | - {index: 0x7010, sub_index: 0x01, type: int16, command_interface: analog_output.2, factor: 3276.7} 13 | - index: 0x1602 14 | channels: 15 | - {index: 0x7020, sub_index: 0x01, type: int16, command_interface: analog_output.3, factor: 3276.7} 16 | - index: 0x1603 17 | channels: 18 | - {index: 0x7030, sub_index: 0x01, type: int16, command_interface: analog_output.4, factor: 3276.7} 19 | 20 | sm: # Sync Manager 21 | - {index: 2, type: output, pdo: rpdo, watchdog: enable} 22 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/beckhoff/beckhoff_el3102.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Beckhoff EL3102 2 | # Description : EtherCAT Terminal, 2-channel analog input, voltage, ±10 V, 16 bit, differential. 3 | vendor_id: 0x00000002 4 | product_id: 0x0c1e3052 5 | tpdo: # TxPDO = transmit PDO Mapping (slave to ROS control, Master In From Slave Out -MISO-) 6 | - index: 0x1a00 7 | channels: 8 | - {index: 0x3101, sub_index: 0x01, type: uint8} 9 | - {index: 0x3101, sub_index: 0x02, type: int16, state_interface: analog_input.1, factor: 0.000305185} 10 | - index: 0x1a01 11 | channels: 12 | - {index: 0x3102, sub_index: 0x01, type: uint8} 13 | - {index: 0x3102, sub_index: 0x02, type: int16, state_interface: analog_input.2, factor: 0.000305185} 14 | sm: # Sync Manager 15 | - {index: 0, type: output, pdo: ~, watchdog: disable} 16 | - {index: 1, type: input, pdo: ~, watchdog: disable} 17 | - {index: 2, type: output, pdo: ~, watchdog: disable} 18 | - {index: 3, type: input, pdo: tpdo, watchdog: disable} 19 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/schneider/schneider_atv320.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Schneider ATV320 drive 2 | # Description: Velocity Control only 3 | vendor_id: 0x0800005a 4 | product_id: 0x00000389 5 | assign_activate: 0x0300 # DC Synch register 6 | auto_fault_reset: false # true = automatic fault reset, false = fault reset on rising edge command interface "reset_fault" 7 | rpdo: # RxPDO = receive PDO Mapping (ROS control to motor drive, Master Out to Slave In -MOSI-) 8 | - index: 0x1600 9 | channels: 10 | - {index: 0x6040, sub_index: 0x00, type: uint16, default: 0} # Control word 11 | - {index: 0x6042, sub_index: 0x00, type: int16, command_interface: velocity, default: 0} # Target velocity 12 | tpdo: # TxPDO = transmit PDO Mapping (motor drive to ROS control, Master In From Slave Out -MISO-) 13 | - index: 0x1a00 14 | channels: 15 | - {index: 0x6041, sub_index: 0x00, type: uint16} # Status word 16 | - {index: 0x6044, sub_index: 0x00, type: int16, state_interface: velocity} # Velocity actual value 17 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/advantech/advantech_amax5051.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Advantech AMAX-5051 2 | # Description : 8-ch Digital Input EtherCAT Slice IO Module 3 | vendor_id: 0x000013FE 4 | product_id: 0x00035051 5 | tpdo: # TxPDO = transmit PDO Mapping (slave to ROS control, Master In From Slave Out -MISO-) 6 | - index: 0x1a00 7 | channels: 8 | - {index: 0x3001, sub_index: 0x01, type: bool, mask: 1, state_interface: d_input.1} 9 | - {index: 0x3001, sub_index: 0x02, type: bool, mask: 2, state_interface: d_input.2} 10 | - {index: 0x3001, sub_index: 0x03, type: bool, mask: 4, state_interface: d_input.3} 11 | - {index: 0x3001, sub_index: 0x04, type: bool, mask: 8, state_interface: d_input.4} 12 | - {index: 0x3001, sub_index: 0x05, type: bool, mask: 16, state_interface: d_input.5} 13 | - {index: 0x3001, sub_index: 0x06, type: bool, mask: 32, state_interface: d_input.6} 14 | - {index: 0x3001, sub_index: 0x07, type: bool, mask: 64, state_interface: d_input.7} 15 | - {index: 0x3001, sub_index: 0x08, type: bool, mask: 128, state_interface: d_input.8} 16 | sm: # Sync Manager 17 | - {index: 0, type: input, pdo: tpdo, watchdog: disable} 18 | -------------------------------------------------------------------------------- /ethercat_motor_drive/description/ros2_control/motor_drive.ros2_control.xacro: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ethercat_driver/EthercatDriver 9 | 0 10 | 100 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ethercat_generic_plugins/EcCiA402Drive 21 | 0 22 | 0 23 | 8 24 | $(find ethercat_motor_drive)/config/maxon_epos3_config.yaml 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/advantech/advantech_amax5056.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Advantech AMAX-5056 2 | # Description : 8-ch Sink-type Digital Output EtherCAT Slice IO Module 3 | vendor_id: 0x000013FE 4 | product_id: 0x00035056 5 | rpdo: # RxPDO = receive PDO Mapping (ROS control to slave, Master Out to Slave In -MOSI-) 6 | - index: 0x1600 7 | channels: 8 | - {index: 0x3101, sub_index: 0x01, type: bool, mask: 1, command_interface: d_output.1} 9 | - {index: 0x3101, sub_index: 0x02, type: bool, mask: 2, command_interface: d_output.2} 10 | - {index: 0x3101, sub_index: 0x03, type: bool, mask: 4, command_interface: d_output.3} 11 | - {index: 0x3101, sub_index: 0x04, type: bool, mask: 8, command_interface: d_output.4} 12 | - {index: 0x3101, sub_index: 0x05, type: bool, mask: 16, command_interface: d_output.5} 13 | - {index: 0x3101, sub_index: 0x06, type: bool, mask: 32, command_interface: d_output.6} 14 | - {index: 0x3101, sub_index: 0x07, type: bool, mask: 64, command_interface: d_output.7} 15 | - {index: 0x3101, sub_index: 0x08, type: bool, mask: 128, command_interface: d_output.8} 16 | sm: # Sync Manager 17 | - {index: 0, type: output, pdo: rpdo, watchdog: enable} 18 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/omron/omron_nx_ecc201_nx_id5442.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Omron NX ECC201 with id5442 2 | # Description : Omron EtherCAT Coupler NX_ECC201 with NX_ID5442 16-ch Digital Input module 3 | vendor_id: 0x00000083 4 | product_id: 0x00000083 5 | rpdo: #RxPDO = receive PDO Mapping (ROS control to slave, Master Out to Slave In -MOSI-) 6 | - index: 0x1604 7 | channels: 8 | - {index: 0x7022, sub_index: 0x01, type: uint16} 9 | tpdo: # TxPDO = transmit PDO Mapping (slave to ROS control, Master In From Slave Out -MISO-) 10 | - index: 0x1bf8 11 | channels: 12 | - {index: 0x3003, sub_index: 0x04, type: bit128} 13 | - {index: 0x3006, sub_index: 0x04, type: bit128} 14 | - index: 0x1bff 15 | channels: 16 | - {index: 0x2002, sub_index: 0x01, type: uint8} 17 | - index: 0x1bf4 18 | channels: 19 | - {index: 0x0000, sub_index: 0x00, type: bit8} 20 | - index: 0x1a00 21 | channels: 22 | - {index: 0x6002, sub_index: 0x01, type: uint16, state_interface: d_input} 23 | sm: # Sync Manager 24 | - {index: 0, type: output, pdo: ~, watchdog: disable} 25 | - {index: 1, type: input, pdo: ~, watchdog: disable} 26 | - {index: 2, type: output, pdo: rpdo, watchdog: disable} 27 | - {index: 3, type: input, pdo: tpdo, watchdog: disable} 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ethercat_driver_ros2_examples 2 | [![Licence](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 3 | [![Build](https://github.com/ICube-Robotics/ethercat_driver_ros2_examples/actions/workflows/ci.yml/badge.svg)](https://github.com/ICube-Robotics/ethercat_driver_ros2_examples/actions/workflows/ci.yml) 4 | 5 | Example repository for the [EtherCAT Driver ROS2 stack](https://github.com/ICube-Robotics/ethercat_driver_ros2). 6 | 7 | This repository contains the following example packages : 8 | - EtherCAT compatible CIA402 motor drive (example using Maxon EPOS3) 9 | - Custom Force Sensor EtherCAT slave using strain gauges and EasyCAT 10 | - Example configuration files for the some EtherCAT modules 11 | 12 | ## Contacts ## 13 | ![icube](https://icube.unistra.fr/fileadmin/templates/DUN/icube/images/logo.png) 14 | 15 | [ICube Laboratory](https://icube.unistra.fr), [University of Strasbourg](https://www.unistra.fr/), France 16 | 17 | __Manuel Yguel:__ [yguel@unistra.fr](mailto:yguel@unistra.fr), @github: [yguel](https://github.com/yguel) 18 | 19 | __Laurent Barbé:__ [laurent.barbe@unistra.fr](mailto:laurent.barbe@unistra.fr) 20 | 21 | __Philippe Zanne:__ [philippe.zanne@unistra.fr](mailto:philippe.zanne@unistra.fr) 22 | 23 | __Maciej Bednarczyk:__ [m.bednarczyk@unistra.fr](mailto:m.bednarczyk@unistra.fr), @github: [mcbed](https://github.com/mcbed) 24 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/beckhoff/beckhoff_el1008.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Beckhoff EL1008 2 | # Description : EtherCAT Terminal, 8-channel digital input, 24 V DC, 3 ms. 3 | vendor_id: 0x00000002 4 | product_id: 0x03f03052 5 | tpdo: # TxPDO = transmit PDO Mapping (slave to ROS control, Master In From Slave Out -MISO-) 6 | - index: 0x1a00 7 | channels: 8 | - {index: 0x6000, sub_index: 0x01, type: bool, mask: 1, state_interface: d_input.1} 9 | - index: 0x1a01 10 | channels: 11 | - {index: 0x6010, sub_index: 0x01, type: bool, mask: 2, state_interface: d_input.2} 12 | - index: 0x1a02 13 | channels: 14 | - {index: 0x6020, sub_index: 0x01, type: bool, mask: 4, state_interface: d_input.3} 15 | - index: 0x1a03 16 | channels: 17 | - {index: 0x6030, sub_index: 0x01, type: bool, mask: 8, state_interface: d_input.4} 18 | - index: 0x1a04 19 | channels: 20 | - {index: 0x6040, sub_index: 0x01, type: bool, mask: 16, state_interface: d_input.5} 21 | - index: 0x1a05 22 | channels: 23 | - {index: 0x6050, sub_index: 0x01, type: bool, mask: 32, state_interface: d_input.6} 24 | - index: 0x1a06 25 | channels: 26 | - {index: 0x6060, sub_index: 0x01, type: bool, mask: 64, state_interface: d_input.7} 27 | - index: 0x1a07 28 | channels: 29 | - {index: 0x6070, sub_index: 0x01, type: bool, mask: 128, state_interface: d_input.8} 30 | sm: # Sync Manager 31 | - {index: 0, type: input, pdo: tpdo, watchdog: disable} 32 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/beckhoff/beckhoff_el1018.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Beckhoff EL1018 2 | # Description : EtherCAT Terminal, 8-channel digital input, 24 V DC, 10 us. 3 | vendor_id: 0x00000002 4 | product_id: 0x03fa3052 5 | tpdo: # TxPDO = transmit PDO Mapping (slave to ROS control, Master In From Slave Out -MISO-) 6 | - index: 0x1a00 7 | channels: 8 | - {index: 0x6000, sub_index: 0x01, type: bool, mask: 1, state_interface: d_input.1} 9 | - index: 0x1a01 10 | channels: 11 | - {index: 0x6010, sub_index: 0x01, type: bool, mask: 2, state_interface: d_input.2} 12 | - index: 0x1a02 13 | channels: 14 | - {index: 0x6020, sub_index: 0x01, type: bool, mask: 4, state_interface: d_input.3} 15 | - index: 0x1a03 16 | channels: 17 | - {index: 0x6030, sub_index: 0x01, type: bool, mask: 8, state_interface: d_input.4} 18 | - index: 0x1a04 19 | channels: 20 | - {index: 0x6040, sub_index: 0x01, type: bool, mask: 16, state_interface: d_input.5} 21 | - index: 0x1a05 22 | channels: 23 | - {index: 0x6050, sub_index: 0x01, type: bool, mask: 32, state_interface: d_input.6} 24 | - index: 0x1a06 25 | channels: 26 | - {index: 0x6060, sub_index: 0x01, type: bool, mask: 64, state_interface: d_input.7} 27 | - index: 0x1a07 28 | channels: 29 | - {index: 0x6070, sub_index: 0x01, type: bool, mask: 128, state_interface: d_input.8} 30 | sm: # Sync Manager 31 | - {index: 0, type: input, pdo: tpdo, watchdog: disable} 32 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/beckhoff/beckhoff_el2008.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Beckhoff EL2008 2 | # Description : EtherCAT Terminal, 8-channel digital output, 24 V DC, 0.5 A. 3 | vendor_id: 0x00000002 4 | product_id: 0x07d83052 5 | rpdo: # RxPDO = receive PDO Mapping (ROS control to slave, Master Out to Slave In -MOSI-) 6 | - index: 0x1600 7 | channels: 8 | - {index: 0x7000, sub_index: 0x01, type: bool, mask: 1, command_interface: d_output.1} 9 | - index: 0x1601 10 | channels: 11 | - {index: 0x7010, sub_index: 0x01, type: bool, mask: 2, command_interface: d_output.2} 12 | - index: 0x1602 13 | channels: 14 | - {index: 0x7020, sub_index: 0x01, type: bool, mask: 4, command_interface: d_output.3} 15 | - index: 0x1603 16 | channels: 17 | - {index: 0x7030, sub_index: 0x01, type: bool, mask: 8, command_interface: d_output.4} 18 | - index: 0x1604 19 | channels: 20 | - {index: 0x7040, sub_index: 0x01, type: bool, mask: 16, command_interface: d_output.5} 21 | - index: 0x1605 22 | channels: 23 | - {index: 0x7050, sub_index: 0x01, type: bool, mask: 32, command_interface: d_output.6} 24 | - index: 0x1606 25 | channels: 26 | - {index: 0x7060, sub_index: 0x01, type: bool, mask: 64, command_interface: d_output.7} 27 | - index: 0x1607 28 | channels: 29 | - {index: 0x7070, sub_index: 0x01, type: bool, mask: 128, command_interface: d_output.8} 30 | sm: # Sync Manager 31 | - {index: 0, type: output, pdo: rpdo, watchdog: enable} 32 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/beckhoff/beckhoff_el2088.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Beckhoff EL2088 2 | # Description : EtherCAT Terminal, 8-channel digital output, 24 V DC, 0.5 A, ground switching. 3 | vendor_id: 0x00000002 4 | product_id: 0x08283052 5 | rpdo: # RxPDO = receive PDO Mapping (ROS control to slave, Master Out to Slave In -MOSI-) 6 | - index: 0x1600 7 | channels: 8 | - {index: 0x7000, sub_index: 0x01, type: bool, mask: 1, command_interface: d_output.1} 9 | - index: 0x1601 10 | channels: 11 | - {index: 0x7010, sub_index: 0x01, type: bool, mask: 2, command_interface: d_output.2} 12 | - index: 0x1602 13 | channels: 14 | - {index: 0x7020, sub_index: 0x01, type: bool, mask: 4, command_interface: d_output.3} 15 | - index: 0x1603 16 | channels: 17 | - {index: 0x7030, sub_index: 0x01, type: bool, mask: 8, command_interface: d_output.4} 18 | - index: 0x1604 19 | channels: 20 | - {index: 0x7040, sub_index: 0x01, type: bool, mask: 16, command_interface: d_output.5} 21 | - index: 0x1605 22 | channels: 23 | - {index: 0x7050, sub_index: 0x01, type: bool, mask: 32, command_interface: d_output.6} 24 | - index: 0x1606 25 | channels: 26 | - {index: 0x7060, sub_index: 0x01, type: bool, mask: 64, command_interface: d_output.7} 27 | - index: 0x1607 28 | channels: 29 | - {index: 0x7070, sub_index: 0x01, type: bool, mask: 128, command_interface: d_output.8} 30 | sm: # Sync Manager 31 | - {index: 0, type: output, pdo: rpdo, watchdog: enable} 32 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/ati/ati_ftsensor.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for ATI EtherCAT F/T Sensor 2 | # Description : ATI EtherCAT F/T Sensor 3 | vendor_id: 0x00000732 4 | product_id: 0x26483052 5 | rpdo: # RxPDO 6 | - index: 0x1601 7 | channels: 8 | - {index: 0x7010, sub_index: 0x01, type: uint32} # Control 1 9 | - {index: 0x7010, sub_index: 0x02, type: uint32} # Control 2 10 | tpdo: # TxPDO 11 | - index: 0x1a00 12 | channels: 13 | - {index: 0x6000, sub_index: 0x01, type: int32, state_interface: force.x, factor: 1e-6, offset: 0.0} # Fx/Gage0 14 | - {index: 0x6000, sub_index: 0x02, type: int32, state_interface: force.y, factor: 1e-6, offset: 0.0} # Fy/Gage1 15 | - {index: 0x6000, sub_index: 0x03, type: int32, state_interface: force.z, factor: 1e-6, offset: 0.0} # Fz/Gage2 16 | - {index: 0x6000, sub_index: 0x04, type: int32, state_interface: torque.x, factor: 1e-6, offset: 0.0} # Tx/Gage3 17 | - {index: 0x6000, sub_index: 0x05, type: int32, state_interface: torque.y, factor: 1e-6, offset: 0.0} # Ty/Gage4 18 | - {index: 0x6000, sub_index: 0x06, type: int32, state_interface: torque.z, factor: 1e-6, offset: 0.0} # Tz/Gage5 19 | - {index: 0x6010, sub_index: 0x00, type: uint32} # Status Code 20 | - {index: 0x6020, sub_index: 0x00, type: uint32} # Sample Counter 21 | sm: # Sync Manager 22 | - {index: 0, type: output, pdo: ~, watchdog: disable} 23 | - {index: 1, type: input, pdo: ~, watchdog: disable} 24 | - {index: 2, type: output, pdo: rpdo, watchdog: enable} 25 | - {index: 3, type: input, pdo: tpdo, watchdog: disable} 26 | -------------------------------------------------------------------------------- /ethercat_force_sensor/config/easycat_config/log_configuration.txt: -------------------------------------------------------------------------------- 1 | 2 | Easy Configurator, configuration engine V_3_3 3 | 4 | log created on Thu Apr 13 11:45:58 2023 5 | 6 | Analyzing the project file 7 | 8 | Easy Configurator project ForceSensor.prj 9 | 10 | OUTPUTS_TAG 11 | INPUTS_TAG 12 | Line 5 --- force_0 int16_t 13 | Line 6 --- force_1 int16_t 14 | INFO_TAG 15 | 0x0000079A 16 | AB&T 17 | 0xDEADBEEF 18 | 0x00000001 19 | ForceSensor 20 | ForceSensor 21 | END_TAG 22 | 23 | The ForceSensor.prj configuration file is correct 24 | 25 | ByteNumOut 0 26 | ByteNumIn 4 27 | PdoNumOut 0 28 | PdoNumIn 2 29 | 30 | Creating the ForceSensor.xml file 31 | 32 | PROJECT_TAG ForceSensor.prj 33 | VENDOID_TAG 0000079A 34 | VEN_NAM_TAG AB&T 35 | PRO_COD_TAG DEADBEEF 36 | REVISIO_TAG 00000001 37 | DEV_NAM_TAG ForceSensor 38 | DEV_NAM_TAG ForceSensor 39 | 40 | FIRST_TAG 41 | 42 | Input entries 43 | 44 | #x6 45 | 1 46 | 16 47 | force_0 48 | INT 49 | 50 | 51 | #x6 52 | 2 53 | 16 54 | force_1 55 | INT 56 | 57 | 58 | LAST_TAG 59 | 60 | The ForceSensor.xml file has been created 61 | 62 | Creating the ForceSensor.h file 63 | 64 | #define CUST_BYTE_NUM_OUT 0 65 | #define CUST_BYTE_NUM_IN 4 66 | #define TOT_BYTE_NUM_ROUND_OUT 0 67 | #define TOT_BYTE_NUM_ROUND_IN 4 68 | 69 | 70 | Output entries 71 | 72 | Input entries 73 | int16_t force_0; 74 | int16_t force_1; 75 | 76 | The ForceSensor.h file has been created 77 | 78 | Creating the ForceSensor.bin file 79 | 80 | 81 | The ForceSensor.bin file has been created 82 | -------------------------------------------------------------------------------- /ethercat_force_sensor/config/easycat_config/ForceSensor.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023, ICube Laboratory, University of Strasbourg 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef ETHERCAT_FORCE_SENSOR__CONFIG__EASYCAT_CONFIG__FORCESENSOR_H_ 16 | #define ETHERCAT_FORCE_SENSOR__CONFIG__EASYCAT_CONFIG__FORCESENSOR_H_ 17 | 18 | //-------------------------------------------------------------------// 19 | // // 20 | // This file has been created by the Easy Configurator tool // 21 | // // 22 | // Easy Configurator project ForceSensor.prj 23 | // // 24 | //-------------------------------------------------------------------// 25 | 26 | 27 | #define CUST_BYTE_NUM_OUT 0 28 | #define CUST_BYTE_NUM_IN 4 29 | #define TOT_BYTE_NUM_ROUND_OUT 0 30 | #define TOT_BYTE_NUM_ROUND_IN 4 31 | 32 | //---- output buffer ---- 33 | typedef union { 34 | uint8_t Byte[TOT_BYTE_NUM_ROUND_OUT]; 35 | struct 36 | { 37 | } Cust; 38 | } PROCBUFFER_OUT; 39 | 40 | //---- input buffer ---- 41 | typedef union { 42 | uint8_t Byte[TOT_BYTE_NUM_ROUND_IN]; 43 | struct 44 | { 45 | int16_t force_0; 46 | int16_t force_1; 47 | } Cust; 48 | } PROCBUFFER_IN; 49 | 50 | #endif // ETHERCAT_FORCE_SENSOR__CONFIG__EASYCAT_CONFIG__FORCESENSOR_H_ 51 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/elmo/elmo_gold.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Elmo Gold drive 2 | vendor_id: 0x0000009a 3 | product_id: 0x00030924 4 | assign_activate: 0x0300 # DC Synch register 5 | period: 100 # Hz 6 | auto_fault_reset: false # true = automatic fault reset, false = fault reset on rising edge command interface "reset_fault" 7 | sdo: # sdo data to be transferred at drive startup 8 | - {index: 0x60C2, sub_index: 1, type: int8, value: 10} # Set interpolation time for cyclic modes to 10 ms 9 | - {index: 0x60C2, sub_index: 2, type: int8, value: -3} # Set base 10-3s 10 | - {index: 0x6098, sub_index: 0, type: int8, value: 35} 11 | rpdo: # RxPDO = receive PDO Mapping (ROS control to motor drive, Master Out to Slave In -MOSI-) 12 | - index: 0x1607 13 | channels: 14 | - {index: 0x607a, sub_index: 0, type: int32, command_interface: position, default: .nan} # Target position 15 | - {index: 0x60ff, sub_index: 0, type: int32, command_interface: velocity, default: 0} # Target velocity 16 | - {index: 0x6071, sub_index: 0, type: int16, command_interface: effort, default: -5} # Target torque 17 | - {index: 0x6072, sub_index: 0, type: int16, default: 1000} # Max torque 18 | - {index: 0x6040, sub_index: 0, type: uint16, default: 0} # Control word 19 | - {index: 0x6060, sub_index: 0, type: int8, default: 8} # Mode of operation 20 | tpdo: # TxPDO = transmit PDO Mapping (motor drive to ROS control, Master In From Slave Out -MISO-) 21 | - index: 0x1a07 22 | channels: 23 | - {index: 0x6064, sub_index: 0, type: int32, state_interface: position} # Position actual value 24 | - {index: 0x606c, sub_index: 0, type: int32, state_interface: velocity} # Velocity actual value 25 | - {index: 0x6077, sub_index: 0, type: int16, state_interface: effort} # Torque actual value 26 | - {index: 0x6041, sub_index: 0, type: uint16} # Status word 27 | - {index: 0x6061, sub_index: 0, type: int8} # Mode of operation display 28 | - {index: 0x2205, sub_index: 1, type: int16, state_interface: analog_input1} # Analog input 29 | -------------------------------------------------------------------------------- /ethercat_motor_drive/README.md: -------------------------------------------------------------------------------- 1 | # ethercat_motor_drive 2 | 3 | This repository contains the instructions for running an EtherCAT compatible motor drive and use it in ROS2 with [EtherCAT Driver ROS2 stack](https://github.com/ICube-Robotics/ethercat_driver_ros2). 4 | 5 | ## Required Hardware ## 6 | - Maxon EPOS3 motor drive 7 | - Compatible DC motor with encoder 8 | 9 | ## Usage ## 10 | ***Required setup : Ubuntu 22.04 LTS*** 11 | 12 | 1. Install `ros2` packages. The current development is based of `ros2 humble`. Installation steps are described [here](https://docs.ros.org/en/humble/Installation.html). 13 | 2. Source your `ros2` environment: 14 | ```shell 15 | source /opt/ros/humble/setup.bash 16 | ``` 17 | **NOTE**: The ros2 environment needs to be sources in every used terminal. If only one distribution of ros2 is used, it can be added to the `~/.bashrc` file. 18 | 3. Install `colcon` and its extensions : 19 | ```shell 20 | sudo apt install python3-colcon-common-extensions 21 | ``` 22 | 3. Create a new ros2 workspace: 23 | ```shell 24 | mkdir ~/ros2_ws/src 25 | ``` 26 | 4. Pull relevant packages, install dependencies, compile, and source the workspace by using: 27 | ```shell 28 | cd ~/ros2_ws 29 | git clone https://github.com/ICube-Robotics/ethercat_driver_ros2_examples.git src/ethercat_driver_ros2_examples 30 | vcs import src < ethercat_driver_ros2_examples.repos 31 | rosdep install --ignore-src --from-paths . -y -r 32 | colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release --symlink-install --packages-select ethercat_motor_drive 33 | source install/setup.bash 34 | ``` 35 | 5. Run the system: 36 | ```shell 37 | ros2 launch ethercat_motor_drive motor_drive.launch.py 38 | ``` 39 | 40 | ## Contacts ## 41 | ![icube](https://icube.unistra.fr/fileadmin/templates/DUN/icube/images/logo.png) 42 | 43 | [ICube Laboratory](https://icube.unistra.fr), [University of Strasbourg](https://www.unistra.fr/), France 44 | 45 | __Maciej Bednarczyk:__ [m.bednarczyk@unistra.fr](mailto:m.bednarczyk@unistra.fr), @github: [mcbed](https://github.com/mcbed) 46 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: [ main ] 5 | pull_request: 6 | branches: [ main ] 7 | jobs: 8 | CI: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Prepare 12 | run: | 13 | mkdir -p ${{github.workspace}}/src 14 | - uses: actions/checkout@v3 15 | with: 16 | path: src/ethercat_driver_ros2_examples 17 | 18 | - name: Build Docker Image 19 | uses: docker/build-push-action@v4 20 | with: 21 | tags: ethercat_driver_ros2_examples:humble 22 | file: .docker/Dockerfile 23 | push: false 24 | 25 | - name: Build 26 | uses: addnab/docker-run-action@v3 27 | with: 28 | image: ethercat_driver_ros2_examples:humble 29 | options: -v ${{github.workspace}}/:/ros/ 30 | run: | 31 | apt update 32 | apt upgrade -y 33 | cd /ros 34 | . /opt/ros/humble/setup.sh 35 | vcs import src < src/ethercat_driver_ros2_examples/ethercat_driver_ros2_examples.repos 36 | rosdep install --ignore-src --from-paths . -y -r && \ 37 | colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release 38 | 39 | - name: Tests 40 | uses: addnab/docker-run-action@v3 41 | with: 42 | image: ethercat_driver_ros2_examples:humble 43 | options: -v ${{github.workspace}}/:/ros/ 44 | run: | 45 | apt update 46 | apt upgrade -y 47 | cd /ros 48 | . /opt/ros/humble/setup.sh 49 | rosdep install --ignore-src --from-paths . -y -r && \ 50 | colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release 51 | colcon test 52 | colcon test-result 53 | 54 | - name: Upload Tests to Artifacts 55 | uses: actions/upload-artifact@v4 56 | if: always() 57 | with: 58 | name: test-results 59 | path: build/*/test_results/*/*.xml 60 | 61 | - name: Publish Unit Test Results 62 | uses: EnricoMi/publish-unit-test-result-action@v2 63 | if: always() 64 | with: 65 | files: build/*/test_results/*/*.xml 66 | -------------------------------------------------------------------------------- /ethercat_motor_drive/config/maxon_epos3_config.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Maxon EPOS3 drive 2 | vendor_id: 0x000000fb 3 | product_id: 0x64400000 4 | assign_activate: 0x0300 # DC Synch register 5 | auto_fault_reset: false # true = automatic fault reset, false = fault reset on rising edge command interface "reset_fault" 6 | sdo: # sdo data to be transferred at drive startup 7 | - { index: 0x60C2, sub_index: 1, type: int8, value: 10 } # Set interpolation time for cyclic modes to 10 ms 8 | - { index: 0x60C2, sub_index: 2, type: int8, value: -3 } # Set base 10-3s 9 | rpdo: # RxPDO = receive PDO 4 Mapping 10 | - index: 0x1603 11 | channels: 12 | - { index: 0x6040, sub_index: 0, type: uint16, default: 0 } # Control word 13 | - { 14 | index: 0x607a, 15 | sub_index: 0, 16 | type: int32, 17 | command_interface: position, 18 | default: .nan, 19 | } # Target position 20 | - { index: 0x60ff, sub_index: 0, type: int32, default: 0 } # Target velocity 21 | - { index: 0x6071, sub_index: 0, type: int16, default: 0 } # Target torque 22 | - { index: 0x60b0, sub_index: 0, type: int32, default: 0 } # Offset position 23 | - { index: 0x60b1, sub_index: 0, type: int32, default: 0 } # Offset velocity 24 | - { index: 0x60b2, sub_index: 0, type: int16, default: 0 } # Offset torque 25 | - { index: 0x6060, sub_index: 0, type: int8, default: 8 } # Mode of operation 26 | - { index: 0x2078, sub_index: 1, type: uint16, default: 0 } # Digital Output Functionalities 27 | - { index: 0x60b8, sub_index: 0, type: uint16, default: 0 } # Touch Probe Function 28 | tpdo: # TxPDO = transmit PDO 4 Mapping 29 | - index: 0x1a03 30 | channels: 31 | - { index: 0x6041, sub_index: 0, type: uint16 } # Status word 32 | - { index: 0x6064, sub_index: 0, type: int32, state_interface: position } # Position actual value 33 | - { index: 0x606c, sub_index: 0, type: int32, state_interface: velocity } # Velocity actual value 34 | - { index: 0x6077, sub_index: 0, type: int16, state_interface: effort } # Torque actual value 35 | - { index: 0x6061, sub_index: 0, type: int8 } # Mode of operation display 36 | - { index: 0x2071, sub_index: 1, type: int16 } # Digital Input Functionalities State 37 | - { index: 0x60b9, sub_index: 0, type: int16 } # Touch Probe Status 38 | - { index: 0x60ba, sub_index: 0, type: int32 } # Touch Probe Position 1 Positive Value 39 | - { index: 0x60bb, sub_index: 0, type: int32 } # Touch Probe Position 1 Negative Value 40 | -------------------------------------------------------------------------------- /ethercat_motor_drive/config/maxon_epos4_50_5_config.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Maxon EPOS4 50/5 drive 2 | vendor_id: 0x000000fb 3 | product_id: 0x63500000 # Product code 4 | assign_activate: 0x0300 # DC Synch register 5 | auto_fault_reset: false # true = automatic fault reset, false = fault reset on rising edge command interface "reset_fault" 6 | sdo: # sdo data to be transferred at drive startup 7 | - { index: 0x60C2, sub_index: 1, type: int8, value: 10 } # Set interpolation time for cyclic modes to 10 ms 8 | - { index: 0x60C2, sub_index: 2, type: int8, value: -3 } # Set base 10-3s 9 | rpdo: # RxPDO = receive PDO 4 Mapping 10 | - index: 0x1603 11 | channels: 12 | - { index: 0x6040, sub_index: 0, type: uint16, default: 0 } # Control word 13 | - { 14 | index: 0x607a, 15 | sub_index: 0, 16 | type: int32, 17 | command_interface: position, 18 | default: .nan, 19 | } # Target position 20 | - { index: 0x60ff, sub_index: 0, type: int32, default: 0 } # Target velocity 21 | - { index: 0x6071, sub_index: 0, type: int16, default: 0 } # Target torque 22 | - { index: 0x60b0, sub_index: 0, type: int32, default: 0 } # Offset position 23 | - { index: 0x60b1, sub_index: 0, type: int32, default: 0 } # Offset velocity 24 | - { index: 0x60b2, sub_index: 0, type: int16, default: 0 } # Offset torque 25 | - { index: 0x6060, sub_index: 0, type: int8, default: 8 } # Mode of operation 26 | - { index: 0x3150, sub_index: 1, type: uint16, default: 0 } # Digital Output Properties 27 | - { index: 0x60b8, sub_index: 0, type: uint16, default: 0 } # Touch Probe Function 28 | tpdo: # TxPDO = transmit PDO 4 Mapping 29 | - index: 0x1a03 30 | channels: 31 | - { index: 0x6041, sub_index: 0, type: uint16 } # Status word 32 | - { index: 0x6064, sub_index: 0, type: int32, state_interface: position } # Position actual value 33 | - { index: 0x606c, sub_index: 0, type: int32, state_interface: velocity } # Velocity actual value 34 | - { index: 0x6077, sub_index: 0, type: int16, state_interface: effort } # Torque actual value 35 | - { index: 0x6061, sub_index: 0, type: int8 } # Mode of operation display 36 | - { index: 0x3141, sub_index: 1, type: int16 } # Digital Input Properties 37 | - { index: 0x60b9, sub_index: 0, type: int16 } # Touch Probe Status 38 | - { index: 0x60ba, sub_index: 0, type: int32 } # Touch Probe Position 1 Positive edge 39 | - { index: 0x60bb, sub_index: 0, type: int32 } # Touch Probe Position 1 Negative edge 40 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/maxon/maxon_epos3.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Maxon EPOS3 drive 2 | vendor_id: 0x000000fb 3 | product_id: 0x64400000 4 | assign_activate: 0x0300 # DC Synch register 5 | auto_fault_reset: false # true = automatic fault reset, false = fault reset on rising edge command interface "reset_fault" 6 | sdo: # sdo data to be transferred at drive startup 7 | - {index: 0x60C2, sub_index: 1, type: int8, value: 10} # Set interpolation time for cyclic modes to 10 ms 8 | - {index: 0x60C2, sub_index: 2, type: int8, value: -3} # Set base 10-3s 9 | rpdo: # RxPDO = receive PDO Mapping (ROS control to motor drive, Master Out to Slave In -MOSI-) 10 | - index: 0x1603 11 | channels: 12 | - {index: 0x6040, sub_index: 0, type: uint16, default: 0} # Control word 13 | - {index: 0x607a, sub_index: 0, type: int32, command_interface: position, default: .nan} # Target position 14 | - {index: 0x60ff, sub_index: 0, type: int32, default: 0} # Target velocity 15 | - {index: 0x6071, sub_index: 0, type: int16, default: 0} # Target torque 16 | - {index: 0x60b0, sub_index: 0, type: int32, default: 0} # Offset position 17 | - {index: 0x60b1, sub_index: 0, type: int32, default: 0} # Offset velocity 18 | - {index: 0x60b2, sub_index: 0, type: int16, default: 0} # Offset torque 19 | - {index: 0x6060, sub_index: 0, type: int8, default: 8} # Mode of operation 20 | - {index: 0x2078, sub_index: 1, type: uint16, default: 0} # Digital Output Functionalities 21 | - {index: 0x60b8, sub_index: 0, type: uint16, default: 0} # Touch Probe Function 22 | tpdo: # TxPDO = transmit PDO Mapping (motor drive to ROS control, Master In From Slave Out -MISO-) 23 | - index: 0x1a03 24 | channels: 25 | - {index: 0x6041, sub_index: 0, type: uint16} # Status word 26 | - {index: 0x6064, sub_index: 0, type: int32, state_interface: position} # Position actual value 27 | - {index: 0x606c, sub_index: 0, type: int32, state_interface: velocity} # Velocity actual value 28 | - {index: 0x6077, sub_index: 0, type: int16, state_interface: effort} # Torque actual value 29 | - {index: 0x6061, sub_index: 0, type: int8} # Mode of operation display 30 | - {index: 0x2071, sub_index: 1, type: int16} # Digital Input Functionalities State 31 | - {index: 0x60b9, sub_index: 0, type: int16} # Touch Probe Status 32 | - {index: 0x60ba, sub_index: 0, type: int32} # Touch Probe Position 1 Positive Value 33 | - {index: 0x60bb, sub_index: 0, type: int32} # Touch Probe Position 1 Negative Value 34 | -------------------------------------------------------------------------------- /ethercat_slave_description/README.md: -------------------------------------------------------------------------------- 1 | # ethercat_slave_description 2 | Collection of EtherCAT module example configurations for the `ethercat_driver`. 3 | 4 | ## Modules using `GenericEcSlave` 5 | The list of available example EtherCAT module configurations for the `GenericEcSlave` Hardware Interface plugin. 6 | ### Beckhoff 7 | - **Beckhoff_EL1008**: EtherCAT Terminal, 8-channel digital input, 24 V DC, 3 ms. 8 | - **Beckhoff_EL1018**: EtherCAT Terminal, 8-channel digital input, 24 V DC, 10 us. 9 | - **Beckhoff_EL2008**: EtherCAT Terminal, 8-channel digital output, 24 V DC, 0.5 A. 10 | - **Beckhoff_EL2088**: EtherCAT Terminal, 8-channel digital output, 24 V DC, 0.5 A, ground switching. 11 | - **Beckhoff_EL2124**: EtherCAT Terminal, 4-channel digital output, 5 V DC, 20 mA. 12 | - **Beckhoff_EL3102**: EtherCAT Terminal, 2-channel analog input, voltage, ±10 V, 16 bit, differential. 13 | - **Beckhoff_EL3104**: EtherCAT Terminal, 4-channel analog input, voltage, ±10 V, 16 bit, differential. 14 | - **Beckhoff_EL4132**: EtherCAT Terminal, 2-channel analog output, voltage, ±10 V, 16 bit. 15 | - **Beckhoff_EL4134**: EtherCAT Terminal, 4-channel analog output, voltage, ±10 V, 16 bit. 16 | - **Beckhoff_EL5101**: EtherCAT Terminal, 1-channel encoder interface, incremental, 5 V DC (DIFF RS422, TTL), 1 MHz. 17 | 18 | ### ATI 19 | - **ATI_FTSensor**: ATI EtherCAT F/T Sensor 20 | 21 | ### Advantech 22 | - **AMAX-5051**: Digital Input Module, 8-channel digital input, 24 V DC, 4 ms. 23 | - **AMAX-5056**: Sink-type Digital Output Module, 8-channel digital output, 24 V DC, 0.3 A. 24 | 25 | ### Omron 26 | - **Omron_NX_ECC201_NX_ID5442**: Omron EtherCAT Coupler NX_ECC201 with Input module NX_ID5442. 27 | - **Omron_NX_ECC201_NX_OD5256**: Omron EtherCAT Coupler NX_ECC201 with Output module NX_OD5256. 28 | 29 | ## Motor drive modules using `EcCiA402Drive` 30 | The list of available example EtherCAT motor drive module configurations for the `EcCiA402Drive` Hardware Interface plugin. 31 | ### Maxon 32 | - **EPOS3**: EPOS3 70/10 EtherCAT, digital positioning controller, 10 A, 11 - 70 VDC 33 | - Plugin : `EcCiA402Drive` 34 | 35 | ### Schneider Electric 36 | - **Schneider_ATV320**: Schneider Electric Variable frequency drive. Coupled with VW3A3601 communication card. 37 | - Plugin : `EcCiA402Drive` 38 | 39 | ### Elmo 40 | - **Elmo Gold**: Elmo Gold servo drive. 41 | - Plugin : `EcCiA402Drive` 42 | 43 | ### Technosoft 44 | - **Technosoft IPOS 3604**: Technosoft IPOS 3064 motor drive. 45 | - Plugin : `EcCiA402Drive` 46 | 47 | ### Synapticon 48 | - **Synapticon SOMANET Circulo 9**: Synapticon SOMANET Circulo 9 Safe Motion servo drive. 49 | - Plugin : `EcCiA402Drive` 50 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/technosoft/technosoft_ipos3604.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Technosoft IPOS 3604 drive 2 | vendor_id: 0x000001a3 3 | product_id: 0x01ab46e5 4 | assign_activate: 0x0330 # DC Synch register 5 | auto_fault_reset: false # true = automatic fault reset, false = fault reset on rising edge command interface "reset_fault" 6 | sdo: # sdo data to be transferred at drive startup 7 | - {index: 0x60C2, sub_index: 1, type: int8, value: 10} # Set interpolation time for cyclic modes to 10 ms 8 | - {index: 0x60C2, sub_index: 2, type: int8, value: -3} # Set base 10-3s 9 | rpdo: # RxPDO = receive PDO Mapping (ROS control to motor drive, Master Out to Slave In -MOSI-) 10 | - index: 0x1600 11 | channels: 12 | - {index: 0x6040, sub_index: 0, type: uint16, command_interface: control_word, default: 0} # Control word 13 | - {index: 0x607a, sub_index: 0, type: int32, command_interface: position} # Target position 14 | - index: 0x1601 15 | channels: 16 | - {index: 0x6060, sub_index: 0, type: int8, command_interface: mode_of_operation, default: 8} # Mode of operation 17 | - {index: 0x60ff, sub_index: 0, type: int32, command_interface: velocity, default: 0} # Target velocity 18 | - index: 0x1602 19 | channels: 20 | - {index: 0x2090, sub_index: 2, type: uint8, default: 3} # Digital outputs mask 21 | - {index: 0x2090, sub_index: 1, type: uint8, command_interface: digital_out, default: 0} # Digital outputs value 22 | tpdo: # TxPDO = transmit PDO Mapping (motor drive to ROS control, Master In From Slave Out -MISO-) 23 | - index: 0x1a00 24 | channels: 25 | - {index: 0x6041, sub_index: 0, type: uint16, state_interface: status_word} # Status word 26 | - {index: 0x6064, sub_index: 0, type: int32, state_interface: position} # Position actual value 27 | - index: 0x1a01 28 | channels: 29 | - {index: 0x6061, sub_index: 0, type: int8, state_interface: mode_of_operation} # Mode of operation display 30 | - {index: 0x606c, sub_index: 0, type: int32, state_interface: velocity} # Velocity actual value 65536 = 1 encoder increment/sample (internal driver slow loop : 1khz ) 31 | - index: 0x1a02 32 | channels: 33 | - {index: 0x6077, sub_index: 0, type: int16, state_interface: effort} # Torque actual value 34 | - {index: 0x208F, sub_index: 2, type: uint8, state_interface: digital_in} # Digital Inputs value 35 | - index: 0x1a03 36 | channels: 37 | - {index: 0x2046, sub_index: 0, type: int16, state_interface: analog_in.1} # Analog input value 38 | - {index: 0x2047, sub_index: 0, type: int16, state_interface: analog_in.2} # Analog input value 39 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/beckhoff/beckhoff_el5101.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Beckhoff EL5101 2 | # Description : EtherCAT Terminal, 1-channel encoder interface, incremental, 5 V DC (DIFF RS422, TTL), 1 MHz 3 | # Predefined PDO assignment for Standard 32-bit mode 4 | vendor_id: 0x00000002 5 | product_id: 0x13ed3052 6 | rpdo: # RxPDO = receive PDO Mapping (ROS control to slave, Master Out to Slave In -MOSI-) 7 | - index: 0x1603 8 | channels: 9 | - {index: 0x7010, sub_index: 0x01, type: bool} # Enable latch C 10 | - {index: 0x7010, sub_index: 0x02, type: bool} # Enable latch extern on positive edge 11 | - {index: 0x7010, sub_index: 0x03, type: bool, mask: 4, command_interface: reset} # Set counter 12 | - {index: 0x7010, sub_index: 0x04, type: bool} # Enable latch extern on negative edge 13 | - {index: 0x0000, sub_index: 0x00, type: bit4} # Gap 14 | - {index: 0x0000, sub_index: 0x00, type: bit8} # Gap 15 | - {index: 0x7010, sub_index: 0x11, type: int32, default: 0} # Set counter value 16 | tpdo: # TxPDO = transmit PDO Mapping (slave to ROS control, Master In From Slave Out -MISO-) 17 | - index: 0x1a04 18 | channels: 19 | - {index: 0x6010, sub_index: 0x01, type: bool} # Latch C valid 20 | - {index: 0x6010, sub_index: 0x02, type: bool} # Latch extern valid 21 | - {index: 0x6010, sub_index: 0x03, type: bool} # Set counter done 22 | - {index: 0x6010, sub_index: 0x04, type: bool} # Counter underflow 23 | - {index: 0x6010, sub_index: 0x05, type: bool} # Counter overflow 24 | - {index: 0x6010, sub_index: 0x06, type: bool} # Status of input status 25 | - {index: 0x6010, sub_index: 0x07, type: bool} # Open circuit 26 | - {index: 0x6010, sub_index: 0x08, type: bool} # Extrapolation stall 27 | - {index: 0x6010, sub_index: 0x09, type: bool} # Status of input A 28 | - {index: 0x6010, sub_index: 0x0a, type: bool} # Status of input B 29 | - {index: 0x6010, sub_index: 0x0b, type: bool} # Status of input C 30 | - {index: 0x6010, sub_index: 0x0c, type: bool} # Status of input gate 31 | - {index: 0x6010, sub_index: 0x0d, type: bool} # Status of extern latch 32 | - {index: 0x1c32, sub_index: 0x20, type: bool} # Sync error 33 | - {index: 0x1804, sub_index: 0x07, type: bool} # TxPDO-State 34 | - {index: 0x1804, sub_index: 0x09, type: bool} # TxPDO-Toggle 35 | - {index: 0x6010, sub_index: 0x11, type: int32, state_interface: position} # Counter value 36 | - {index: 0x6010, sub_index: 0x12, type: int32} # Latch value 37 | sm: # Sync Manager 38 | - {index: 0, type: output, pdo: ~, watchdog: disable} 39 | - {index: 1, type: input, pdo: ~, watchdog: disable} 40 | - {index: 2, type: output, pdo: rpdo, watchdog: disable} 41 | - {index: 3, type: input, pdo: tpdo, watchdog: disable} 42 | -------------------------------------------------------------------------------- /ethercat_force_sensor/launch/force_sensor.launch.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 ICube Laboratory, University of Strasbourg 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from launch import LaunchDescription 16 | from launch.substitutions import Command, FindExecutable, PathJoinSubstitution, LaunchConfiguration 17 | from launch.actions import DeclareLaunchArgument 18 | 19 | from launch_ros.actions import Node 20 | from launch_ros.substitutions import FindPackageShare 21 | 22 | 23 | def generate_launch_description(): 24 | 25 | # Declare arguments 26 | declared_arguments = [] 27 | declared_arguments.append( 28 | DeclareLaunchArgument( 29 | 'description_file', 30 | default_value='force_sensor.config.xacro', 31 | description='URDF/XACRO description file with the sensor.', 32 | ) 33 | ) 34 | 35 | description_file = LaunchConfiguration('description_file') 36 | 37 | # Get URDF via xacro 38 | robot_description_content = Command( 39 | [ 40 | PathJoinSubstitution([FindExecutable(name="xacro")]), 41 | " ", 42 | PathJoinSubstitution( 43 | [ 44 | FindPackageShare("ethercat_force_sensor"), 45 | "description/config", 46 | description_file, 47 | ] 48 | ), 49 | ] 50 | ) 51 | robot_description = {"robot_description": robot_description_content} 52 | 53 | robot_controllers = PathJoinSubstitution( 54 | [ 55 | FindPackageShare("ethercat_force_sensor"), 56 | "config", 57 | "controllers.yaml", 58 | ] 59 | ) 60 | 61 | control_node = Node( 62 | package="controller_manager", 63 | executable="ros2_control_node", 64 | parameters=[robot_description, robot_controllers], 65 | output="both", 66 | ) 67 | 68 | joint_state_broadcaster_spawner = Node( 69 | package="controller_manager", 70 | executable="spawner", 71 | arguments=["joint_state_broadcaster", "-c", "/controller_manager"], 72 | ) 73 | 74 | nodes = [ 75 | control_node, 76 | joint_state_broadcaster_spawner, 77 | ] 78 | 79 | return LaunchDescription( 80 | declared_arguments + 81 | nodes) 82 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | Thank you for your interest in contributing to `ethercat_driver_ros2_examples`. Whether it's a bug report, new feature, correction, or additional documentation, we greatly value feedback and contributions from the community. 3 | 4 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary information to effectively respond to your bug report or contribution. 5 | 6 | 7 | ## Reporting Bugs/Feature Requests 8 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 9 | 10 | When filing an issue, please check [existing open][issues], or [recently closed][closed-issues], issues to make sure somebody else hasn't already reported the issue. 11 | 12 | Please try to include as much information as you can. Details like these are incredibly useful: 13 | 14 | * A reproducible test case or series of steps 15 | * The version of our code being used 16 | * Any modifications you've made relevant to the bug 17 | * Anything unusual about your environment or deployment 18 | 19 | 20 | ## Contributing via Pull Requests 21 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 22 | 23 | 1. You are working against the latest source on the *main* branch. 24 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 25 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 26 | 27 | To send us a pull request, please: 28 | 29 | 1. Fork the repository. 30 | 2. Modify the source; please focus on the specific change you are contributing. 31 | If you also reformat all the code, it will be hard for us to focus on your change. 32 | 3. Ensure local tests pass. 33 | 4. Commit to your fork using clear commit messages. 34 | 5. Send a pull request, answering any default questions in the pull request interface. 35 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 36 | 37 | GitHub provides additional documentation on [forking a repository](https://help.github.com/articles/fork-a-repo/) and [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 38 | 39 | 40 | ## Licensing 41 | Any contribution that you make to this repository will be under the Apache 2 License, as dictated by that [license](http://www.apache.org/licenses/LICENSE-2.0.html): 42 | 43 | ~~~ 44 | 5. Submission of Contributions. Unless You explicitly state otherwise, 45 | any Contribution intentionally submitted for inclusion in the Work 46 | by You to the Licensor shall be under the terms and conditions of 47 | this License, without any additional terms or conditions. 48 | Notwithstanding the above, nothing herein shall supersede or modify 49 | the terms of any separate license agreement you may have executed 50 | with Licensor regarding such Contributions. 51 | ~~~ 52 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/synapticon/synapticon_somanet_circulo9.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Synapticon SOMANET Circulo 9 Safe Motion, Firmware Version 5.1.3 2 | vendor_id: 0x000022d2 3 | product_id: 0x00000302 4 | assign_activate: 0x0300 # DC Synch register 5 | auto_fault_reset: false # true = automatic fault reset, false = fault reset on rising edge command interface "reset_fault" 6 | rpdo: # RxPDO = receive PDO Mapping (ROS control to motor drive, Master Out to Slave In -MOSI-) 7 | - index: 0x1600 8 | channels: 9 | - {index: 0x6040, sub_index: 0, type: uint16, default: 0} # Control word 10 | - {index: 0x607a, sub_index: 0, type: int32, command_interface: position, default: .nan} # Target position 11 | - {index: 0x60ff, sub_index: 0, type: int32, default: 0} # Target velocity 12 | - {index: 0x6071, sub_index: 0, type: int16, default: 0} # Target torque 13 | - {index: 0x60b2, sub_index: 0, type: int16, default: 0} # Offset torque 14 | - {index: 0x6060, sub_index: 0, type: int8, default: 8} # Mode of operation 15 | - {index: 0x2701, sub_index: 0, type: uint32, default: 0} # Tuning command 16 | - index: 0x1601 17 | channels: 18 | - {index: 0x60fe, sub_index: 1, type: uint32, default: 0} # Digital Outputs: Physical Outputs 19 | - {index: 0x60fe, sub_index: 2, type: uint32, default: 0} # Digital Outputs: Bit Mask 20 | - index: 0x1602 21 | channels: 22 | - {index: 0x60b1, sub_index: 0, type: int32, default: 0} # Offset velocity 23 | - {index: 0x2703, sub_index: 0, type: uint32, default: 0} # User MOSI 24 | 25 | tpdo: # TxPDO = transmit PDO Mapping (motor drive to ROS control, Master In From Slave Out -MISO-) 26 | - index: 0x1a00 27 | channels: 28 | - {index: 0x6041, sub_index: 0, type: uint16} # Status word 29 | - {index: 0x6064, sub_index: 0, type: int32, state_interface: position} # Position actual value 30 | - {index: 0x606c, sub_index: 0, type: int32, state_interface: velocity} # Velocity actual value 31 | - {index: 0x6077, sub_index: 0, type: int16, state_interface: effort} # Torque actual value 32 | - {index: 0x6061, sub_index: 0, type: int8} # Mode of operation display 33 | - {index: 0x60f4, sub_index: 0, type: int32} # Following error actual value 34 | - index: 0x1a01 35 | channels: 36 | - {index: 0x2401, sub_index: 0, type: uint16} # Analog input 1 37 | - {index: 0x2402, sub_index: 0, type: uint16} # Analog input 2 38 | - {index: 0x2403, sub_index: 0, type: uint16} # Analog input 3 39 | - {index: 0x2404, sub_index: 0, type: uint16} # Analog input 4 40 | - {index: 0x2702, sub_index: 0, type: uint32} # Tuning status 41 | - index: 0x1a02 42 | channels: 43 | - {index: 0x60fd, sub_index: 0, type: uint32} # Digital Inputs 44 | - index: 0x1a03 45 | channels: 46 | - {index: 0x2704, sub_index: 0, type: uint32} # User MISO 47 | - {index: 0x20f0, sub_index: 0, type: uint32} # Timestamp 48 | - {index: 0x60fc, sub_index: 0, type: int32} # Position demand internal value 49 | - {index: 0x606b, sub_index: 0, type: int32} # Velocity demand value 50 | - {index: 0x6074, sub_index: 0, type: int16} # Torque demand 51 | -------------------------------------------------------------------------------- /ethercat_force_sensor/README.md: -------------------------------------------------------------------------------- 1 | # ethercat_force_sensor 2 | 3 | This repository contains the instructions for building a custom Force Sensor EtherCAT slave using strain gauges and EasyCAT and use it in ROS2 with [EtherCAT Driver ROS2 stack](https://github.com/ICube-Robotics/ethercat_driver_ros2). 4 | 5 | ## Required Hardware ## 6 | | | | 7 | |---|--- 8 | | [Arduino Uno](https://store.arduino.cc/products/arduino-uno-rev3) | 9 | | [Load Cell / Wheatstone Amplifier Shield (2ch)](https://eu.robotshop.com/products/strain-gauge-load-cell-amplifier-shield-2ch) | | 10 | | [EasyCAT Shield for Arduino](https://www.bausano.net/en/hardware/easycat.html) | 11 | | [5 Kg Micro Load Cell](https://eu.robotshop.com/products/micro-load-cell-5-kg) | 12 | 13 | 14 | 15 | ## EasyCAT configuration ## 16 | Use the [EasyConfigurator](https://www.bausano.net/images/arduino-easycat/EasyConfigurator_UserManual.pdf) tool to load the [ForceSensor](config/easycat_config/ForceSensor.prj) file and write the configuration to the slave EEPROM. 17 | 18 | Open the [ForceSensor](config/easycat_config/ForceSensor.ino) Arduino project in the [Arduino IDE](https://www.arduino.cc/en/software) and upload it to the Arduino board. 19 | 20 | ## Usage ## 21 | ***Required setup : Ubuntu 22.04 LTS*** 22 | 23 | 1. Install `ros2` packages. The current development is based of `ros2 humble`. Installation steps are described [here](https://docs.ros.org/en/humble/Installation.html). 24 | 2. Source your `ros2` environment: 25 | ```shell 26 | source /opt/ros/humble/setup.bash 27 | ``` 28 | **NOTE**: The ros2 environment needs to be sources in every used terminal. If only one distribution of ros2 is used, it can be added to the `~/.bashrc` file. 29 | 3. Install `colcon` and its extensions : 30 | ```shell 31 | sudo apt install python3-colcon-common-extensions 32 | ``` 33 | 3. Create a new ros2 workspace: 34 | ```shell 35 | mkdir ~/ros2_ws/src 36 | ``` 37 | 4. Pull relevant packages, install dependencies, compile, and source the workspace by using: 38 | ```shell 39 | cd ~/ros2_ws 40 | git clone https://github.com/ICube-Robotics/ethercat_driver_ros2_examples.git src/ethercat_driver_ros2_examples 41 | vcs import src < ethercat_driver_ros2_examples.repos 42 | rosdep install --ignore-src --from-paths . -y -r 43 | colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release --symlink-install --packages-select ethercat_force_sensor 44 | source install/setup.bash 45 | ``` 46 | 5. Run the system: 47 | ```shell 48 | ros2 launch ethercat_force_sensor force_sensor.launch.py 49 | ``` 50 | 51 | ## Contacts ## 52 | ![icube](https://icube.unistra.fr/fileadmin/templates/DUN/icube/images/logo.png) 53 | 54 | [ICube Laboratory](https://icube.unistra.fr), [University of Strasbourg](https://www.unistra.fr/), France 55 | 56 | __Maciej Bednarczyk:__ [m.bednarczyk@unistra.fr](mailto:m.bednarczyk@unistra.fr), @github: [mcbed](https://github.com/mcbed) 57 | -------------------------------------------------------------------------------- /ethercat_slave_description/config/beckhoff/beckhoff_el3104.yaml: -------------------------------------------------------------------------------- 1 | # Configuration file for Beckhoff EL3104 2 | # Description : EtherCAT Terminal, 4-channel analog input, voltage, ±10 V, 16 bit, differential. 3 | vendor_id: 0x00000002 4 | product_id: 0x0c203052 5 | tpdo: # TxPDO = transmit PDO Mapping (slave to ROS control, Master In From Slave Out -MISO-) 6 | - index: 0x1a00 7 | channels: 8 | - {index: 0x6000, sub_index: 0x01, type: bool} # Underrange 9 | - {index: 0x6000, sub_index: 0x02, type: bool} # Overrange 10 | - {index: 0x6000, sub_index: 0x03, type: bit2} # Limit 1 11 | - {index: 0x6000, sub_index: 0x05, type: bit2} # Limit 2 12 | - {index: 0x6000, sub_index: 0x07, type: bool} # Error 13 | - {index: 0x0000, sub_index: 0x00, type: bool} # Gap 14 | - {index: 0x0000, sub_index: 0x00, type: bit5} # Gap 15 | - {index: 0x6000, sub_index: 0x0e, type: bool} # Sync error 16 | - {index: 0x6000, sub_index: 0x0f, type: bool} # TxPDO State 17 | - {index: 0x6000, sub_index: 0x10, type: bool} # TxPDO Toggle 18 | - {index: 0x6000, sub_index: 0x11, type: int16, state_interface: analog_input.1, factor: 0.000305185} # Value 19 | - index: 0x1a02 20 | channels: 21 | - {index: 0x6010, sub_index: 0x01, type: bool} # Underrange 22 | - {index: 0x6010, sub_index: 0x02, type: bool} # Overrange 23 | - {index: 0x6010, sub_index: 0x03, type: bit2} # Limit 1 24 | - {index: 0x6010, sub_index: 0x05, type: bit2} # Limit 2 25 | - {index: 0x6010, sub_index: 0x07, type: bool} # Error 26 | - {index: 0x0000, sub_index: 0x00, type: bool} # Gap 27 | - {index: 0x0000, sub_index: 0x00, type: bit5} # Gap 28 | - {index: 0x6010, sub_index: 0x0e, type: bool} # Sync error 29 | - {index: 0x6010, sub_index: 0x0f, type: bool} # TxPDO State 30 | - {index: 0x6010, sub_index: 0x10, type: bool} # TxPDO Toggle 31 | - {index: 0x6010, sub_index: 0x11, type: int16, state_interface: analog_input.2, factor: 0.000305185} 32 | - index: 0x1a04 33 | channels: 34 | - {index: 0x6020, sub_index: 0x01, type: bool} # Underrange 35 | - {index: 0x6020, sub_index: 0x02, type: bool} # Overrange 36 | - {index: 0x6020, sub_index: 0x03, type: bit2} # Limit 1 37 | - {index: 0x6020, sub_index: 0x05, type: bit2} # Limit 2 38 | - {index: 0x6020, sub_index: 0x07, type: bool} # Error 39 | - {index: 0x0000, sub_index: 0x00, type: bool} # Gap 40 | - {index: 0x0000, sub_index: 0x00, type: bit5} # Gap 41 | - {index: 0x6020, sub_index: 0x0e, type: bool} # Sync error 42 | - {index: 0x6020, sub_index: 0x0f, type: bool} # TxPDO State 43 | - {index: 0x6020, sub_index: 0x10, type: bool} # TxPDO Toggle 44 | - {index: 0x6020, sub_index: 0x11, type: int16, state_interface: analog_input.3, factor: 0.000305185} 45 | - index: 0x1a06 46 | channels: 47 | - {index: 0x6030, sub_index: 0x01, type: bool} # Underrange 48 | - {index: 0x6030, sub_index: 0x02, type: bool} # Overrange 49 | - {index: 0x6030, sub_index: 0x03, type: bit2} # Limit 1 50 | - {index: 0x6030, sub_index: 0x05, type: bit2} # Limit 2 51 | - {index: 0x6030, sub_index: 0x07, type: bool} # Error 52 | - {index: 0x0000, sub_index: 0x00, type: bool} # Gap 53 | - {index: 0x0000, sub_index: 0x00, type: bit5} # Gap 54 | - {index: 0x6030, sub_index: 0x0e, type: bool} # Sync error 55 | - {index: 0x6030, sub_index: 0x0f, type: bool} # TxPDO State 56 | - {index: 0x6030, sub_index: 0x10, type: bool} # TxPDO Toggle 57 | - {index: 0x6030, sub_index: 0x11, type: int16, state_interface: analog_input.4, factor: 0.000305185} 58 | sm: # Sync Manager 59 | - {index: 3, type: input, pdo: tpdo, watchdog: enable} 60 | -------------------------------------------------------------------------------- /ethercat_motor_drive/launch/motor_drive.launch.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 ICube Laboratory, University of Strasbourg 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from launch import LaunchDescription 16 | from launch.substitutions import Command, FindExecutable, PathJoinSubstitution, LaunchConfiguration 17 | from launch.actions import DeclareLaunchArgument 18 | 19 | from launch_ros.actions import Node 20 | from launch_ros.substitutions import FindPackageShare 21 | 22 | 23 | def generate_launch_description(): 24 | 25 | # Declare arguments 26 | declared_arguments = [] 27 | declared_arguments.append( 28 | DeclareLaunchArgument( 29 | 'description_file', 30 | default_value='motor_drive.config.xacro', 31 | description='URDF/XACRO description file with the axis.', 32 | ) 33 | ) 34 | 35 | description_file = LaunchConfiguration('description_file') 36 | 37 | # Get URDF via xacro 38 | robot_description_content = Command( 39 | [ 40 | PathJoinSubstitution([FindExecutable(name="xacro")]), 41 | " ", 42 | PathJoinSubstitution( 43 | [ 44 | FindPackageShare("ethercat_motor_drive"), 45 | "description/config", 46 | description_file, 47 | ] 48 | ), 49 | ] 50 | ) 51 | robot_description = {"robot_description": robot_description_content} 52 | 53 | robot_controllers = PathJoinSubstitution( 54 | [ 55 | FindPackageShare("ethercat_motor_drive"), 56 | "config", 57 | "controllers.yaml", 58 | ] 59 | ) 60 | 61 | control_node = Node( 62 | package="controller_manager", 63 | executable="ros2_control_node", 64 | parameters=[robot_description, robot_controllers], 65 | output="both", 66 | ) 67 | robot_state_pub_node = Node( 68 | package="robot_state_publisher", 69 | executable="robot_state_publisher", 70 | output="both", 71 | parameters=[robot_description], 72 | ) 73 | 74 | joint_state_broadcaster_spawner = Node( 75 | package="controller_manager", 76 | executable="spawner", 77 | arguments=["joint_state_broadcaster", "-c", "/controller_manager"], 78 | ) 79 | 80 | trajectory_controller_spawner = Node( 81 | package="controller_manager", 82 | executable="spawner", 83 | arguments=["trajectory_controller", "-c", "/controller_manager"], 84 | ) 85 | 86 | # velocity_controller_spawner = Node( 87 | # package="controller_manager", 88 | # executable="spawner", 89 | # arguments=["velocity_controller", "-c", "/controller_manager"], 90 | # ) 91 | 92 | # effort_controller_spawner = Node( 93 | # package="controller_manager", 94 | # executable="spawner", 95 | # arguments=["effort_controller", "-c", "/controller_manager"], 96 | # ) 97 | 98 | nodes = [ 99 | control_node, 100 | robot_state_pub_node, 101 | joint_state_broadcaster_spawner, 102 | trajectory_controller_spawner, 103 | # velocity_controller_spawner, 104 | # effort_controller_spawner, 105 | ] 106 | 107 | return LaunchDescription( 108 | declared_arguments + 109 | nodes) 110 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # To use: 2 | # 3 | # pre-commit run -a 4 | # 5 | # Or: 6 | # 7 | # pre-commit install # (runs every time you commit in git) 8 | # 9 | # To update this file: 10 | # 11 | # pre-commit autoupdate 12 | # 13 | # See https://github.com/pre-commit/pre-commit 14 | 15 | repos: 16 | # Standard hooks 17 | - repo: https://github.com/pre-commit/pre-commit-hooks 18 | rev: v4.4.0 19 | hooks: 20 | - id: check-added-large-files 21 | - id: check-ast 22 | - id: check-case-conflict 23 | - id: check-docstring-first 24 | - id: check-merge-conflict 25 | - id: check-symlinks 26 | - id: check-xml 27 | - id: check-yaml 28 | - id: debug-statements 29 | - id: end-of-file-fixer 30 | - id: mixed-line-ending 31 | - id: trailing-whitespace 32 | exclude_types: [rst] 33 | - id: fix-byte-order-marker 34 | 35 | 36 | # Python hooks 37 | - repo: https://github.com/asottile/pyupgrade 38 | rev: v3.3.1 39 | hooks: 40 | - id: pyupgrade 41 | args: [--py36-plus] 42 | 43 | # PyDocStyle 44 | - repo: https://github.com/PyCQA/pydocstyle 45 | rev: 6.3.0 46 | hooks: 47 | - id: pydocstyle 48 | args: ["--ignore=D100,D101,D102,D103,D104,D105,D106,D107,D203,D212,D404"] 49 | 50 | - repo: https://github.com/pycqa/flake8 51 | rev: 6.0.0 52 | hooks: 53 | - id: flake8 54 | args: ["--extend-ignore=E501"] 55 | 56 | # Uncrustify 57 | - repo: local 58 | hooks: 59 | - id: ament_uncrustify 60 | name: ament_uncrustify 61 | description: Uncrustify. 62 | stages: [commit] 63 | entry: ament_uncrustify 64 | language: system 65 | files: \.(h\+\+|h|hh|hxx|hpp|cuh|c|cc|cpp|cu|c\+\+|cxx|tpp|txx)$ 66 | args: ["--reformat"] 67 | 68 | # CPP hooks 69 | - repo: local 70 | hooks: 71 | - id: clang-format 72 | name: clang-format 73 | description: Format files with ClangFormat. 74 | entry: clang-format-14 75 | language: system 76 | files: \.(c|cc|cxx|cpp|frag|glsl|h|hpp|hxx|ih|ispc|ipp|java|js|m|proto|vert)$ 77 | args: ['-fallback-style=none', '-i'] 78 | 79 | # - repo: local 80 | # hooks: 81 | # - id: ament_cppcheck 82 | # name: ament_cppcheck 83 | # description: Static code analysis of C/C++ files. 84 | # stages: [commit] 85 | # entry: ament_cppcheck 86 | # language: system 87 | # files: \.(h\+\+|h|hh|hxx|hpp|cuh|c|cc|cpp|cu|c\+\+|cxx|tpp|txx)$ 88 | 89 | # Maybe use https://github.com/cpplint/cpplint instead 90 | - repo: local 91 | hooks: 92 | - id: ament_cpplint 93 | name: ament_cpplint 94 | description: Static code analysis of C/C++ files. 95 | stages: [commit] 96 | entry: ament_cpplint 97 | language: system 98 | files: \.(h\+\+|h|hh|hxx|hpp|cuh|c|cc|cpp|cu|c\+\+|cxx|tpp|txx)$ 99 | args: ["--linelength=100", "--filter=-whitespace/newline"] 100 | 101 | # Cmake hooks 102 | - repo: local 103 | hooks: 104 | - id: ament_lint_cmake 105 | name: ament_lint_cmake 106 | description: Check format of CMakeLists.txt files. 107 | stages: [commit] 108 | entry: ament_lint_cmake 109 | language: system 110 | files: CMakeLists\.txt$ 111 | 112 | # Copyright 113 | - repo: local 114 | hooks: 115 | - id: ament_copyright 116 | name: ament_copyright 117 | description: Check if copyright notice is available in all files. 118 | stages: [commit] 119 | entry: ament_copyright 120 | language: system 121 | 122 | # Docs - RestructuredText hooks 123 | - repo: https://github.com/PyCQA/doc8 124 | rev: v1.1.1 125 | hooks: 126 | - id: doc8 127 | args: ['--max-line-length=100', '--ignore=D001'] 128 | exclude: CHANGELOG\.rst$ 129 | 130 | - repo: https://github.com/pre-commit/pygrep-hooks 131 | rev: v1.10.0 132 | hooks: 133 | - id: rst-backticks 134 | exclude: CHANGELOG\.rst$ 135 | - id: rst-directive-colons 136 | - id: rst-inline-touching-normal 137 | 138 | # Spellcheck in comments and docs 139 | # skipping of *.svg files is not working... 140 | - repo: https://github.com/codespell-project/codespell 141 | rev: v2.2.2 142 | hooks: 143 | - id: codespell 144 | args: ['--write-changes'] 145 | exclude: CHANGELOG\.rst|\.(svg|pyc)$ 146 | -------------------------------------------------------------------------------- /ethercat_force_sensor/config/easycat_config/ForceSensor.ino: -------------------------------------------------------------------------------- 1 | #define CUSTOM 2 | #include "ForceSensor.h" 3 | #include "EasyCAT.h" // EasyCAT library to interface the LAN9252 4 | #include // SPI library 5 | 6 | EasyCAT EASYCAT(8); // EasyCAT istantiation 7 | 8 | const int Ana0 = A0; // analog input 0 9 | const int Ana1 = A1; // analog input 1 10 | 11 | unsigned long Millis = 0; 12 | unsigned long PreviousMillis = 0; 13 | 14 | 15 | //---- setup --------------------------------------------------------------------------------------- 16 | 17 | void setup() 18 | { 19 | Serial.begin(9600); // serial line initialization 20 | //(used only for debug) 21 | 22 | Serial.print ("\nEasyCAT - Generic EtherCAT slave\n"); // print the banner 23 | 24 | //---- initialize the EasyCAT board ----- 25 | 26 | if (EASYCAT.Init() == true) // initialization 27 | { // successfully completed 28 | Serial.print ("initialized"); // 29 | } // 30 | 31 | else // initialization failed 32 | { // the EasyCAT board was not recognized 33 | Serial.print ("initialization failed"); // 34 | // The most common reason is that the SPI 35 | // chip select chosen on the board doesn't 36 | // match the one chosen by the firmware 37 | 38 | pinMode(13, OUTPUT); // stay in loop for ever 39 | // with the Arduino led blinking 40 | while(1) // 41 | { // 42 | digitalWrite (13, LOW); // 43 | delay(500); // 44 | digitalWrite (13, HIGH); // 45 | delay(500); // 46 | } // 47 | } 48 | 49 | PreviousMillis = millis(); 50 | } 51 | 52 | 53 | //---- main loop ---------------------------------------------------------------------------------------- 54 | 55 | void loop() // In the main loop we must call ciclically the 56 | { // EasyCAT task and our application 57 | // 58 | // This allows the bidirectional exachange of the data 59 | // between the EtherCAT master and our application 60 | // 61 | // The EasyCAT cycle and the Master cycle are asynchronous 62 | // 63 | 64 | EASYCAT.MainTask(); // execute the EasyCAT task 65 | 66 | Application(); // user applications 67 | 68 | } 69 | 70 | //---- user application ------------------------------------------------------------------------------ 71 | 72 | void Application () 73 | 74 | { 75 | uint16_t Analog0; 76 | uint16_t Analog1; 77 | 78 | Millis = millis(); // As an example for this application 79 | if (Millis - PreviousMillis >= 10) // we choose a cycle time of 10 mS 80 | { // 81 | PreviousMillis = Millis; // 82 | 83 | // --- analog inputs management --- 84 | 85 | Analog0 = analogRead(Ana0); // read analog input 0 86 | Analog0 = Analog0 << 6; // normalize it on 16 bits 87 | EASYCAT.BufferIn.Cust.force_0 = Analog0; // and put the result into 88 | // input Byte 0 89 | 90 | Analog1 = analogRead(Ana1); // read analog input 1 91 | Analog1 = Analog1 << 6; // normalize it on 16 bits 92 | EASYCAT.BufferIn.Cust.force_1 = Analog1; // and put the result into 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /ethercat_force_sensor/config/easycat_config/ForceSensor.xml: -------------------------------------------------------------------------------- 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 | 31 | 32 | 33 | 34 | 35 | #x0000079A 36 | AB&T 37 | 424dd6020000000000003600000028000000100000000e0000000100180000000000a0020000c40e0000c40e000000000000000000004cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb1224cb122ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff241cedffffff241cedffffff241ced241cedffffffffffffffffff241ced241ced241cedffffff241cedffffffffffff241cedffffff241cedffffff241cedffffff241cedffffff241cedffffff241cedffffffffffff241cedffffffffffff241cedffffff241cedffffff241cedffffff241cedffffff241cedffffff241cedffffffffffff241cedffffffffffff241cedffffff241cedffffff241cedffffff241cedffffffffffff241cedffffffffffffffffff241cedffffffffffff241ced241ced241cedffffff241ced241cedffffffffffff241cedffffff241cedffffffffffff241cedffffffffffff241cedffffff241cedffffff241cedffffff241cedffffff241cedffffff241cedffffffffffff241cedffffffffffff241cedffffff241cedffffff241cedffffff241cedffffffffffff241cedffffffffffffffffff241cedffffffffffff241cedffffff241cedffffff241cedffffff241cedffffffffffffffffffffffffffffffffffff241cedffffffffffffffffff241cedffffffffffffffffff241cedffffffffffffffffffffffffffffffffffff241ced241ced241cedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 38 | 39 | 40 | 41 | 42 | SSC_Device 43 | EasyCAT 44 | 424dd6020000000000003600000028000000100000000e0000000100180000000000a0020000c40e0000c40e00000000000000000000241ced241ced241ced241cedffffff241cedffffffffffffffffff241cedffffffffffffffffff241cedffffffffffff241cedffffffffffffffffffffffff241cedffffffffffffffffff241cedffffffffffffffffff241cedffffffffffff241cedffffffffffffffffffffffff241ced241ced241ced241ced241cedffffffffffffffffff241cedffffffffffff241cedffffffffffffffffffffffff241cedffffffffffffffffff241cedffffffffffffffffff241cedffffffffffff241cedffffffffffffffffffffffff241ced241cedffffff241ced241cedffffff241cedffffff241cedffffff241ced241ced241ced241ced241cedffffffffffff241ced241ced241cedffffffffffff241ced241ced241ced241ced241cedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff241ced241ced241cedffffffffffff241ced241ced241cedffffff241ced241ced241cedffffff241ced241ced241ced241cedffffffffffffffffff241cedffffffffffff241cedffffffffffffffffff241cedffffffffffffffffff241ced241cedffffffffffffffffffffffff241ced241cedffffffffffff241ced241ced241cedffffff241ced241ced241ced241ced241cedffffffffffffffffffffffffffffff241cedffffff241cedffffffffffffffffff241cedffffff241ced241cedffffffffffffffffffffffff241ced241ced241cedffffff241ced241ced241cedffffff241cedffffff241ced241cedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff241ced241ced241cedffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | ForceSensor 57 | 58 | SSC_Device 59 | Inputs 60 | 61 | 62 | Inputs 63 | 64 | 65 | 66 | 67 | #x1A00 68 | Inputs 69 | 70 | #x6 71 | 1 72 | 16 73 | force_0 74 | INT 75 | 76 | 77 | #x6 78 | 2 79 | 16 80 | force_1 81 | INT 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | SM_Sync or Async 91 | SM_Sync or Async 92 | #x0000 93 | 94 | 95 | 96 | DC_Sync 97 | DC_Sync 98 | #x300 99 | 0 100 | 2000200000 101 | 102 | 103 | 104 | 105 | 106 | 107 | 4096 108 | 8003006EFF00FF000000 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------