Giter VIP home page Giter VIP logo

soem's Introduction

SOEM for ROS

Table of Contents

A Note On The Version Number

This package tracks the upstream Open Ethercat Master Repo and thus should directly reference the respective version number of the upstream. As this does not allow for intermediate releases that only change ROS specific parts, like the CMake plumbing, it has been decided to deviate from the upstream version by adding an arbitrary number (100) to the patch part of the version, and then multiplying by ten (i.e. (patch of upstream + 100) * 10). This allows for intermediate releases in between integrations of upstream releases.

Thus, the version numbers relate to each other as follows:

1.4.1000 -> upstream 1.4.0
1.4.1010 -> upstream 1.4.1
1.4.1011 -> upstream 1.4.1 + ROS specific changes 1

The idea for this approach was taken from the cartographer_ros package.

Package Description

SOEM is an open source EtherCAT master library written in C. Its primary target is Linux but can be adapted to other OS and embedded systems.

SOEM has originally been hosted at http://developer.berlios.de/projects/soem/ but has been moved to GitHub and the OpenEtherCATsociety organisation.

This package contains the upstream SOEM repository as a git subtree and wraps it to be easily used within ROS.

Disclaimer: This package is not a development package for SOEM, but rather a wrapper to provide SOEM to ROS. In the end, this just provides the CMake quirks that allows releasing SOEM as a ROS package.

All bug reports regarding the original SOEM source code should go to the bugtracker at https://github.com/OpenEtherCATsociety/SOEM/issues.

All ROS related issues should target the bug tracker on GitHub (but might be redirected ;-)).

Obviously, any support, being it bug reports or pull requests (obviously preferred) are highly welcome!

Installation

If soem has been released for your respective ROS distribution, you can simply install it using

sudo apt install ros-<DISTRO>-soem

Currently, soem has been released for ROS indigo, kinetic and melodic. If you want to use soem from source, please check out the section about Development.

Usage

To use soem in your ROS package add the following to your package.xmland CMakeLists.txt, respectively.

In your package.xml add:

  <build_depend>soem</build_depend>
  <exec_depend>soem</exec_depend>

and in your CMakeLists.txt, add it to find_package and adapt the include_directories as shown:

find_package(catkin REQUIRED COMPONENTS
  ...
  soem
  ...
)

include_directories(
  ...
  ${catkin_INCLUDE_DIRS}
)

Running without sudo/root

SOEM requires access to certain network capabilities as it is using raw sockets, and as such any executable linking against SOEM needs to be run with certain privileges. Typically, you run any SOEM executables with sudo or as root. Tis is impractical for any ROS system, and as such there exists a tool called ethercat_grant that helps with that.

Install with

sudo apt install ros-<DISTRO>-ethercat-ethercat_grant

and add the following to your your node tag in your launchfile

launch-prefix="ethercat_grant

Development

With the integration of the upstream SOEM repo as a git subtree, and a major overhaul of the build system, it is now possible to use the soem ROS package easily from your regular ROS workspace.

Simply clone this repository into your workspace

git clone [email protected]:mgruhler/soem.git

Note that if you want to update or patch the subtree which includes the SOEM upstream repository, you need to be sure to do this properly. When creating this, I followed the instructions in this Atlassian blog post. This covers all the things you need.

This package has been tested using both, catkin_make and catkin build.

soem's People

Contributors

meyerj avatar mgruhler avatar seanyen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

soem's Issues

Update to latest upstream SOEM release

The latest release of upstream SOEM is 1.3.1, there is a release candidate for 1.3.3 available as well. (1.3.2 is marked as DON'T use) 1.4, as stated by @FelixBlix in #16 (comment).
If possible, it would be nice to update to the latest release.

Updating to 1.3.1 has initally been proposed in #9.

However, there are apparently some issues with 1.3.1, as discussed in #5 (comment)

As mentioned in issue #9 , I tried using 1.3.1 myself. It did compile, but wasn't working at all. I think the main issue is the Added multi-threaded configuration for parallel configurations of slaves

This would need to be thoroughly tested though.

Can't find osal.h when linking from catkin/ROS package

System config:

  • ROS Indigo/14.04
  • Installed ros-indigo-soem

When trying to link against soem to build the robotiq package, I get the following error in ethercattype.h

/opt/ros/indigo/include/soem/ethercattype.h:68:18: fatal error: osal.h: No such file or directory
 #include <osal.h>

If I download the soem source, the header is found and everything compiles.

I can also get it to work by manually adding the soem header directory, see here

I'm not sure what the fix is, since catkin/ROS convention is for headers to be in the <package_name> subdirectory, but the soem headers do not adhere to this.

Hardware needed?

Hi @mgruhler,

I want to communicate my PC to an Ethercat remote IO using ROS.

Do I need special chip on the PC side?
Or I can directly communicate using soem?

Using soem with robotiq

I'm trying to build the soem library, but when linking with the robotiq packages I run into an issue where cmake cannot find the soem/ethercattype.h file. It seems like there have been other similar issues with robotiq packages. I'm running on kinetic, is there a way to get them to build together?

No socket connection

Hi,
I've installed SOEM(build from source) with ROS Kinetic on Ubuntu 16.04.
And I've created a C++ ROS node and inside it I've reproduced the example "simple test"
However, when I "rosrun" this node, I was told that:
No socket connection on ethxxx
Excecute as root

Thus, I try "rosrun" this node in root:
sudo su
rosrun [package] [node]

but the same problem occurred.

How can I solve it?
Could you give some examples, such as a node?
Waiting for you response, thank you.

SOEM to ease CI for ROS-i tests

Is your feature request related to a problem? Please describe.
Using Travis (or some other platform-like) for Continuous Integration may require a physical robot for regression tests (i.e. robot drivers)

Describe the solution you'd like
I was imaging about a SOEM version for testing, so it should keep track on the calls and returning as if a physical robot were responding. Does this make sense?

ROS Distro (please check as appropriate):

  • Kinetic
  • Lunar
  • Melodic
  • Other: ...

Hardware setup
No hardware at all.

ROS SOEM installation

Hi,
I'm new about SOEM and I want to test it using ROS kinetic in Ubuntu 16.04.
I followed the instructions regarding installation which I found at the link: https://github.com/mgruhler/soem
Unfortunately, installation doesn't work and the following errors are shown:
Errore:1 http://packages.ros.org/ros/ubuntu xenial/main amd64 ros-kinetic-soem amd64 1.3.0-0xenial-20180809-141333-0800
404 Not Found
E: Impossibile recuperare http://packages.ros.org/ros/ubuntu/pool/main/r/ros-kinetic-soem/ros-kinetic-soem_1.3.0-0xenial-20180809-141333-0800_amd64.deb 404
Does it exist another link to download it?
How can I solve this issue?
Thank you.

Possible Improvement: Using SOEM as Submodule

I was having trouble compiling this package in ROS to work with robotiq_ethercat, so I ended up starting from scratch with the base SOEM repo. I got it to compile with minimal work by creating a ROS package with the following files and SOEM as a submodule:

CMakeLists.txt
package.xml

Could this help resolve some of the other issues for this package? Any other feedback?

Getting error while integrating with ros node in C++

@mgruhler i have tried a lot to integrate soem library to our own ROS C++ node which will publish the topic... but i am unable to do, i have pointed my issue below. could you please help me out from this issue.if you need i can share my CMakeLists.txt file.

Errors     << ethercat_soem:make /home/atugv/Manpack_Drive_code/ethercat_motor/catkin_ws/logs/ethercat_soem/build.make.000.log
/home/atugv/Manpack_Drive_code/ethercat_motor/catkin_ws/src/ethercat-soem/src/final.cpp: In member function ‘void Epos_interaction::initialized_thread()’:
/home/atugv/Manpack_Drive_code/ethercat_motor/catkin_ws/src/ethercat-soem/src/final.cpp:595:73: warning: converting from ‘void (Epos_interaction::*)()’ to ‘void*’ [-Wpmf-conversions]
          osal_thread_create(&thread1, 128000, (void*)&Epos_interaction::ecatcheck, (void*) &ctime);
                                                                         ^
/home/atugv/Manpack_Drive_code/ethercat_motor/catkin_ws/src/ethercat-soem/src/final.cpp: In member function ‘void Epos_interaction::initialized_thread()’:
/home/atugv/Manpack_Drive_code/ethercat_motor/catkin_ws/src/ethercat-soem/src/final.cpp:595:73: warning: converting from ‘void (Epos_interaction::*)()’ to ‘void*’ [-Wpmf-conversions]
          osal_thread_create(&thread1, 128000, (void*)&Epos_interaction::ecatcheck, (void*) &ctime);
                                                                         ^
CMakeFiles/ethercat_soem.dir/src/final.cpp.o: In function `Epos_interaction::initialized_thread()':
final.cpp:(.text+0x5c13): undefined reference to `osal_thread_create'
collect2: error: ld returned 1 exit status
make[2]: *** [/home/atugv/Manpack_Drive_code/ethercat_motor/catkin_ws/devel/.private/ethercat_soem/lib/ethercat_soem/ethercat_soem] Error 1
make[1]: *** [CMakeFiles/ethercat_soem.dir/all] Error 2
make: *** [all] Error 2
cd /home/atugv/Manpack_Drive_code/ethercat_motor/catkin_ws/build/ethercat_soem; catkin build --get-env ethercat_soem | catkin env -si  /usr/bin/make --jobserver-fds=6,7 -j; cd -
...............................................................................
Failed     << ethercat_soem:make                   [ Exited with code 2 ]      
Failed    <<< ethercat_soem                        [ 4.7 seconds ]             
[build] Summary: 1 of 2 packages succeeded.                                    
[build]   Ignored:   None.                                                     
[build]   Warnings:  None.                                                     
[build]   Abandoned: None.                                                     
[build]   Failed:    1 packages failed.                                        
[build] Runtime: 6.3 seconds total.                                            
[build] Note: Workspace packages have changed, please re-source setup files to use them. 

Configure new EtherCAT-Device with ROS

Hello all :)

first of all, I'm sorry, if my question might be silly or trivial, but I'm pretty new to the world of EtherCAT.

I'm trying to controll a Festo CPX-FB37 bus node (https://www.festo.com/net/SupportPortal/Files/344605/CPX-FB37_2014-06_8029675g1.pdf) via ros, using SOEM.

I'm already having problems, when using the simple_test or slaveinfo. In both cases, the following error gets displayed:
Not all slaves reached safe operational state.
Slave 1 State=12 StatusCode= 1e : Invalid input configuration

Is there a kind of tutorial on how to start with SOEM? How can I connect new devices, which steps are done automatically, which have to be done manually?

Thanks a lot in advance,

Philipp

Attached you find the outputs of simple_test and slaveinfo.
simpleTest_Output.txt
slaveinfo_Output.txt

issue when soem run with rospackage

Hi,
I am currently using ros kinetic with ubuntu 16.04.
Thanks to your open source policy, I could download and run your example code slaveinfo.c.
When I testing with 7 slaves, it works well.
However, when I copy the code and generate a ros package, it behaves differently.
The different part happens in the following part of the code.

ec_statecheck(0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE * 3);
if (ec_slave[0].state != EC_STATE_SAFE_OP )                                                                                                                                                        
{
      printf("Not all slaves reached safe operational state.\n");                                                                                                                                     
      ec_readstate();                                                                                                                                                                                 
      for(i = 1; i<=ec_slavecount ; i++)                                                                                                                                                              
      {                                                                                                                                                                                               
           if(ec_slave[i].state != EC_STATE_SAFE_OP)                                                                                                                                                    
           {                                                                                                                                                                                            
               printf("Slave %d State=%2x StatusCode=%4x : %s\n",                                                                                                                                        
                         i, ec_slave[i].state, ec_slave[i].ALstatuscode, 
                         ec_ALstatuscode2string(ec_slave[i].ALstatuscode));                                                                                     
            }                                                                                                                                                                                            
      }                                                                                                                                                                                               
}

When I run the code with ros, ec_slave[0].state is not equals to EC_STATE_SAFE_OP, so it goes into if statement. The print out message looks like

Slave 1 State= 12 StatusCode = 1e : Invalid input configuration

or

Slave 1 State= 12 StatusCode = 1d : Invalid output configuration

One more thing I notice is that when I use small number of slaves (e.g. 3 instead of 7), ec_slave[0].state equals to EC_STATE_SAFE_OP.

However, without using ros package, ec_slave[0].state is always equals to EC_STATE_SAFE_OP.
Is there any problem when I try to bind soem to ros package?

Send and Receive processdata Twice.

Question

Hello.
I'm a beginner in E-cat. And thank you for developing SOEM.

I use 'simpletest' for initializing slaves and a 1000Hz thread for calculating and sending-receiving E-cat data.
In a normal situation, the data is only sent at 1000us timing. But in my graph, as the picture attached, it sends at 0ms and 1000us twice.

I'll attach my code and timing graph. Please help me. Thank you.

Platinum

#include <ros/ros.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <list>
#include <signal.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <cobalt/time.h>
#include <cobalt/unistd.h>
#include <cobalt/pthread.h>
#include <fcntl.h>   // File control definitions
#include <errno.h>   // Error number definitions
#include <termios.h> // POSIX terminal control definitions
#include "utility.h"
#include "ethercat.h"
using namespace std;
/*--------------------------Variables-----------------------------*/
#pragma region globalVars
// thread EtherCAT
#define EC_TIMEOUTMON 500
#define stack64k (64 * 1024)
#define NSEC_PER_SEC 1000000000
#define NUM_AXIS_TMP 1
pthread_t thread1; // ethercat
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
char IOmap[4096] = {0}; // for XMC E-Cat
int expectedWKC;
boolean needlf;
volatile int wkc;
boolean inOP;
//----------------------------------------------------
#pragma pack(1)
typedef struct DSTRUCT_OUT     // pdo
{                              // 1c12
    int32_t target_position;   // 0x607a
    int32_t target_velocity;   // 0x60ff
    int16_t max_torque;        // 0x6072
    uint16_t control_word;     // 0x6040 pdo domain 0x1604
    int16_t target_torque;     // 0x6071
    uint8_t mode_of_operation; // 0x6060
} out_ELMOt;
typedef struct DSTRUCT_IN           // pdo
{                                   // 1c13
    int32_t position_actual;        // 0x6064
    int32_t position_follow_err;    // 0x60f4
    int16_t torque_actual;          // 0x6077
    uint16_t status_word;           // 0x6041
    uint8_t mode_of_operation_disp; //
    int32_t velocity_actual;        // 0x606C
} in_ELMOt;
#pragma pack(4)
static out_ELMOt *out_ELMO[NUM_AXIS_TMP] = {NULL};
static in_ELMOt *in_ELMO[NUM_AXIS_TMP] = {NULL};
/*----------------------------------------------------------------*/
// EtherCAT
int ELMOsetupGOLD(uint16 slave);
int ELMOsetupPlatinum(uint16 slave);
bool simpletest(char *ifname);
void add_timespec(struct timespec *ts, int64 addtime);
void ec_sync(int reftime, int cycletime, int *offsettime);
//------------------------------------------------------------
void *ecatthread(void *ptr)
{
    struct timespec ts, tleft;
    int ht;
    int cycletime;
    int toff = 0;
    struct sched_param p;
    p.sched_priority = sched_get_priority_max(SCHED_FIFO);
    pthread_setschedparam(pthread_self(), SCHED_FIFO, &p);
    clock_gettime(CLOCK_MONOTONIC, &ts);
    ht = (ts.tv_nsec / 1000000) + 1; /* round to nearest ms */
    ts.tv_nsec = ht * 1000000;
    cycletime = *(int *)ptr * 1000; /* cycletime in ns */
    printf("create ecatthread! \n");
    printf("pthread priority = %d\n", p.sched_priority);
    ec_send_processdata();
    //-----------------------------------------------------------------------------------------
    while (1)
    {
        /* calculate next cycle start */
        add_timespec(&ts, cycletime + toff);
        std::cout << cycletime << " cycletime | toff " << toff << std::endl;
        /* wait to cycle start */
        clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, &tleft);
        ec_receive_processdata(EC_TIMEOUTRET);
        if (ec_slave[0].hasdc)
        {
            ec_sync(ec_DCtime, cycletime, &toff);
        }
        ec_send_processdata();
    }
}
// Main Thread
int main(int argc, char **argv)
{
    ros::init(argc, argv, "soem_node");
    ros::NodeHandle nh;
    char IOmap[1028] = {0};
    char ch = 0;
    int cnt = 0;
    int ctime = 1000; // us()
    char *eth_name = "rteth0";
    pthread_attr_t thread_attr;
    struct sched_param param;
    try
    {
        if (!simpletest(eth_name)) //
            throw "Failed initialization for master \n";
        if (ec_slavecount < NUM_AXIS_TMP)
            throw "Number of axis exceeded to ecat slaves \n";
        for (int i = 0; i < NUM_AXIS_TMP; i++)
        {
            out_ELMO[i] = (out_ELMOt *)ec_slave[i + 1].outputs;
            in_ELMO[i] = (in_ELMOt *)ec_slave[i + 1].inputs;
            out_ELMO[i]->target_position = in_ELMO[i]->position_actual;
        }
        pthread_attr_init(&thread_attr);
        pthread_create(&thread1, NULL, ecatthread, (void *)&ctime);
    }
    catch (const char *str)
    {
        perror(str);
        abort();
    }
    mlockall(MCL_CURRENT | MCL_FUTURE);
    while (ros::ok())
    {
        cnt = (cnt + 1) % 10;
        if (cnt == 0) //
        {
        }
        //========================================================
        usleep(50000); //
    }
    return 0;
}
/*--------------------------------------------------------------*/

int ELMOsetupGOLD(uint16 slave)
{
    int wkc = 0;
    uint32_t sdoObj = 0x00000000;
    uint8_t diable_bits = 0x00;
    uint8_t enable_bits = 0x01;
    uint16_t objAddr = 0x0000;
    uint16_t TxAddr = 0x1607;
    uint16_t RxAddr = 0x1A07;

    wkc += ec_SDOwrite(slave, TxAddr, 0x00, FALSE, sizeof(diable_bits), &(diable_bits), EC_TIMEOUTSAFE); // 0 disable
    sdoObj = 0x607A0020;                                                                                 // Target position
    wkc += ec_SDOwrite(slave, TxAddr, 0x01, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60FF0020; // Target velocity
    wkc += ec_SDOwrite(slave, TxAddr, 0x02, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60720010; // Max torque
    wkc += ec_SDOwrite(slave, TxAddr, 0x03, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60400010; // Controlword
    wkc += ec_SDOwrite(slave, TxAddr, 0x04, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60710010; // Target torque
    wkc += ec_SDOwrite(slave, TxAddr, 0x05, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60600008; // Modes of operation
    wkc += ec_SDOwrite(slave, TxAddr, 0x06, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    enable_bits = 0x06;
    wkc += ec_SDOwrite(slave, TxAddr, 0x00, FALSE, sizeof(enable_bits), &(enable_bits), EC_TIMEOUTSAFE);

    wkc += ec_SDOwrite(slave, RxAddr, 0x00, FALSE, sizeof(diable_bits), &(diable_bits), EC_TIMEOUTSAFE); // 0 disable
    sdoObj = 0x60640020;                                                                                 // Position actual value
    wkc += ec_SDOwrite(slave, RxAddr, 0x01, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60F40020; // Following error actual value
    wkc += ec_SDOwrite(slave, RxAddr, 0x02, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60770010; // Torque actual value
    wkc += ec_SDOwrite(slave, RxAddr, 0x03, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60410010; // Statusword
    wkc += ec_SDOwrite(slave, RxAddr, 0x04, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60610008; // Modes of operation display
    wkc += ec_SDOwrite(slave, RxAddr, 0x05, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x606C0020; // Additional position actual value
    wkc += ec_SDOwrite(slave, RxAddr, 0x06, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    enable_bits = 0x06;
    wkc += ec_SDOwrite(slave, RxAddr, 0x00, FALSE, sizeof(enable_bits), &(enable_bits), EC_TIMEOUTSAFE);

    // Tx PDO disable
    wkc += ec_SDOwrite(slave, 0x1c12, 0x00, FALSE, sizeof(diable_bits), &(diable_bits), EC_TIMEOUTSAFE);
    // Tx PDO dictionary mapping
    objAddr = TxAddr;
    wkc += ec_SDOwrite(slave, 0x1c12, 0x01, FALSE, sizeof(objAddr), &(objAddr), EC_TIMEOUTSAFE);

    // Rx PDO disable
    wkc += ec_SDOwrite(slave, 0x1c13, 0x00, FALSE, sizeof(diable_bits), &(diable_bits), EC_TIMEOUTSAFE);
    // Rx PDO dictionary mapping
    objAddr = RxAddr;
    wkc += ec_SDOwrite(slave, 0x1c13, 0x01, FALSE, sizeof(objAddr), &(objAddr), EC_TIMEOUTSAFE);

    enable_bits = 0x01;
    wkc += ec_SDOwrite(slave, 0x1c12, 0x00, FALSE, sizeof(enable_bits), &(enable_bits), EC_TIMEOUTSAFE);
    wkc += ec_SDOwrite(slave, 0x1c13, 0x00, FALSE, sizeof(enable_bits), &(enable_bits), EC_TIMEOUTSAFE);
    printf("wkc : %d\n", wkc);

    uint8 u8val = 8;                                                               // 8:position 9:velocity 10:torque
    ec_SDOwrite(slave, 0x6060, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM); //    cyclic sychronous position mode

    printf("supported drive modes: %d\n", u8val);
}

int ELMOsetupPlatinum(uint16 slave)
{
    int wkc = 0;
    uint8_t diable_bits = 0x00;
    uint8_t enable_bits = 0x01;
    uint16_t objAddr = 0x0000;
    uint32_t sdoObj = 0x00000000;

    wkc += ec_SDOwrite(slave, 0x1601, 0x00, FALSE, sizeof(diable_bits), &(diable_bits), EC_TIMEOUTSAFE); // 0 disable
    sdoObj = 0x607A0020;                                                                                 // Target position
    wkc += ec_SDOwrite(slave, 0x1601, 0x01, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60FF0020; // Target velocity
    wkc += ec_SDOwrite(slave, 0x1601, 0x02, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60720010; // Max torque
    wkc += ec_SDOwrite(slave, 0x1601, 0x03, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60400010; // Controlword
    wkc += ec_SDOwrite(slave, 0x1601, 0x04, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60710010; // Target torque
    wkc += ec_SDOwrite(slave, 0x1601, 0x05, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60600008; // Modes of operation
    wkc += ec_SDOwrite(slave, 0x1601, 0x06, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    enable_bits = 0x06; // nums of sdo // enable
    wkc += ec_SDOwrite(slave, 0x1601, 0x00, FALSE, sizeof(enable_bits), &(enable_bits), EC_TIMEOUTSAFE);

    wkc += ec_SDOwrite(slave, 0x1A01, 0x00, FALSE, sizeof(diable_bits), &(diable_bits), EC_TIMEOUTSAFE); // 0 disable
    sdoObj = 0x60640020;                                                                                 // Position actual value
    wkc += ec_SDOwrite(slave, 0x1A01, 0x01, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60F40020; // Following error actual value
    wkc += ec_SDOwrite(slave, 0x1A01, 0x02, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60770010; // Torque actual value
    wkc += ec_SDOwrite(slave, 0x1A01, 0x03, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60410010; // Statusword
    wkc += ec_SDOwrite(slave, 0x1A01, 0x04, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x60610008; // Modes of operation display
    wkc += ec_SDOwrite(slave, 0x1A01, 0x05, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    // sdoObj = 0x30CD02;//0x36E40220 ; // Additional position actual value 0x66110020; 0x30CD0220;
    // wkc += ec_SDOwrite(slave, 0x1A01, 0x06, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    sdoObj = 0x606C0020; // Velocity actual value
    wkc += ec_SDOwrite(slave, 0x1A01, 0x06, FALSE, sizeof(sdoObj), &(sdoObj), EC_TIMEOUTSAFE);
    enable_bits = 0x06; // nums of sdo // enable
    wkc += ec_SDOwrite(slave, 0x1A01, 0x00, FALSE, sizeof(enable_bits), &(enable_bits), EC_TIMEOUTSAFE);

    // Tx PDO disable
    wkc += ec_SDOwrite(slave, 0x1c12, 0x00, FALSE, sizeof(diable_bits), &(diable_bits), EC_TIMEOUTSAFE);
    // Tx PDO dictionary mapping
    objAddr = 0x1601;
    wkc += ec_SDOwrite(slave, 0x1c12, 0x01, FALSE, sizeof(objAddr), &(objAddr), EC_TIMEOUTSAFE);
    // Rx PDO disable
    wkc += ec_SDOwrite(slave, 0x1c13, 0x00, FALSE, sizeof(diable_bits), &(diable_bits), EC_TIMEOUTSAFE);
    // Rx PDO dictionary mapping
    objAddr = 0x1A01;
    wkc += ec_SDOwrite(slave, 0x1c13, 0x01, FALSE, sizeof(objAddr), &(objAddr), EC_TIMEOUTSAFE);

    enable_bits = 0x01;
    wkc += ec_SDOwrite(slave, 0x1c12, 0x00, FALSE, sizeof(enable_bits), &(enable_bits), EC_TIMEOUTSAFE);
    enable_bits = 0x01;
    wkc += ec_SDOwrite(slave, 0x1c13, 0x00, FALSE, sizeof(enable_bits), &(enable_bits), EC_TIMEOUTSAFE);
    printf("wkc : %d\n", wkc);

    uint8 u8val = 8;                                                               // 8:position 9:velocity 10:torque
    ec_SDOwrite(slave, 0x6060, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM); //    cyclic sychronous position mode

    printf("supported drive modes: %d\n", u8val);
}
bool simpletest(char *ifname)
{
    int i, j, oloop, iloop, chk, slc;
    u_int mmResult;
    needlf = FALSE;
    inOP = FALSE;
    printf("Starting simple test\n");
    /* initialise SOEM, bind socket to ifname */
    if (ec_init(ifname)) // Network Interface Card NIC
    {
        printf("ec_init on %s succeeded.\n", ifname);
        /* find and auto-config slaves */
        if (ec_config_init(FALSE) > 0) // Mailbox Setup, Slave -> PRE_OP Mode, All data read and configured are stored in a global array
        {
            printf("%d slaves found and configured.\n", ec_slavecount);
            if ((ec_slavecount >= 1)) // ec_slabecount : number of slaves found on the network
            {
                for (slc = 1; slc <= ec_slavecount; slc++) // ec_slave[0] : reserved for the master
                {
                    printf("Name: %s EEpMan: %d eep_id: %d configadr: %d aliasadr: %d State %d\n\r ",
                           ec_slave[slc].name, ec_slave[slc].eep_man, ec_slave[slc].eep_id, ec_slave[slc].configadr, ec_slave[slc].aliasadr, ec_slave[slc].state);
                    if (ec_slave[slc].eep_man == 154 && ec_slave[slc].eep_id == 198948) // ELMO GOLD's man & id
                    {
                        printf("slave%d -> ELMO GOLD detected\n", slc - 1);
                        ec_slave[slc].PO2SOconfig = &ELMOsetupGOLD;
                    }
                    else if (ec_slave[slc].eep_man == 154 && ec_slave[slc].eep_id == 17825794) // ELMO PLATINUM's man & id
                    {
                        printf("slave%d -> ELMO PLATINUM detected\n", slc - 1);
                        ec_slave[slc].PO2SOconfig = &ELMOsetupPlatinum;
                        ec_slave[slc].blockLRW = 1; // Platinum does not support LRW function
                        ec_slave[0].blockLRW++;     // Platinum does not support LRW function
                    }
                    else if (ec_slave[slc].eep_man == 3138 && ec_slave[slc].eep_id == 0) // XMC's man & id
                    {
                        printf("slave%d -> XMC detected\n", slc - 1);
                    }
                }
            }
            ec_config_map(&IOmap); // 32 Map all PDOs from slaves to IOmap with Outputs / Inputs in sequential order(legacy SOEM way).
            ec_configdc();

            printf("Slaves mapped, state to SAFE_OP.\n");
            /* wait for all slaves to reach SAFE_OP state , When the mapping is done
            SOEM requests slaves to enter SAFE_OP.*/
            ec_statecheck(0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE * 4);
            // Operation Mode
            oloop = ec_slave[0].Obytes;
            if ((oloop == 0) && (ec_slave[0].Obits > 0))
                oloop = 1;
            if (oloop > 8)
                oloop = 8;
            iloop = ec_slave[0].Ibytes;
            if ((iloop == 0) && (ec_slave[0].Ibits > 0))
                iloop = 1;
            if (iloop > 8)
                iloop = 8;
            printf("segments : %d : %d %d %d %d\n", ec_group[0].nsegments,
                   ec_group[0].IOsegment[0], ec_group[0].IOsegment[1], ec_group[0].IOsegment[2],
                   ec_group[0].IOsegment[3]);
            printf("Request operational state for all slaves\n");
            expectedWKC = (ec_group[0].outputsWKC * 2) + ec_group[0].inputsWKC;
            printf("Calculated workcounter %d\n", expectedWKC);
            ec_slave[0].state = EC_STATE_OPERATIONAL;
            ///////////////////////////////// 0 or 1
            /* send one valid process data to make outputs in slaves happy*/
            ec_send_processdata();
            ec_receive_processdata(EC_TIMEOUTRET);
            /* request OP state for all slaves */
            ec_writestate(0); ///////////////////////////////// 0 or 1
            chk = 200;
            /* wait for all slaves to reach OP state */
            do
            {
                ec_send_processdata();
                ec_receive_processdata(EC_TIMEOUTRET);
                ec_statecheck(0, EC_STATE_OPERATIONAL, 50000);
            } while (chk-- && (ec_slave[0].state != EC_STATE_OPERATIONAL));
            //////////////////////////////////////////////////
            //////////////////////////////////////////////////
            if (ec_slave[0].state == EC_STATE_OPERATIONAL)
            {
                printf("Operational state reached for all slaves.\n");
                inOP = TRUE;
                /* cyclic loop, reads data from RT thread */
                int PCL = 30; // Processdata Cycle Loop
                for (i = 1; i <= PCL; i++)
                {
                    ec_send_processdata();
                    wkc = ec_receive_processdata(EC_TIMEOUTRET);
                    if (wkc >= expectedWKC)
                    {
                        printf("Processdata cycle %4d, WKC %d , O:", i, wkc);
                        for (j = 0; j < oloop; j++)
                        {
                            printf(" %2.2x", *(ec_slave[0].outputs + j));
                        }
                        printf(" I:");
                        for (j = 0; j < iloop; j++)
                        {
                            printf(" %2.2x", *(ec_slave[0].inputs + j));
                        }
                        printf("\nOutput Byte: %d / input Byte: %d\n", oloop, iloop);
                        // printf(" T:%lld\r", ec_DCtime);
                        needlf = TRUE;
                    }
                    osal_usleep(50000);
                }
                inOP = FALSE;
            }
            else
            {
                printf("Not all slaves reached operational state.\n");
                ec_readstate();
                for (i = 1; i <= ec_slavecount; i++)
                {
                    if (ec_slave[i].state != EC_STATE_OPERATIONAL)
                    {
                        printf("Slave %d State=0x%2.2x StatusCode=0x%4.4x : %s\n",
                               i, ec_slave[i].state, ec_slave[i].ALstatuscode,
                               ec_ALstatuscode2string(ec_slave[i].ALstatuscode));
                    }
                }
                return false;
            }
            printf("\nRequest init state for all slaves\n");
            ec_slave[0].state = EC_STATE_INIT;
            /* request INIT state for all slaves */
            ec_writestate(0);
        }
        else
        {
            printf("No slaves found!\n");
            return false;
        }
        // printf("End simple test\n");
    }
    else
    {
        printf("No socket connection on %s\nExcecute as root\n", ifname);
        return false;
    }
    return true;
}
void add_timespec(struct timespec *ts, int64 addtime)
{
    int64 sec, nsec;
    nsec = addtime % NSEC_PER_SEC;
    sec = (addtime - nsec) / NSEC_PER_SEC;
    ts->tv_sec += sec;
    ts->tv_nsec += nsec;
    if (ts->tv_nsec > NSEC_PER_SEC)
    {
        nsec = ts->tv_nsec % NSEC_PER_SEC;
        ts->tv_sec += (ts->tv_nsec - nsec) / NSEC_PER_SEC;
        ts->tv_nsec = nsec;
    }
}
/* PI calculation to get linux time synced to DC time */
void ec_sync(int reftime, int cycletime, int *offsettime)
{
    static int integral = 0;
    static int delta;
    /* set linux sync point 50us later than DC sync, just as example */
    delta = (reftime - 50000) % cycletime;
    if (delta > (cycletime / 2))
    {
        delta = delta - cycletime;
    }
    if (delta > 0)
    {
        integral++;
    }
    if (delta < 0)
    {
        integral--;
    }
    *offsettime = -(delta / 100) - (integral / 20); // 100 20
    // gl_delta = delta;
}

soem_ros_Twice_error_code.pdf

ROS Distro (please check as appropriate):

  • [O] Kinetic
  • Melodic
  • Noetic
  • Other: ...

SOEM ROS Wrapper version (please check and complete as appropriate):

  • [O ] from apt: 1.4.1
  • [] from source: 1.?.?
  • Commit SHA:

Hardware setup
Describe exactly which type of hardware setup you have (i.e. which ethercat slaves)

  • Numbers of ELMO twitter Platinum Motor Controller

Example of a ROS node using SOEM library

Dear Matthias,

I have to implement a connection between MoveIt and an ethercat board to control a manipulator.
I am new to ethercat and I found your library very useful. I do not know, however, how to use the library. Do you have perhaps an example you can share?
A ROS node that communicate simple doubles or structures to the ehtercat board.

Thank you in advance!
Elena

how to install soem on xenomai

To compile for linux:

go to project directory

source ./setup.sh linux

make all

when I input make all in terminal

there are serveal error as fellow

--- Compiling ebox.c
ebox.c: In function ‘eboxtest’:
ebox.c:196:26: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 3 has type ‘int64’ [-Wformat]
ebox.c: In function ‘ecatthread’:
ebox.c:284:8: warning: variable ‘rc’ set but not used [-Wunused-but-set-variable]
ebox.c: In function ‘main’:
ebox.c:348:8: warning: variable ‘iret1’ set but not used [-Wunused-but-set-variable]
--- Linking ebox
/usr/bin/ld: cannot find -lsoem
collect2: ld returned 1 exit status
make[3]: *** [ebox] Error 1
make[2]: *** [subdirs] Error 2
make[1]: *** [linux] Error 2
make: *** [test] Error 2

SDO comunication problem

Goodmorning to all,
I'm using a Pc with Ubuntu as Ethercat master and an ethercat slave which uses a LAN9252.
The slave is connected to a pc with window which is used to load the SOES program and once the software has been loaded, it remains connected in debug mode for checking the variables. I have a problem with the SDO communication. When i run, on my master, the slaveinfo.c from command window with the optional parameter -sdo i obtain the following results:

SOEM (Simple Open EtherCAT Master)
Slaveinfo
Starting slaveinfo
ec_init on enp2s0 succeeded.
1 slaves found and configured.
Calculated workcounter 3

Slave:1
Name: SSC_Device
Output size: 1024bits
Input size: 1024bits
State: 4
Delay: 0[ns]
Has DC: 1
DCParentport:0
Activeports:1.0.0.0
Configured address: 1001
Man: 00000afc ID: 00010000 Rev: 00000001
SM0 A:1000 L: 128 F:00010026 Type:1
SM1 A:1200 L: 128 F:00010022 Type:2
SM2 A:1400 L: 128 F:00010064 Type:3
SM3 A:1600 L: 128 F:00010020 Type:4
FMMU0 Ls:00000000 Ll: 128 Lsb:0 Leb:7 Ps:1400 Psb:0 Ty:02 Act:01
FMMU1 Ls:00000080 Ll: 128 Lsb:0 Leb:7 Ps:1600 Psb:0 Ty:01 Act:01
FMMUfunc 0:1 1:2 2:0 3:0
MBX length wr: 128 rd: 128 MBX protocols : 04
CoE details: 0d FoE details: 00 EoE details: 00 SoE details: 00
Ebus current: 0[mA]
only LRD/LWR:0
ec_slave[cnt].mbx_proto: 04
printSDO: 1
End slaveinfo, close socket
End program

The problem is that i don't see the CoE object dictionary. I checked the exchange of packages between master and slave, i saw that the master sent a request to obtain the informations but my slave don't receive them. From the slave debugger I checked the SM_status (Sync manager status SM1 0x080d) that is the register that indicate if the mailmox is full and can be read and i saw that this register doesn't change value and then my slave doesn't pass into read SDO mode. Someone know what is the problem? the eeprom memory need to have a particular structure to allow a correct SDO comunication? Or maybe is only a slave software problem?

Thanks.

How to download older soem versions

Hello,

we are following with great interest this SOEM ROS package.
Before starting to use v.1.4.0 we still need to finish some tests with the previous version 1.3.0.
We need to install it on a new pc but we suppose that the "Installation" instructions are referred to the newer version (v1.4.0).
I'm sorry for my trivial question, but how can we download and install v.1.3.0 with a "sudo apt-get ..." command?
Waiting for your response, thank you.
Best regards.

Issue when exporting a new package with SOEM

Hi,

I am trying to set up a new package (pkg_a) that depends on SOEM. I got that working properly. The problem appears when I use this new package with another package (pkg_b), I have to add ${soem_INCLUDE_DIRS}/soem in the include_directories of pkg_b again.

I am looking to find a solution that this is taken care of in pkg_a. Since I cannot add ${soem_INCLUDE_DIRS}/soem in catkin_package INCLUDE_DIRS of pkg_a (I would get a non-package include path error from catkin_lint), I am curious if there is a way to do this.

Thanks!

SOEM PDO Transmission

Hi,
I've installed SOEM and I'm using it with ROS Kinetic on Ubuntu 16.04.
I've created a C++ ROS node and inside it I've reproduced the example "simple test" contained in the SOEM package to communicate to a DELTA servo drive.
The communication link between ROS node and servo started correctly, in fact I see the change of the state of the slave after each specific command.
When I try to launch "ec_send_processdata()", the servo drive give me an alarm message in which it told me that it is in operational state but the data receveid are wrong.
Servo drive configuration needs to receive a RxPDO containing 2 object ( a uint16 "control word" 6040 and a int32 "target position" 607A) but I don't understand how to do to send them to the slave.
How can I solve it?
Which variables must be setted?
Waiting for you response, thank you.

SOEM for ROS 2.0

Hi,

is a future release of SOEM for ROS 2 (Crystal or Dashing Diademata) expected?
I'm getting familiar with ROS 2 and I think that a SOEM release for it it would be useful.
Thank you.

Is this command typo?

Question

sudo apt install ros-<DISTRO>-ethercat-ethercat_grant

This command were not worked on ROS noetic and ROS melodic

Maybe the correct command is

sudo apt install ros-<DISTRO>-ethercat-grant

It's right?

ROS Distro (please check as appropriate):

  • Kinetic
  • Melodic
  • Noetic
  • Other: ...

SOEM ROS Wrapper version (please check and complete as appropriate):

  • from apt: 1.?.?
  • from source: 1.4.1003
  • Commit SHA:

Hardware setup
Master PC

  • Intel i9 12900K
  • DDR4 32GB
  • No external GPU

Slave EtherCAT board

  • NDA

Release for ROS Jade?

Package robotiq_ethercat depends on this package so cannot currently be installed on Jade from debian. Could someone release this package again? Thanks!

Improve header handling

SOEM expects headers in a flat directory hierarchy (i.e. <headerpath>). In contrast, ROS, by convention, expects headers in a subdirectory which is named after the ROS package (i.e. <pkg>/<headerpath>).

Currently, with the intention of not having to adapt any soem headers, but still somehow stick to the ROS convention, the soem headers are installed to soem/*.h.

This leads to the problem, that any ROS code building against soem runs into problems with finding headers.
A work around to overcome this is shown in the Usage section of the README.md.

This should be cleaned up such that we don't break existing code but without having to adapt any soem sources.

This has been reported multiple time, e.g. in #4 and #8

Sending and receiving different types of PDOs

Hello,

I manage a 6 axes robot in ROS through EtherCAT using the soem package.
The "ROS Master EtherCAT PC" is a laptop in which are installed Ubuntu 18.04 LTS and ROS Melodic.
Each joint has an EtherCAT driver developed by us.
We developed a ROS node which acts as Master EtherCAT using soem library.
This node was developed based on simple_test.c example.
Each Joint communicates with the "ROS Master EtherCAT" using:

  • 1 RXPDO
  • 1 TXPDO
    which are transmitted and received from ROS Master each ms.
    The commands used are the following:

ec_send_processdata();
auto wkc = ec_receive_processdata( EC_TIMEOUTAW );

Now we need to implement a further change. We need that "ROS Master EtherCAT PC" sends/receives each ms:

  • 1 RXPDO for "standard data"
  • 1 RXPDO for "special data"
  • 1 TXPDO for "standard data"
  • 1 TXPDO for "special data"

"Standard data" and "special data" need to be managed with separately in different PDOs.

I don't know how implement this feature in our code, because I suppose that the only two commands listed above couldn't be enough for transmitting 2 RXPDOs and 2 TXPDOs separately at the same time.
Anyone can help us?
Waiting for a response, I thank you.
Best regards.

Can't find headers when using SOEM from source

Describe the bug
When using SOEM 1.4 from APT, I don't have any problems. But when using SOEM 1.4 from source, I get a missing headers error. I have tried finding SOEM directly or via catkin as component, both fail. It only happens on the melodic branch. kinetic branch works fine.
I was able to pin point the issue to commit 9b40aa1.

To Reproduce
Steps to reproduce the behavior:

  1. Clone https://github.com/tue-robotics/ethercat_interface.git in catkin workspace and checkout the fix/ci_2020 branch
  2. Clone soem in catkin workspace and checkout melodic branch
  3. Install ros-$ROS_DISTRO-hardware-interface ros-$ROS_DISTRO-controller-manager ros-$ROS_DISTRO-roscpp
  4. Compile with 'catkin build'
  5. See error (https://travis-ci.com/github/tue-robotics/ethercat_interface/jobs/367803096#L745)
Errors     << ethercat_interface:make /home/amigo/ros/melodic/system/logs/ethercat_interface/build.make.000.log
In file included from /home/amigo/ros/melodic/system/src/ethercat_interface/src/drivers/./el4xxx.h:3:0,
                 from /home/amigo/ros/melodic/system/src/ethercat_interface/src/drivers/el4xxx.cpp:1:
/home/amigo/ros/melodic/system/src/ethercat_interface/include/ethercat_interface/driver.h:10:10: fatal error: soem/ethercattype.h: No such file or directory
 #include "soem/ethercattype.h"
          ^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
In file included from /home/amigo/ros/melodic/system/src/ethercat_interface/src/drivers/./el5101.h:3:0,
                 from /home/amigo/ros/melodic/system/src/ethercat_interface/src/drivers/el5101.cpp:1:
/home/amigo/ros/melodic/system/src/ethercat_interface/include/ethercat_interface/driver.h:10:10: fatal error: soem/ethercattype.h: No such file or directory
 #include "soem/ethercattype.h"
          ^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/ethercat_interface.dir/src/drivers/el4xxx.cpp.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[2]: *** [CMakeFiles/ethercat_interface.dir/src/drivers/el5101.cpp.o] Error 1
make[1]: *** [CMakeFiles/ethercat_interface.dir/all] Error 2
make: *** [all] Error 2
cd /home/amigo/ros/melodic/system/build/ethercat_interface; catkin build --get-env ethercat_interface | catkin env -si  /usr/bin/make --jobserver-fds=6,7 -j; cd -

Expected behavior
Compiling ;)

ROS Distro (please check as appropriate):

  • Kinetic
  • Lunar
  • Melodic

SOEM ROS Wrapper version (please check as appropriate):

  • from apt: 1.3.0
  • from apt: 1.4.0
  • from source: 1.3.0
  • from source: 1.4.0
  • Commit SHA:

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3)

## Use C++ 11
add_compile_options(-std=c++11)

project(ethercat_interface)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS
  roscpp
  soem
  hardware_interface
  controller_manager)

## Declare a catkin package
catkin_package(CATKIN_DEPENDS roscpp
               INCLUDE_DIRS include
               LIBRARIES ${PROJECT_NAME})

include_directories(
  include
  ${catkin_INCLUDE_DIRS}
)

# Ethercat interface library
add_library(${PROJECT_NAME}
    ${HEADERS}

    # Driver implementations
    src/drivers/el200x.h
    src/drivers/el4xxx.cpp
    src/drivers/el5101.cpp
    src/drivers/tuees030.cpp

    # IO implementations
    src/io/analog_input.h
    src/io/analog_output.h
    src/io/digital_input.h
    src/io/digital_output.h
    src/io/encoder.h

    src/interface.cpp
    src/driver.cpp
    src/io.cpp
    src/input.cpp
    src/output.cpp
)
target_link_libraries(${PROJECT_NAME} ${catkin_LIBRARIES})

# #### Test executables ####
# Ethercat interface node
add_executable(ethercat_interface_node test/ethercat_interface_node.cpp)
target_link_libraries(ethercat_interface_node ${PROJECT_NAME} ${catkin_LIBRARIES})

# List interfaces
add_executable(list_interfaces test/list_interfaces.cpp)
target_link_libraries(list_interfaces ${PROJECT_NAME} ${catkin_LIBRARIES})

# Test AI
add_executable(test_ai test/test_ai.cpp)
target_link_libraries(test_ai ${PROJECT_NAME} ${catkin_LIBRARIES})

# Test AO
add_executable(test_ao test/test_ao.cpp)
target_link_libraries(test_ao ${PROJECT_NAME} ${catkin_LIBRARIES})

# Test DO
add_executable(test_do test/test_do.cpp)
target_link_libraries(test_do ${PROJECT_NAME} ${catkin_LIBRARIES})

# Test encoder
add_executable(test_encoder test/test_encoder.cpp)
target_link_libraries(test_encoder ${PROJECT_NAME} ${catkin_LIBRARIES})

Hardware setup
Just compiling issues at the moment.

P.S.
You are doing a good job since you have taken over this repo.

Giving up maintainership - any volunteers?

Hi all,

I'm finding less and less time (which has been very limited to begin with) mainting the ROS wrapper around the SOEM library, and thus, I'll not be able to support here much longer.
If anyone is interested, I'll be happy to transfer ownership of this repo to another individual or an org who will take over.

Mentioning a few of the people that have been active on issues / PRs around here: @smits @meyerj @etorta @ValATG @mictas @MatthijsBurgh @cplasberg @edhage

FSOE SOEM management

Hello,

we use this "SOEM ROS package" to manage our actuators (ROS Melodic - Ubuntu 18.04 LTS). It works.
For a future project we need to manage Safety funtions using FSOE. A commercial device will act as "Master FSOE" and "EtherCAT Slave". We suppose that "SOEM ROS" should be able to manage "EtherCAT" data and "FSOE" data using different PDOs.
Is the current "SOEM ROS" package able to manage FSOE data?
If not, is someone developing it?

I found the following page in github:

https://github.com/rtlabs-com/fsoe-soem-demo

Waiting for a response, thank you.
Best regards.

compile the soem library

when I make the makefile in soem directory, there is a error as fellow:

make: *** No rule to make target simple_test.o', needed bysimple_test'. Stop.

what should I do ? thank for you help。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.