Hello,
A brief list of what you would need to do:
Implement a hardware interface to move your robot. You can follow this tutorial and also this. You will likely have to expose a PositionJointInterface for the joints of your robot, since you mentioned that you can send desired positions. The interface will "live" in a package of its own.
Make sure that you can move the robot using simple controllers, such as position_controllers/JointGroupPositionController
. If controllers are working properly, you should be able to move the robot simply by publishing into a topic. If you can do this, 95% of the work is done.
Load and start a Joint Trajectory Controller. It will start a FollowJointTrajectory action server. This is the "connection" used by MoveIt to send commands to your real robot.
Follow this MoveIt tutorial. It shows how to "instruct" MoveGroup to locate the controller you created. Just to be clear, in the MoveIt controllers.yaml
file you have to give the full name, including namespaces for the controller. As an example, if your controller is named trajectory_controller
, but runs in the namespace my_robot
, then the parameter name
will be my_robot/trajectory_controller
.
Do not launch demo.launch
from your MoveIt configuration file. Instead, make a copy of that and change it so that trajectory execution is allowed. As far as I remember, you will have to change the parameters given to the joint_state_publisher (so that it listens to the correct topic) and change the argument fake_execution to false when including the main MoveGroup launch file. I do not remember if you have to do other changes, sorry. In any case, that should be all! :)
Originally posted by ffusco with karma: 271 on 2019-08-23
This answer was ACCEPTED on the original site
Post score: 1
Original comments
Comment by schlitz0hr on 2019-09-03:
Thank you for your help! I think one problem were the namespaces, but now it works! Nevertheless I am still a bit confused wether the joint trajectory position controller is the right controller. The real robot state is displayed in moveit, so when I move the robot by hand, it is also moving in the visualisation, but the execution does not match the planned trajectory, especially if there are any Interruptions. So if I say go to position 200 and the sensor only senses 180, there will not be any correction made to the goal position?
Comment by ffusco on 2019-09-03:
Sorry, I did not fully get your question, would you mind rephrasing it? In particular I do not get what you mean with "I say go to position 200 and the sensor only senses 180": do you mean something like "what happens if I plan, then move the robot manually without MoveIt, and finally ask to execute the path that was planned in the beginning?".
In any case, think to the trajectory controller as a simple "bridge" between MoveIt and your bot: you ask MoveIt to plan from point A to B. The plan creates intermediate steps C1, C2, etc, each with an associated time T1, T2, ... . You then ask the controller to execute the motion, which will make sure that the robot properly follows in space and time the given trajectory, so that, eg, at time T3 it will say to the robot to be in C3. Note that it also makes a smooth interpolation, so that when the time is between, eg, T1 and T2, the robot will go to a position that is somewhere in the middle of C1 and C2.
Comment by ffusco on 2019-09-03:
I hope the last part helps you understanding better why the trajectory controller might be the right controller. If you feel like it is not the case, you can of course use other strategies!
Comment by wootoodoo on 2020-06-09:
Hi ffusco, I'm going through a similar issue with the OP, except that now I have managed to set up my hardware_interface node to communicate with my Arduino through the rosserial, which accepts a joint_position_controller.
I have also managed to set up my Moveit-Gazebo connection, which is communicating through a FollowJointTrajectoryAction and JointTrajectoryController, and I can get Moveit to control the robot arm in RViz and Gazebo.
Is there any way of allowing hardware_interface to communicate directly with the FollowJointTrajectoryAction? Is this an issue with namespaces, or do I have to implement an intermediate controller between joint_position_controller and joint_trajectory_controller?
Sorry if this is a silly question, I'm quite new to ROS :S
Comment by ffusco on 2020-06-09:
I have never used arduino with ros, so I do not know exactly how you can set it up. However, in general, if you use ros control most of the times you define and load multiple controllers at once, starting only those that are actually required at a specific time. As an example, it is rather common to load a position controller for one or more joints and a joint trajectory controller at the same time. Then, you just need to switch between the two as needed. Most likely, you'll start the position controller(s) and command the joints "manually" via the proper topic, then switch to the trajectory controller and let, e.g., MoveIt plan and forward the execution request. This is the general working principle, but perhaps your setup is different. Referring to your question "Is there any way of allowing hardware_interface to communicate directly with the FollowJointTrajectoryAction?", the answer should be yes.
Comment by ffusco on 2020-06-09:
Actually, it should be the other way around: it's the hardware that "spawns" the action server, and MoveIt should simply "connect" to it :)
I don't know if this answers you, since I don't know your full setup. If you need further details, feel free to comment below. Just give me few more details about the ros connections you have and I'll try to clarify if possible ;)
Comment by wootoodoo on 2020-06-09:
Thanks for the quick response!
I've got a feeling the issue is in how I spawn my controllers, here is my controller.yaml that I spawn in the Moveit package:
controller_manager_ns: controller_manager
controller_list:
name: six_dof_arm/six_dof_arm_joint_controller
action_ns: follow_joint_trajectory
type: FollowJointTrajectory
default: true
joints:
- shoulder_pan_joint
- shoulder_pitch_joint
- elbow_pitch_joint
- wrist_pitch_joint
- gripper_roll_joint
name: six_dof_arm/gripper_controller
action_ns: follow_joint_trajectory
type: FollowJointTrajectory
default: true
joints:
- finger_joint1
- finger_joint2
Comment by wootoodoo on 2020-06-09:
Here is the controller.yaml that I spawn at the hardware_interface package
six_dof_arm:
controller:
state:
type: joint_state_controller/JointStateController
publish_rate: 50
position:
shoulder_pan_joint:
type: position_controllers/JointPositionController
joint: shoulder_pan_joint
pid: {p: 10.0, i: 0.0, d: 1.0}
shoulder_pitch_joint:
type: position_controllers/JointPositionController
joint: shoulder_pitch_joint
pid: {p: 10.0, i: 0.0, d: 1.0}
elbow_pitch_joint:
type: position_controllers/JointPositionController
joint: elbow_pitch_joint
pid: {p: 10.0, i: 0.0, d: 1.0}
wrist_pitch_joint:
type: position_controllers/JointPositionController
joint: wrist_pitch_joint
pid: {p: 10.0, i: 0.0, d: 1.0}
gripper_roll_joint:
type: position_controllers/JointPositionController
joint: gripper_roll_joint
pid: {p: 10.0, i: 0.0, d:
Comment by wootoodoo on 2020-06-09:
Right now both packages just kind of exist in the same /six_dof_arm namespace and the controllers just don't communicate with each other.
My setup is move_group -> JointTrajectoryAction -> Hardware_interface -> Rosserial -> Arduino
The JointTrajectoryAction also connects to Gazebo separately.
Comment by ffusco on 2020-06-15:
I think the problem is that you are using a set of position controllers for your robot, not a joint trajectory controller. As far as I know, this will not allow you to properly connect MoveGroup and ROS Control. Based on what I see in your (ROS control) controller.yaml, you could add something like:
arm_trajectory_controller:
type: position_controllers/JointTrajectoryController
joints:
- shoulder_pan_joint
- shoulder_pitch_joint
- etc.
Note that this is just a simplified configuration, have a look at the link above to see what other parameters you can set to properly configure the controller!
Now, in the "other" controller.yaml (the MoveIt one), change the name of the controller to six_dof_arm/arm_trajectory_controller
.
I hope this fixes the problem!
PS: sorry for the late reply, but I missed the notification of your comment...
Comment by wootoodoo on 2020-06-18:
I think i have solved it following your advice! One additional mistake I had made was that my hardware_interface node was also running in the wrong namespace so the controller_spawner also could not spawn the trajectory collectors correctly, the correct namespace was supposed to be "six_dof_arm".
Is it impossible to connect the trajectory controller to both gazebo and hardware_interface at the same time?
Comment by ffusco on 2020-06-18:
Glad of hearing it!
Regarding the connection with Gazebo, I think you are trying something a little strange. As I understand, when you say "hardware_interface" you mean the hardware interface that is connected to the Arduino. As a simulator, Gazebo effectively replaces your real robot, and thus you should either use the simulation or your real hardware, but not both at the same time. In addition, keep in mind that the JointTrajectoryController spawns an Action Server, and the rule is that there cannot be two servers with the same name in the same namespace. Thus, I believe that it is not only discouraged but also impossible - unless you do something very specific.
That said, if for Gazebo you are using the ROS control plugin, note that the same controllers configuration file can be re-used for both, meaning that you can effectively use the same JointTrajectoryController configuration regardless the type of robot, real or simulated.
Comment by ffusco on 2020-06-18:
I believe this to be one of the coolest advantages of ROS control: you can switch between simulations and real platforms almost without changing a single portion of your code!
Comment by sophvk on 2022-07-21:
Hello, I'm trying to do something similar. I have a Universal robot with additional actuators, and want moveit to plan and send trajectories to both the robot and the actuator. I kinda have parts solved, I have a JointTrajectoryController that receives the goal when moveit plans the motion. But I am stuck in the next step. I understand that the Hardware interface should be the one to tell the actuator to move, nut haven't found one single example of how this is done for a trajectory. Should my hardware interface contain an action client to send the goal to the actuator? Thank you!