Skip to content

Commit 983bc62

Browse files
committed
Finished the passthrough controller
The number of joints in the controller is variable and received from the hardware interface. (It is not variable there though). The internal action server uses the action type FollowJointTrajectory. Both goal time tolerance and goal position tolerance are checked upon completion of trajectory, and feedback is sent to the user. The integration test has also been updated to test the controller.
1 parent b459bd1 commit 983bc62

File tree

13 files changed

+434
-187
lines changed

13 files changed

+434
-187
lines changed

examples/example_movej.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929

3030
import rclpy
3131
from builtin_interfaces.msg import Duration
32-
from control_msgs.action import JointTrajectory
32+
from control_msgs.action import FollowJointTrajectory
33+
from control_msgs.msg import JointTolerance
3334

3435
from rclpy.action import ActionClient
3536
from rclpy.node import Node
@@ -100,7 +101,7 @@ def init_robot(self):
100101
self.jtc_action_client = waitForAction(
101102
self.node,
102103
"/passthrough_trajectory_controller/forward_joint_trajectory",
103-
JointTrajectory,
104+
FollowJointTrajectory,
104105
)
105106
time.sleep(2)
106107

@@ -127,14 +128,23 @@ def send_trajectory(self, waypts, time_vec):
127128
point.time_from_start = time_vec[i]
128129
joint_trajectory.points.append(point)
129130

131+
tolerances = [JointTolerance(position=0.001) for i in range(6)]
132+
time_tolerance = Duration()
133+
time_tolerance.sec = 1
130134
# Sending trajectory goal
131135
goal_response = self.call_action(
132-
self.jtc_action_client, JointTrajectory.Goal(trajectory=joint_trajectory)
136+
self.jtc_action_client,
137+
FollowJointTrajectory.Goal(
138+
trajectory=joint_trajectory,
139+
goal_tolerance=tolerances,
140+
goal_time_tolerance=time_tolerance,
141+
),
133142
)
134143
if goal_response.accepted is False:
135144
raise Exception("trajectory was not accepted")
136145

137146
# Verify execution
147+
138148
result = self.get_result(self.jtc_action_client, goal_response)
139149
return result
140150

@@ -217,7 +227,7 @@ def load_passthrough_controller(self):
217227
self.jtc_action_client = waitForAction(
218228
self.node,
219229
"/passthrough_trajectory_controller/forward_joint_trajectory",
220-
JointTrajectory,
230+
FollowJointTrajectory,
221231
)
222232
time.sleep(2)
223233

@@ -242,9 +252,9 @@ def switch_controller(self, active, inactive):
242252

243253
# The following list are arbitrary joint positions, change according to your own needs
244254
waypts = [
245-
[-1, -2.5998, -1.004, -2.676, -0.992, -1.5406],
246-
[-0.1, -2.6998, -1.104, -2.676, -0.992, -1.5406],
247-
[-1, -2.5998, -1.004, -2.676, -0.992, -1.5406],
255+
[-1.58, -1.692, -1.4311, -0.0174, 1.5882, 0.0349],
256+
[-3, -1.692, -1.4311, -0.0174, 1.5882, 0.0349],
257+
[-1.58, -1.692, -1.4311, -0.0174, 1.5882, 0.0349],
248258
]
249259
time_vec = [Duration(sec=4, nanosec=0), Duration(sec=8, nanosec=0), Duration(sec=12, nanosec=0)]
250260

examples/example_spline.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
import rclpy
3131
from builtin_interfaces.msg import Duration
32-
from control_msgs.action import JointTrajectory
32+
from control_msgs.action import FollowJointTrajectory
3333

3434
from rclpy.action import ActionClient
3535
from rclpy.node import Node
@@ -100,7 +100,7 @@ def init_robot(self):
100100
self.jtc_action_client = waitForAction(
101101
self.node,
102102
"/passthrough_trajectory_controller/forward_joint_trajectory",
103-
JointTrajectory,
103+
FollowJointTrajectory,
104104
)
105105
time.sleep(2)
106106

@@ -131,7 +131,7 @@ def send_trajectory(self, waypts, time_vec, vels, accels):
131131

132132
# Sending trajectory goal
133133
goal_response = self.call_action(
134-
self.jtc_action_client, JointTrajectory.Goal(trajectory=joint_trajectory)
134+
self.jtc_action_client, FollowJointTrajectory.Goal(trajectory=joint_trajectory)
135135
)
136136
if goal_response.accepted is False:
137137
raise Exception("trajectory was not accepted")
@@ -219,7 +219,7 @@ def load_passthrough_controller(self):
219219
self.jtc_action_client = waitForAction(
220220
self.node,
221221
"/passthrough_trajectory_controller/forward_joint_trajectory",
222-
JointTrajectory,
222+
FollowJointTrajectory,
223223
)
224224
time.sleep(2)
225225

examples/examples.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
import rclpy
3131
from builtin_interfaces.msg import Duration
32-
from control_msgs.action import JointTrajectory
32+
from control_msgs.action import FollowJointTrajectory
3333

3434
from rclpy.action import ActionClient
3535
from rclpy.node import Node
@@ -123,7 +123,7 @@ def send_trajectory(self, waypts, time_vec):
123123

124124
# Sending trajectory goal
125125
goal_response = self.call_action(
126-
self.jtc_action_client, JointTrajectory.Goal(trajectory=joint_trajectory)
126+
self.jtc_action_client, FollowJointTrajectory.Goal(trajectory=joint_trajectory)
127127
)
128128
if goal_response.accepted is False:
129129
raise Exception("trajectory was not accepted")
@@ -211,7 +211,7 @@ def load_passthrough_controller(self):
211211
self.jtc_action_client = waitForAction(
212212
self.node,
213213
"/passthrough_trajectory_controller/forward_joint_trajectory",
214-
JointTrajectory,
214+
FollowJointTrajectory,
215215
)
216216
time.sleep(2)
217217

examples/load_switch_controller_example.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
import rclpy
3131
from builtin_interfaces.msg import Duration
32-
from control_msgs.action import JointTrajectory
32+
from control_msgs.action import FollowJointTrajectory
3333

3434
from rclpy.action import ActionClient
3535
from rclpy.node import Node
@@ -123,7 +123,7 @@ def send_trajectory(self, waypts, time_vec):
123123

124124
# Sending trajectory goal
125125
goal_response = self.call_action(
126-
self.jtc_action_client, JointTrajectory.Goal(trajectory=joint_trajectory)
126+
self.jtc_action_client, FollowJointTrajectory.Goal(trajectory=joint_trajectory)
127127
)
128128
if goal_response.accepted is False:
129129
raise Exception("trajectory was not accepted")
@@ -211,7 +211,7 @@ def load_passthrough_controller(self):
211211
self.jtc_action_client = waitForAction(
212212
self.node,
213213
"/passthrough_trajectory_controller/forward_joint_trajectory",
214-
JointTrajectory,
214+
FollowJointTrajectory,
215215
)
216216
time.sleep(2)
217217

ur_controllers/include/ur_controllers/passthrough_trajectory_controller.hpp

Lines changed: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
#include "rclcpp_action/create_server.hpp"
5252
#include "rclcpp/rclcpp.hpp"
5353
#include "rclcpp_action/server_goal_handle.hpp"
54+
#include "rclcpp/time.hpp"
55+
#include "rclcpp/duration.hpp"
5456

5557
#include "trajectory_msgs/msg/joint_trajectory.hpp"
5658
#include "trajectory_msgs/msg/joint_trajectory_point.hpp"
@@ -63,15 +65,36 @@ namespace ur_controllers
6365
{
6466
enum CommandInterfaces
6567
{
68+
/* The PASSTHROUGH_TRAJECTORY_TRANSFER_STATE value is used to keep track of which stage the transfer is in.
69+
0.0: No trajectory to forward, the controller is idling and ready to receive a new trajectory.
70+
1.0: The controller has received and accepted a new trajecotry. When the state is 1.0, the controller will write a
71+
point to the hardware interface.
72+
2.0: The hardware interface will read the point written from the controller. The state will switch between 1.0
73+
and 2.0 until all points have been read by the hardware interface.
74+
3.0: The hardware interface has read all the points, and will now write all the points to the robot driver.
75+
4.0: The robot is moving through the trajectory.
76+
5.0: The robot finished executing the trajectory. */
6677
PASSTHROUGH_TRAJECTORY_TRANSFER_STATE = 0,
67-
PASSTHROUGH_POINT_WRITTEN = 1,
68-
PASSTHROUGH_TRAJECTORY_NUMBER_OF_POINTS = 2,
69-
PASSTHROUGH_TRAJECTORY_CANCEL = 3,
70-
PASSTHROUGH_TRAJECTORY_DIMENSIONS = 4,
71-
PASSTHROUGH_TRAJECTORY_POSITIONS_ = 5,
72-
PASSTHROUGH_TRAJECTORY_VELOCITIES_ = 11,
73-
PASSTHROUGH_TRAJECTORY_ACCELERATIONS_ = 17,
74-
PASSTHROUGH_TRAJECTORY_TIME_FROM_START = 23
78+
/* The PASSTHROUGH_TRAJECTORY_CANCEL value is used to indicate whether the trajectory has been cancelled from the
79+
* hardware interface.*/
80+
PASSTHROUGH_TRAJECTORY_CANCEL = 1,
81+
/* The PASSTHROUGH_TRAJECTORY_DIMENSIONS is used to indicate what combination of joint positions, velocities and
82+
* accelerations the trajectory consists of, see check_dimensions() for a description of what the values mean. */
83+
PASSTHROUGH_TRAJECTORY_DIMENSIONS = 2,
84+
/* Arrays to hold the values of a point. */
85+
PASSTHROUGH_TRAJECTORY_POSITIONS_ = 3,
86+
PASSTHROUGH_TRAJECTORY_VELOCITIES_ = 9,
87+
PASSTHROUGH_TRAJECTORY_ACCELERATIONS_ = 15,
88+
PASSTHROUGH_TRAJECTORY_TIME_FROM_START = 21
89+
};
90+
91+
enum StateInterfaces
92+
{
93+
/* State interface 0 - 17 are joint state interfaces*/
94+
95+
SPEED_SCALING_FACTOR = 18,
96+
NUMBER_OF_JOINTS = 19,
97+
CONTROLLER_RUNNING = 20
7598
};
7699

77100
class PassthroughTrajectoryController : public controller_interface::ControllerInterface
@@ -93,32 +116,64 @@ class PassthroughTrajectoryController : public controller_interface::ControllerI
93116
controller_interface::return_type update(const rclcpp::Time& time, const rclcpp::Duration& period) override;
94117

95118
private:
119+
/* Start an action server with an action called: /passthrough_trajectory_controller/forward_joint_trajectory. */
96120
void start_action_server(void);
97121

122+
void end_goal();
123+
124+
bool check_goal_tolerance();
125+
98126
std::shared_ptr<passthrough_trajectory_controller::ParamListener> passthrough_param_listener_;
99127
passthrough_trajectory_controller::Params passthrough_params_;
100128

101-
rclcpp_action::Server<control_msgs::action::JointTrajectory>::SharedPtr send_trajectory_action_server_;
129+
rclcpp_action::Server<control_msgs::action::FollowJointTrajectory>::SharedPtr send_trajectory_action_server_;
102130

103-
rclcpp_action::GoalResponse goal_received_callback(
104-
const rclcpp_action::GoalUUID& uuid, std::shared_ptr<const control_msgs::action::JointTrajectory::Goal> goal);
131+
rclcpp_action::GoalResponse
132+
goal_received_callback(const rclcpp_action::GoalUUID& uuid,
133+
std::shared_ptr<const control_msgs::action::FollowJointTrajectory::Goal> goal);
105134

106135
rclcpp_action::CancelResponse goal_cancelled_callback(
107-
const std::shared_ptr<rclcpp_action::ServerGoalHandle<control_msgs::action::JointTrajectory>> goal_handle);
136+
const std::shared_ptr<rclcpp_action::ServerGoalHandle<control_msgs::action::FollowJointTrajectory>> goal_handle);
108137

109138
void goal_accepted_callback(
110-
const std::shared_ptr<rclcpp_action::ServerGoalHandle<control_msgs::action::JointTrajectory>> goal_handle);
139+
const std::shared_ptr<rclcpp_action::ServerGoalHandle<control_msgs::action::FollowJointTrajectory>> goal_handle);
140+
141+
void execute(
142+
const std::shared_ptr<rclcpp_action::ServerGoalHandle<control_msgs::action::FollowJointTrajectory>> goal_handle);
143+
144+
std::vector<std::string> joint_names_;
145+
std::vector<std::string> state_interface_types_;
146+
147+
std::vector<std::reference_wrapper<hardware_interface::LoanedStateInterface>> joint_position_state_interface_;
148+
std::vector<std::reference_wrapper<hardware_interface::LoanedStateInterface>> joint_velocity_state_interface_;
149+
150+
/*
151+
If there are values in the velocities and accelerations vectors, they should have as many elements as there are
152+
joints, and all be the same size.
153+
The return value indicates what combination of joint positions, velocities and accelerations is present;
154+
0: The trajectory is invalid, and will be rejected.
155+
1: Only positions are defined for the trajectory.
156+
2: Positions and velocities are defined for the trajectory.
157+
3: Positions and accelerations are defined for the trajectory.
158+
4: Both positions, velocities and accelerations are defined for the trajectory.
159+
*/
160+
int check_dimensions(std::shared_ptr<const control_msgs::action::FollowJointTrajectory::Goal> goal);
111161

112-
void
113-
execute(const std::shared_ptr<rclcpp_action::ServerGoalHandle<control_msgs::action::JointTrajectory>> goal_handle);
114-
int check_dimensions(std::shared_ptr<const control_msgs::action::JointTrajectory::Goal> goal);
115162
trajectory_msgs::msg::JointTrajectory active_joint_traj_;
163+
std::vector<control_msgs::msg::JointTolerance> path_tolerance_;
164+
std::vector<control_msgs::msg::JointTolerance> goal_tolerance_;
165+
rclcpp::Duration goal_time_tolerance_ = rclcpp::Duration::from_nanoseconds(0);
166+
116167
uint32_t current_point_;
117168
bool trajectory_active_;
118-
uint64_t active_trajectory_elapsed_time_;
119-
uint64_t max_trajectory_time_;
169+
uint64_t period_ns;
170+
uint64_t last_time_ns;
171+
uint64_t now_ns;
172+
double active_trajectory_elapsed_time_;
173+
double max_trajectory_time_;
120174
double scaling_factor_;
121-
std::shared_ptr<rclcpp_action::ServerGoalHandle<control_msgs::action::JointTrajectory>> current_handle;
175+
uint32_t number_of_joints_;
176+
std::shared_ptr<rclcpp_action::ServerGoalHandle<control_msgs::action::FollowJointTrajectory>> active_goal_;
122177
};
123178
} // namespace ur_controllers
124179
#endif // UR_CONTROLLERS__PASSTHROUGH_TRAJECTORY_CONTROLLER_HPP_

0 commit comments

Comments
 (0)