Skip to content

Commit 8e8ff0f

Browse files
committed
The tests are OK for the in: pos, vel and out: pos
1 parent f11b05e commit 8e8ff0f

File tree

5 files changed

+183
-104
lines changed

5 files changed

+183
-104
lines changed

joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa
137137
// matches i-th index in joint_names_
138138
std::vector<std::vector<std::reference_wrapper<hardware_interface::LoanedCommandInterface>>>
139139
joint_command_interface_;
140-
std::vector<std::vector<std::reference_wrapper<hardware_interface::LoanedCommandInterface>>>
140+
std::vector<std::vector<std::reference_wrapper<hardware_interface::LoanedStateInterface>>>
141141
joint_state_interface_;
142142

143143
/* If used a command given the desired state and state error using velocity feedforward term plus a corrective PID term is used
@@ -156,7 +156,9 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa
156156
realtime_tools::RealtimeBuffer<std::shared_ptr<trajectory_msgs::msg::JointTrajectory>>
157157
traj_msg_external_point_ptr_;
158158

159-
bool is_halted = false;
159+
// The controller should be in halted state after creation otherwise memory corruption
160+
// TODO(anyone): Is the variable relevant, since we are using lifecycle?
161+
bool is_halted_ = true;
160162

161163
using ControllerStateMsg = control_msgs::msg::JointTrajectoryControllerState;
162164
using StatePublisher = realtime_tools::RealtimePublisher<ControllerStateMsg>;

joint_trajectory_controller/src/joint_trajectory_controller.cpp

Lines changed: 102 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ JointTrajectoryController::init(const std::string & controller_name)
6767
node_->declare_parameter<std::vector<std::string>>("joints", joint_names_);
6868
node_->declare_parameter<std::vector<std::string>>(
6969
"command_interfaces", command_interface_types_);
70-
node_->declare_parameter<std::vector<std::string>>("state_interfaces", command_interface_types_);
70+
node_->declare_parameter<std::vector<std::string>>("state_interfaces", state_interface_types_);
7171
node_->declare_parameter<double>("state_publish_rate", 50.0);
7272
node_->declare_parameter<double>("action_monitor_rate", 20.0);
7373
node_->declare_parameter<bool>("allow_partial_joints_goal", allow_partial_joints_goal_);
@@ -109,9 +109,9 @@ controller_interface::return_type
109109
JointTrajectoryController::update()
110110
{
111111
if (get_current_state().id() == State::PRIMARY_STATE_INACTIVE) {
112-
if (!is_halted) {
112+
if (!is_halted_) {
113113
halt();
114-
is_halted = true;
114+
is_halted_ = true;
115115
}
116116
return controller_interface::return_type::SUCCESS;
117117
}
@@ -147,39 +147,41 @@ JointTrajectoryController::update()
147147
resize_joint_trajectory_point(state_current, joint_num);
148148

149149
auto check_if_interface_type_exist =
150-
[](const std::vector<std::string> & interface_type_list, const std::string & interface_type)
151-
{
152-
return std::find(interface_type_list.begin(), interface_type_list.end(), interface_type) !=
153-
interface_type_list.end();
154-
};
150+
[](const std::vector<std::string> & interface_type_list, const std::string & interface_type)
151+
{
152+
return std::find(interface_type_list.begin(), interface_type_list.end(), interface_type) !=
153+
interface_type_list.end();
154+
};
155155
auto assign_point_from_interface = [&, joint_num](
156156
std::vector<double> & trajectory_point_interface, const auto & joint_inteface)
157-
{
158-
for (auto index = 0ul; index < joint_num; ++index) {
159-
trajectory_point_interface[index] = joint_inteface[index].get().get_value();
160-
}
161-
};
157+
{
158+
for (auto index = 0ul; index < joint_num; ++index) {
159+
trajectory_point_interface[index] = joint_inteface[index].get().get_value();
160+
}
161+
};
162162
// TODO(anyone): can I here also use const on joint_interface since the reference_wrapper is not
163163
// changed, but its value only?
164164
auto assign_interface_from_point = [&, joint_num](
165165
auto & joint_inteface, const std::vector<double> & trajectory_point_interface)
166-
{
167-
for (auto index = 0ul; index < joint_num; ++index) {
168-
joint_inteface[index].get().set_value(trajectory_point_interface[index]);
169-
}
170-
};
166+
{
167+
for (auto index = 0ul; index < joint_num; ++index) {
168+
joint_inteface[index].get().set_value(trajectory_point_interface[index]);
169+
}
170+
};
171171

172172
// current state update
173173
state_current.time_from_start.set__sec(0);
174174

175175
// Assign values from the hardware
176176
// Position states always exist
177177
assign_point_from_interface(state_current.positions, joint_state_interface_[0]);
178-
// velocitiy and acceleration states are optional
178+
// velocity and acceleration states are optional
179179
if (check_if_interface_type_exist(state_interface_types_, hardware_interface::HW_IF_VELOCITY)) {
180180
assign_point_from_interface(state_current.velocities, joint_state_interface_[1]);
181181
// Acceleration is used only in combination with velocity
182-
if (check_if_interface_type_exist(state_interface_types_, hardware_interface::HW_IF_ACCELERATION))
182+
if (check_if_interface_type_exist(
183+
state_interface_types_,
184+
hardware_interface::HW_IF_ACCELERATION))
183185
{
184186
assign_point_from_interface(state_current.accelerations, joint_state_interface_[2]);
185187
} else {
@@ -189,6 +191,7 @@ JointTrajectoryController::update()
189191
} else {
190192
// Make empty so the property is ignored during interpolation
191193
state_current.velocities.clear();
194+
state_current.accelerations.clear();
192195
}
193196

194197
// currently carrying out a trajectory
@@ -214,18 +217,21 @@ JointTrajectoryController::update()
214217

215218
// set values for next hardware write()
216219
if (check_if_interface_type_exist(
217-
command_interface_types_, hardware_interface::HW_IF_POSITION)) {
220+
command_interface_types_, hardware_interface::HW_IF_POSITION))
221+
{
218222
assign_interface_from_point(joint_command_interface_[0], state_desired.positions);
219223
}
220224
if (check_if_interface_type_exist(
221-
command_interface_types_, hardware_interface::HW_IF_VELOCITY)) {
225+
command_interface_types_, hardware_interface::HW_IF_VELOCITY))
226+
{
222227
assign_interface_from_point(joint_command_interface_[1], state_desired.velocities);
223228
}
224229
if (check_if_interface_type_exist(
225-
command_interface_types_, hardware_interface::HW_IF_ACCELERATION)) {
230+
command_interface_types_, hardware_interface::HW_IF_ACCELERATION))
231+
{
226232
assign_interface_from_point(joint_command_interface_[2], state_desired.accelerations);
227233
}
228-
// TODO: Add here "if using_closed_loop_hw_interface_adapter (see ROS')
234+
// TODO(anyone): Add here "if using_closed_loop_hw_interface_adapter (see ROS')
229235
// if (check_if_interface_type_exist(
230236
// command_interface_types_, hardware_interface::HW_IF_EFFORT)) {
231237
// assign_interface_from_point(joint_command_interface_[3], state_desired.effort);
@@ -321,14 +327,16 @@ JointTrajectoryController::on_configure(const rclcpp_lifecycle::State &)
321327
if (!reset()) {
322328
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
323329
}
330+
// The controller should be in halted state after creation otherwise memory corruption
331+
is_halted_ = true;
324332

325333
if (joint_names_.empty()) {
326334
RCLCPP_WARN(logger, "'joints' parameter is empty.");
327335
}
328336

329337
// Specialized, child controllers set interfaces before calling configure function.
330338
if (command_interface_types_.empty()) {
331-
state_interface_types_ = node_->get_parameter("command_interfaces").as_string_array();
339+
command_interface_types_ = node_->get_parameter("command_interfaces").as_string_array();
332340
}
333341

334342
if (command_interface_types_.empty()) {
@@ -342,10 +350,7 @@ JointTrajectoryController::on_configure(const rclcpp_lifecycle::State &)
342350
for (const auto & interface : command_interface_types_) {
343351
auto it = std::find(
344352
allowed_interface_types_.begin(), allowed_interface_types_.end(), interface);
345-
if (it != allowed_interface_types_.end()) {
346-
auto index = std::distance(allowed_interface_types_.begin(), it);
347-
joint_command_interface_[index].resize(joint_names_.size());
348-
} else {
353+
if (it == allowed_interface_types_.end()) {
349354
RCLCPP_ERROR(logger, "Command interface type '" + interface + "' not allowed!");
350355
return CallbackReturn::ERROR;
351356
}
@@ -356,22 +361,26 @@ JointTrajectoryController::on_configure(const rclcpp_lifecycle::State &)
356361
// 2. velocity
357362
// 2. position [velocity, [acceleration]]
358363
auto check_if_interface_type_exist =
359-
[](const std::vector<std::string> & interface_type_list, const std::string & interface_type)
360-
{
361-
return std::find(interface_type_list.begin(), interface_type_list.end(), interface_type) !=
362-
interface_type_list.end();
363-
};
364+
[](const std::vector<std::string> & interface_type_list, const std::string & interface_type)
365+
{
366+
return std::find(interface_type_list.begin(), interface_type_list.end(), interface_type) !=
367+
interface_type_list.end();
368+
};
364369

365370
// effort can't be combined with other interfaces
366-
if (check_if_interface_type_exist(command_interface_types_, hardware_interface::HW_IF_EFFORT)
367-
&& command_interface_types_.size() == 1) {
368-
// TODO(anyone): This flag is not used for now
369-
// There should be PID-approach used as in ROS1:
370-
// https://github.com/ros-controls/ros_controllers/blob/noetic-devel/joint_trajectory_controller/include/joint_trajectory_controller/hardware_interface_adapter.h#L283
371-
use_closed_loop_pid_adapter = true;
372-
} else {
373-
RCLCPP_ERROR(logger, "'effort' command interface has to be used alone.");
374-
return CallbackReturn::ERROR;
371+
if (check_if_interface_type_exist(command_interface_types_, hardware_interface::HW_IF_EFFORT)) {
372+
if (command_interface_types_.size() == 1) {
373+
// TODO(anyone): This flag is not used for now
374+
// There should be PID-approach used as in ROS1:
375+
// https://github.com/ros-controls/ros_controllers/blob/noetic-devel/joint_trajectory_controller/include/joint_trajectory_controller/hardware_interface_adapter.h#L283
376+
use_closed_loop_pid_adapter = true;
377+
// TODO(anyone): remove the next two lines when implemented
378+
RCLCPP_ERROR(logger, "using 'effort' command interface alone is not yet implemented yet.");
379+
return CallbackReturn::ERROR;
380+
} else {
381+
RCLCPP_ERROR(logger, "'effort' command interface has to be used alone.");
382+
return CallbackReturn::ERROR;
383+
}
375384
}
376385

377386
if (check_if_interface_type_exist(
@@ -380,18 +389,25 @@ JointTrajectoryController::on_configure(const rclcpp_lifecycle::State &)
380389
// if there is only velocity then use also PID adapter
381390
if (command_interface_types_.size() == 1) {
382391
use_closed_loop_pid_adapter = true;
383-
// if velocity interface can be used without position if multiple defined
392+
// TODO(anyone): remove this when implemented
393+
RCLCPP_ERROR(logger, "using 'velocity' command interface alone is not yet implemented yet.");
394+
return CallbackReturn::ERROR;
395+
// if velocity interface can be used without position if multiple defined
384396
} else if (!check_if_interface_type_exist(
385-
command_interface_types_, hardware_interface::HW_IF_POSITION)) {
386-
RCLCPP_ERROR(logger, "'velocity' command interface can be used either alone or 'position' "
387-
"interface has to be present.");
397+
command_interface_types_, hardware_interface::HW_IF_POSITION))
398+
{
399+
RCLCPP_ERROR(
400+
logger, "'velocity' command interface can be used either alone or 'position' "
401+
"interface has to be present.");
388402
return CallbackReturn::ERROR;
389403
}
390-
// invalid: acceleration is defined and no velocity
404+
// invalid: acceleration is defined and no velocity
391405
} else if (check_if_interface_type_exist(
392-
command_interface_types_, hardware_interface::HW_IF_ACCELERATION)) {
393-
RCLCPP_ERROR(logger, "'acceleration' command interface can only be used if 'velocity' and "
394-
"'position' interfaces are present");
406+
command_interface_types_, hardware_interface::HW_IF_ACCELERATION))
407+
{
408+
RCLCPP_ERROR(
409+
logger, "'acceleration' command interface can only be used if 'velocity' and "
410+
"'position' interfaces are present");
395411
return CallbackReturn::ERROR;
396412
}
397413

@@ -417,27 +433,28 @@ JointTrajectoryController::on_configure(const rclcpp_lifecycle::State &)
417433
for (const auto & interface : state_interface_types_) {
418434
auto it = std::find(
419435
allowed_interface_types_.begin(), allowed_interface_types_.end(), interface);
420-
if (it != allowed_interface_types_.end()) {
421-
auto index = std::distance(allowed_interface_types_.begin(), it);
422-
joint_state_interface_[index].resize(joint_names_.size());
423-
} else {
436+
if (it == allowed_interface_types_.end()) {
424437
RCLCPP_ERROR(logger, "State interface type '" + interface + "' not allowed!");
425438
return CallbackReturn::ERROR;
426439
}
427440
}
428441

429442
if (check_if_interface_type_exist(state_interface_types_, hardware_interface::HW_IF_VELOCITY)) {
430-
if (!check_if_interface_type_exist(state_interface_types_, hardware_interface::HW_IF_POSITION))
443+
if (!check_if_interface_type_exist(
444+
state_interface_types_,
445+
hardware_interface::HW_IF_POSITION))
431446
{
432-
RCLCPP_ERROR(logger, "'velocity' state interface can be used if 'position' interface "
433-
"is present.");
447+
RCLCPP_ERROR(
448+
logger, "'velocity' state interface can be used if 'position' interface "
449+
"is present.");
434450
return CallbackReturn::ERROR;
435451
}
436452
} else if (check_if_interface_type_exist(
437453
state_interface_types_, hardware_interface::HW_IF_ACCELERATION))
438454
{
439-
RCLCPP_ERROR(logger, "'acceleration' state interface can be used if 'position' and 'velocity' "
440-
"interfaces are present.");
455+
RCLCPP_ERROR(
456+
logger, "'acceleration' state interface can be used if 'position' and 'velocity' "
457+
"interfaces are present.");
441458
return CallbackReturn::ERROR;
442459
}
443460

@@ -471,9 +488,8 @@ JointTrajectoryController::on_configure(const rclcpp_lifecycle::State &)
471488
// State publisher
472489
const double state_publish_rate =
473490
node_->get_parameter("state_publish_rate").get_value<double>();
474-
RCLCPP_INFO_STREAM(
475-
logger, "Controller state will be published at " <<
476-
state_publish_rate << "Hz.");
491+
RCLCPP_INFO(
492+
logger, "Controller state will be published at %f.2 Hz.", state_publish_rate);
477493
if (state_publish_rate > 0.0) {
478494
state_publisher_period_ =
479495
rclcpp::Duration::from_seconds(1.0 / state_publish_rate);
@@ -510,9 +526,8 @@ JointTrajectoryController::on_configure(const rclcpp_lifecycle::State &)
510526
const double action_monitor_rate = node_->get_parameter("action_monitor_rate")
511527
.get_value<double>();
512528

513-
RCLCPP_INFO_STREAM(
514-
logger, "Action status changes will be monitored at " <<
515-
action_monitor_rate << "Hz.");
529+
RCLCPP_INFO(
530+
logger, "Action status changes will be monitored at %f.2 Hz.", action_monitor_rate);
516531
action_monitor_period_ = rclcpp::Duration::from_seconds(1.0 / action_monitor_rate);
517532

518533
using namespace std::placeholders;
@@ -559,14 +574,25 @@ JointTrajectoryController::on_activate(const rclcpp_lifecycle::State &)
559574
allowed_interface_types_.begin(), allowed_interface_types_.end(), interface);
560575
auto index = std::distance(allowed_interface_types_.begin(), it);
561576
if (!get_ordered_interfaces(
562-
command_interfaces_, joint_names_, interface, joint_command_interface_[index])) {
563-
RCLCPP_ERROR(node_->get_logger(), "Expected %u %s command interfaces, got %u",
577+
command_interfaces_, joint_names_, interface, joint_command_interface_[index]))
578+
{
579+
RCLCPP_ERROR(
580+
node_->get_logger(), "Expected %u %s command interfaces, got %u",
564581
joint_names_.size(), interface.c_str(), joint_command_interface_[index].size());
582+
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
565583
}
584+
}
585+
for (const auto & interface : state_interface_types_) {
586+
auto it = std::find(
587+
allowed_interface_types_.begin(), allowed_interface_types_.end(), interface);
588+
auto index = std::distance(allowed_interface_types_.begin(), it);
566589
if (!get_ordered_interfaces(
567-
state_interfaces_, joint_names_, interface, joint_state_interface_[index])) {
568-
RCLCPP_ERROR(node_->get_logger(), "Expected %u %s command interfaces, got %u",
590+
state_interfaces_, joint_names_, interface, joint_state_interface_[index]))
591+
{
592+
RCLCPP_ERROR(
593+
node_->get_logger(), "Expected %u %s state interfaces, got %u",
569594
joint_names_.size(), interface.c_str(), joint_state_interface_[index].size());
595+
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::ERROR;
570596
}
571597
}
572598

@@ -586,7 +612,7 @@ JointTrajectoryController::on_activate(const rclcpp_lifecycle::State &)
586612
traj_external_point_ptr_ = std::make_shared<Trajectory>();
587613
traj_home_point_ptr_ = std::make_shared<Trajectory>();
588614

589-
is_halted = false;
615+
is_halted_ = false;
590616
subscriber_is_active_ = true;
591617
traj_point_active_ptr_ = &traj_external_point_ptr_;
592618
last_state_publish_time_ = node_->now();
@@ -598,7 +624,7 @@ JointTrajectoryController::on_activate(const rclcpp_lifecycle::State &)
598624
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
599625
JointTrajectoryController::on_deactivate(const rclcpp_lifecycle::State &)
600626
{
601-
for (int index = 0; index < allowed_interface_types_.size(); ++index) {
627+
for (auto index = 0ul; index < allowed_interface_types_.size(); ++index) {
602628
joint_command_interface_[index].clear();
603629
joint_state_interface_[index].clear();
604630
}
@@ -641,7 +667,7 @@ JointTrajectoryController::reset()
641667
traj_home_point_ptr_.reset();
642668
traj_msg_home_ptr_.reset();
643669

644-
is_halted = false;
670+
is_halted_ = false;
645671

646672
return true;
647673
}
@@ -658,6 +684,8 @@ void
658684
JointTrajectoryController::halt()
659685
{
660686
// TODO(anyone): How to halt when using effort commands?
687+
// TODO(anyone): Does this make sense at all? When we stop controller an call deactivate
688+
// the controller does not have access to the interfaces anymore...
661689
for (auto index = 0ul; index < joint_names_.size(); ++index) {
662690
joint_command_interface_[0][index].get().set_value(
663691
joint_command_interface_[0][index].get().get_value());
@@ -698,7 +726,7 @@ rclcpp_action::GoalResponse JointTrajectoryController::goal_callback(
698726
RCLCPP_INFO(node_->get_logger(), "Received new action goal");
699727

700728
// Precondition: Running controller
701-
if (is_halted) {
729+
if (is_halted_) {
702730
RCLCPP_ERROR(
703731
node_->get_logger(),
704732
"Can't accept new action goals. Controller is not running.");

joint_trajectory_controller/test/test_trajectory_actions.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,16 @@
4949

5050
using trajectory_msgs::msg::JointTrajectoryPoint;
5151
using test_trajectory_controllers::TestableJointTrajectoryController;
52-
using test_trajectory_controllers::TestTrajectoryController;
52+
using test_trajectory_controllers::TrajectoryControllerTest;
5353
using std::placeholders::_1;
5454
using std::placeholders::_2;
5555

56-
class TestTrajectoryActions : public TestTrajectoryController
56+
class TestTrajectoryActions : public TrajectoryControllerTest
5757
{
5858
protected:
5959
void SetUp()
6060
{
61-
TestTrajectoryController::SetUp();
61+
TrajectoryControllerTest::SetUp();
6262
goal_options_.goal_response_callback =
6363
std::bind(&TestTrajectoryActions::common_goal_response, this, _1);
6464
goal_options_.result_callback =

0 commit comments

Comments
 (0)