Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JTC] Accept larger number of joints than command_joints #809

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa

// Degrees of freedom
size_t dof_;
size_t num_cmd_joints_;
std::vector<size_t> map_cmd_to_joints_;

// Storing command joint names for interfaces
std::vector<std::string> command_joint_names_;
Expand Down Expand Up @@ -295,9 +297,9 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa

void init_hold_position_msg();
void resize_joint_trajectory_point(
trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size);
trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size, double value = 0.0);
void resize_joint_trajectory_point_command(
trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size);
trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size, double value = 0.0);

urdf::Model model_;

Expand All @@ -313,9 +315,9 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa
void assign_interface_from_point(
const T & joint_interface, const std::vector<double> & trajectory_point_interface)
{
for (size_t index = 0; index < dof_; ++index)
for (size_t index = 0; index < num_cmd_joints_; ++index)
{
joint_interface[index].get().set_value(trajectory_point_interface[index]);
joint_interface[index].get().set_value(trajectory_point_interface[map_cmd_to_joints_[index]]);
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class Trajectory
/**
* \return The map between \p t1 indices (implicitly encoded in return vector indices) to \p t2
* indices. If \p t1 is <tt>"{C, B}"</tt> and \p t2 is <tt>"{A, B, C, D}"</tt>, the associated
* mapping vector is <tt>"{2, 1}"</tt>.
* mapping vector is <tt>"{2, 1}"</tt>. return empty vector if \p t1 is not a subset of \p t2.
*/
template <class T>
inline std::vector<size_t> mapping(const T & t1, const T & t2)
Expand Down
115 changes: 72 additions & 43 deletions joint_trajectory_controller/src/joint_trajectory_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include <chrono>
#include <functional>
#include <memory>

#include <numeric>
#include <string>
#include <vector>

Expand All @@ -40,7 +40,7 @@
namespace joint_trajectory_controller
{
JointTrajectoryController::JointTrajectoryController()
: controller_interface::ControllerInterface(), dof_(0)
: controller_interface::ControllerInterface(), dof_(0), num_cmd_joints_(0)
{
}

Expand Down Expand Up @@ -83,16 +83,7 @@ JointTrajectoryController::command_interface_configuration() const
{
controller_interface::InterfaceConfiguration conf;
conf.type = controller_interface::interface_configuration_type::INDIVIDUAL;
if (dof_ == 0)
{
fprintf(
stderr,
"During ros2_control interface configuration, degrees of freedom is not valid;"
" it should be positive. Actual DOF is %zu\n",
dof_);
std::exit(EXIT_FAILURE);
}
conf.names.reserve(dof_ * params_.command_interfaces.size());
conf.names.reserve(num_cmd_joints_ * params_.command_interfaces.size());
for (const auto & joint_name : command_joint_names_)
{
for (const auto & interface_type : params_.command_interfaces)
Expand Down Expand Up @@ -258,12 +249,14 @@ controller_interface::return_type JointTrajectoryController::update(
if (use_closed_loop_pid_adapter_)
{
// Update PIDs
for (auto i = 0ul; i < dof_; ++i)
for (auto i = 0ul; i < num_cmd_joints_; ++i)
{
tmp_command_[i] = (state_desired_.velocities[i] * ff_velocity_scale_[i]) +
pids_[i]->computeCommand(
state_error_.positions[i], state_error_.velocities[i],
(uint64_t)period.nanoseconds());
size_t index_cmd_joint = map_cmd_to_joints_[i];
tmp_command_[index_cmd_joint] =
(state_desired_.velocities[index_cmd_joint] * ff_velocity_scale_[i]) +
pids_[i]->computeCommand(
state_error_.positions[index_cmd_joint], state_error_.velocities[index_cmd_joint],
(uint64_t)period.nanoseconds());
}
}

Expand Down Expand Up @@ -435,9 +428,10 @@ bool JointTrajectoryController::read_state_from_command_interfaces(JointTrajecto
auto assign_point_from_interface =
[&](std::vector<double> & trajectory_point_interface, const auto & joint_interface)
{
for (size_t index = 0; index < dof_; ++index)
for (size_t index = 0; index < num_cmd_joints_; ++index)
{
trajectory_point_interface[index] = joint_interface[index].get().get_value();
trajectory_point_interface[map_cmd_to_joints_[index]] =
joint_interface[index].get().get_value();
}
};

Expand Down Expand Up @@ -506,9 +500,10 @@ bool JointTrajectoryController::read_commands_from_command_interfaces(
auto assign_point_from_interface =
[&](std::vector<double> & trajectory_point_interface, const auto & joint_interface)
{
for (size_t index = 0; index < dof_; ++index)
for (size_t index = 0; index < num_cmd_joints_; ++index)
{
trajectory_point_interface[index] = joint_interface[index].get().get_value();
trajectory_point_interface[map_cmd_to_joints_[index]] =
joint_interface[index].get().get_value();
}
};

Expand Down Expand Up @@ -647,8 +642,8 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure(

if (params_.joints.empty())
{
// TODO(destogl): is this correct? Can we really move-on if no joint names are not provided?
RCLCPP_WARN(logger, "'joints' parameter is empty.");
return CallbackReturn::FAILURE;
}

command_joint_names_ = params_.command_joints;
Expand All @@ -659,12 +654,40 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure(
RCLCPP_INFO(
logger, "No specific joint names are used for command interfaces. Using 'joints' parameter.");
}
else if (command_joint_names_.size() != params_.joints.size())
num_cmd_joints_ = command_joint_names_.size();

if (num_cmd_joints_ > dof_)
{
RCLCPP_ERROR(
logger, "'command_joints' parameter has to have the same size as 'joints' parameter.");
logger, "'command_joints' parameter must not have greater size as 'joints' parameter.");
return CallbackReturn::FAILURE;
}
else if (num_cmd_joints_ < dof_)
{
// create a map for the command joints
map_cmd_to_joints_ = mapping(command_joint_names_, params_.joints);
if (map_cmd_to_joints_.size() != num_cmd_joints_)
{
RCLCPP_ERROR(
logger,
"'command_joints' parameter must be a subset of 'joints' parameter, if their size is not "
"equal.");
return CallbackReturn::FAILURE;
}
for (size_t i = 0; i < command_joint_names_.size(); i++)
{
RCLCPP_DEBUG(
logger, "Command joint %lu: '%s' maps to joint %lu: '%s'.", i,
command_joint_names_[i].c_str(), map_cmd_to_joints_[i],
params_.joints.at(map_cmd_to_joints_[i]).c_str());
}
}
else
{
// create a map for the command joints, trivial if the size is the same
map_cmd_to_joints_.resize(num_cmd_joints_);
std::iota(map_cmd_to_joints_.begin(), map_cmd_to_joints_.end(), 0);
}

if (params_.command_interfaces.empty())
{
Expand Down Expand Up @@ -694,9 +717,9 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure(

if (use_closed_loop_pid_adapter_)
{
pids_.resize(dof_);
ff_velocity_scale_.resize(dof_);
tmp_command_.resize(dof_, 0.0);
pids_.resize(num_cmd_joints_);
ff_velocity_scale_.resize(num_cmd_joints_);
tmp_command_.resize(dof_, std::numeric_limits<double>::quiet_NaN());

update_pids();
}
Expand Down Expand Up @@ -871,10 +894,12 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure(
std::bind(&JointTrajectoryController::goal_accepted_callback, this, _1));

resize_joint_trajectory_point(state_current_, dof_);
resize_joint_trajectory_point_command(command_current_, dof_);
resize_joint_trajectory_point_command(
command_current_, dof_, std::numeric_limits<double>::quiet_NaN());
resize_joint_trajectory_point(state_desired_, dof_);
resize_joint_trajectory_point(state_error_, dof_);
resize_joint_trajectory_point(last_commanded_state_, dof_);
resize_joint_trajectory_point(
last_commanded_state_, dof_, std::numeric_limits<double>::quiet_NaN());

query_state_srv_ = get_node()->create_service<control_msgs::srv::QueryTrajectoryState>(
std::string(get_node()->get_name()) + "/query_state",
Expand Down Expand Up @@ -905,7 +930,7 @@ controller_interface::CallbackReturn JointTrajectoryController::on_activate(
command_interfaces_, command_joint_names_, interface, joint_command_interface_[index]))
{
RCLCPP_ERROR(
get_node()->get_logger(), "Expected %zu '%s' command interfaces, got %zu.", dof_,
get_node()->get_logger(), "Expected %zu '%s' command interfaces, got %zu.", num_cmd_joints_,
interface.c_str(), joint_command_interface_[index].size());
return CallbackReturn::ERROR;
}
Expand Down Expand Up @@ -935,7 +960,11 @@ controller_interface::CallbackReturn JointTrajectoryController::on_activate(
// running already)
trajectory_msgs::msg::JointTrajectoryPoint state;
resize_joint_trajectory_point(state, dof_);
if (read_state_from_command_interfaces(state))
// read from cmd joints only if all joints have command interface
// otherwise it leaves the entries of joints without command interface NaN.
// if no open_loop control, state_current_ is then used for `set_point_before_trajectory_msg` and
// future trajectory sampling will always give NaN for these joints
if (dof_ == num_cmd_joints_ && read_state_from_command_interfaces(state))
{
state_current_ = state;
last_commanded_state_ = state;
Expand Down Expand Up @@ -990,7 +1019,7 @@ controller_interface::CallbackReturn JointTrajectoryController::on_deactivate(
rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr());
}

for (size_t index = 0; index < dof_; ++index)
for (size_t index = 0; index < num_cmd_joints_; ++index)
{
if (has_position_command_interface_)
{
Expand Down Expand Up @@ -1536,37 +1565,37 @@ bool JointTrajectoryController::contains_interface_type(
}

void JointTrajectoryController::resize_joint_trajectory_point(
trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size)
trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size, double value)
{
point.positions.resize(size, 0.0);
point.positions.resize(size, value);
if (has_velocity_state_interface_)
{
point.velocities.resize(size, 0.0);
point.velocities.resize(size, value);
}
if (has_acceleration_state_interface_)
{
point.accelerations.resize(size, 0.0);
point.accelerations.resize(size, value);
}
}

void JointTrajectoryController::resize_joint_trajectory_point_command(
trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size)
trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size, double value)
{
if (has_position_command_interface_)
{
point.positions.resize(size, 0.0);
point.positions.resize(size, value);
}
if (has_velocity_command_interface_)
{
point.velocities.resize(size, 0.0);
point.velocities.resize(size, value);
}
if (has_acceleration_command_interface_)
{
point.accelerations.resize(size, 0.0);
point.accelerations.resize(size, value);
}
if (has_effort_command_interface_)
{
point.effort.resize(size, 0.0);
point.effort.resize(size, value);
}
}

Expand All @@ -1577,9 +1606,9 @@ bool JointTrajectoryController::has_active_trajectory() const

void JointTrajectoryController::update_pids()
{
for (size_t i = 0; i < dof_; ++i)
for (size_t i = 0; i < num_cmd_joints_; ++i)
{
const auto & gains = params_.gains.joints_map.at(params_.joints[i]);
const auto & gains = params_.gains.joints_map.at(params_.joints.at(map_cmd_to_joints_[i]));
if (pids_[i])
{
// update PIDs with gains from ROS parameters
Expand Down
6 changes: 3 additions & 3 deletions joint_trajectory_controller/test/test_trajectory_actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@
#include "action_msgs/msg/goal_status_array.hpp"
#include "control_msgs/action/detail/follow_joint_trajectory__struct.hpp"
#include "controller_interface/controller_interface.hpp"
#include "gtest/gtest.h"
#include "hardware_interface/resource_manager.hpp"
#include "joint_trajectory_controller/joint_trajectory_controller.hpp"
#include "rclcpp/clock.hpp"
#include "rclcpp/duration.hpp"
#include "rclcpp/executors/multi_threaded_executor.hpp"
Expand All @@ -45,10 +43,12 @@
#include "rclcpp_action/client_goal_handle.hpp"
#include "rclcpp_action/create_client.hpp"
#include "rclcpp_lifecycle/lifecycle_node.hpp"
#include "test_trajectory_controller_utils.hpp"
#include "trajectory_msgs/msg/joint_trajectory.hpp"
#include "trajectory_msgs/msg/joint_trajectory_point.hpp"

#include "joint_trajectory_controller/joint_trajectory_controller.hpp"
#include "test_trajectory_controller_utils.hpp"

using std::placeholders::_1;
using std::placeholders::_2;
using test_trajectory_controllers::TestableJointTrajectoryController;
Expand Down
Loading
Loading