Rosanswers logo

Hy there,

i am trying to implement a controller for a igus-dryve motor drive on ros-kinetic. I am using canopen and the ros_canopen package to communicate over a sysWORXX USBCanmodule 1 with the igus-dryve and have everything setup properly (stepper motor in closed loop beeing controllable over the igus webinterface and set to accept CANopen communication which is wired correctly).

Calling rosservice call /joint/driver/init works fine, axis gets reset, return is True and the ros-controllers are loading.

Here comes my issue:

  1. How do I actually move/command the motor? By setting the actual values of the Object by rosservice call /joint/driver/setObject ? Or does the canopen_motor_node take care of all the communication in order to drive the motor? In that case how do I forward a positioning command? I tried to call rostopic pub /lifter_ros/lifter_joint_position_controller/command std_msgs/Float64 "data: 1.0" but no reactions.
  2. Additionally i was thinking about if ros_control is really needed in my use-case? igus-dryve already performs a closed-loop control so isn`t ros_control a layer ontop and too much?

Please find attached my controller config:

  type: joint_state_controller/JointStateController
  publish_rate: 50
  type: position_controllers/JointPositionController
  joint: lifter_joint
  required_drive_mode: 1

And my node layer:

name: igus-dryve 

  eds_pkg: lifter_ros
  eds_file: "config/igus_dryve_D1.eds" #electrical desciption file of igus dryve

  #the following scaling is due to 16bit value range limitation of velocity command in vl mode (2)
  #vel_to_device: "rint(rad2deg(vel)*250)"
  #dcf_overlay: # "ObjectID": "ParameterValue" (both as strings)
  #  "604Csub1": "1" # vl dimension factor numerator
  #  "604Csub2": "24000" # vl dimension factor denominator
#defaults: # optional, all defaults can be overwritten per node
  # canopen_chain_node settings ..
  motor_allocator: canopen::Motor402::Allocator # select allocator for motor layer
#motor_layer: #settings passed to motor layer (plugin-specific)
  switching_state: 5 # (Operation_Enable), state for mode switching
  pos_to_device: "rint(rad2deg(pos)*1000)" # rad -> mdeg
  pos_from_device: "deg2rad(obj6064)/1000" # actual position [mdeg] -> rad
  vel_to_device: "rint(rad2deg(vel)*1000)" # rad/s -> mdeg/s
  vel_from_device: "deg2rad(obj606C)/1000" # actual velocity [mdeg/s] -> rad/s
  eff_to_device: "rint(eff)" # just round to integer
  eff_from_device: "0" # unset
    id: 2

and my launchfile:

?xml version="1.0"?>
  <!-- send urdf to param server -->
  <param name="robot_description" command="cat '$(find lifter_ros)/urdf/lifter.urdf'" />
  <!-- robot state publisher -->
  <node ns="lifter_ros" pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher">
      <param name="publish_frequency" type="double" value="50.0" />
      <param name="tf_prefix" type="string" value="" />
      <!--remap from="joint_states" to="/arm/joint_states"/-->

  <node ns="lifter_ros" name="driver" pkg="canopen_motor_node" type="canopen_motor_node" output="screen" clear_params="true" launch-prefix="">
     <rosparam command="load" file="$(find lifter_ros)/config/CANopen_layer.yaml" />
     <rosparam command="load" file="$(find lifter_ros)/config/node_layer.yaml" />
  <!-- controllers -->
  <rosparam ns="lifter_ros" command="load" file="$(find lifter_ros)/config/dryve_controller.yaml" />
 <!-- start_controllers -->
  <node ns="lifter_ros" name="lifter_ros_controller_spawner" pkg="controller_manager" type="controller_manager" args="spawn joint_state_controller" respawn="false" output="screen"/>

I would highly appreciate your help!


EDIT Regarding the controllers: The output says the controller is loaded succesfully, this is also visible when calling the status of the controllers with rosservice call /lifter_ros/controller_manager/list_controllers ---> running. Terminal shows following:

[ INFO] [1563888510.915229736]: Initializing XXX
[ INFO] [1563888510.915637125]: Current state: 1 device error: system:0 internal_error: 0 (OK)
[ INFO] [1563888510.915873954]: Current state: 2 device error: system:0 internal_error: 0 (OK)
Loaded joint_state_controller
Loaded lifter_joint_position_controller
Started ['joint_state_controller'] successfully
Started ['lifter_joint_position_controller'] successfully
[lifter_ros/controller-4] process has finished cleanly

On first startup when calling /driver/init following error message appears: afterwards it works always as described before.

Did not receive a response message
[ERROR] [1563892238.035051383]: /home/fhi/flexbin/flexbin_ws/src/ros_canopen/canopen_master/src/sdo.cpp(429): Throw in function void canopen::SDOClient::transmitAndWait(const canopen::ObjectDict::Entry&, const canopen::String&, canopen::String*)
Dynamic exception type: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<canopen::TimeoutException> >
std::exception::what: SDO
[canopen::tag_objectdict_key*] = 6061sub0

Originally posted by mtROS on ROS Answers with karma: 92 on 2019-07-17

Post score: 0


1 Answer 1


Rosanswers logo

How do I actually move/command the motor?

You have to publish to the command topic of the lifter_joint_position_controller (just like in your example). If it does not work, please double-check that the controller was actually started. It looks like you have copied the parameters from the Schunk LWA4 packages, perhaps IGUS needs different settings.

Additionally i was thinking about if ros_control is really needed in my use-case?

ros_control provides a generic controller interface, so all users can choose their controllers.

igus-dryve already performs a closed-loop control so isn`t ros_control a layer ontop and too much?

position_controllers/JointPositionController just forwards the command, i.e., it connects CANopen and ROS.

Originally posted by Mathias Lüdtke with karma: 1596 on 2019-07-19

This answer was ACCEPTED on the original site

Post score: 0

Original comments

Comment by mtROS on 2019-07-23:
Thank you for your answer!

It looks like you have copied the parameters from the Schunk LWA4 packages, perhaps IGUS needs different settings.

Do you mean the settings of the canopen_motor_node? I am a bit confused of what i would have to actually change...?

I had a look at different examples that use a dcf overlay but have not idea where to start.

Please see Edit for controller up check.

Comment by Mathias Lüdtke on 2019-07-23:
I was referring to https://github.com/ipa320/schunk_robots/blob/indigo_dev/schunk_lwa4p/config/arm_driver.yaml#L7. According to your config, if you command "1.0" [rad], the device will receive the target 57296 [millidegrees]. You should be able to find this in the candump as well.

As a starting point you should first check your unit settings and verify it by reading the joint states in different positions.

Comment by mtROS on 2019-07-23:
I can't find any message in the candump beeing send when calling /command...

When i rostopic echo /joint_states I just recieve zeros and i can't actually move the motor by hand. header: seq: 38525 stamp: secs: 1563890889 nsecs: 267513294 frame_id: '' name: ['lifter_joint'] position: [0.0] velocity: [0.0] effort: [0.0]

Could you please check my edit above? Seems that the controllers are working properly, arn't they?

Comment by Mathias Lüdtke on 2019-07-23:
The controllers seem to work, but they just forward message, so it is hard to make them fail.

It looks like your unit settings are wrong: your device is a linear actuator, but your config is for rotary devices. Better check the manual.

You can move the drive to a known location (with the IGUS tool) and check the the position afterwards.

Comment by mtROS on 2019-07-23:
Thank you for your support!

  1. Changed the unit settings to rotary.

  2. I moved the motor with the igus-tool and was then calling via /get_object the object 6064 "Position actual value"---> the rostopic echo of the joint states then updates the value.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.