Skip to content

Commit 024e183

Browse files
committed
Start executing passthrogh trajectories earlier than all points are transferred.
When transferring trajectories with many waypoints it can take quite a while until all points are transferred from the controller to the hardware interface, especially on lower hardware_interface update rates. With this change, execution starts as soon as enough trajectory points are transferred to fill 5 control cycles. This PR effectively allows reducing the hardware_interface update_rate when using the passthrough_trajectory_controller significantly. This will reduce the networking requirements improving the overall user experience.
1 parent b1c1c00 commit 024e183

File tree

5 files changed

+91
-35
lines changed

5 files changed

+91
-35
lines changed

ur_controllers/include/ur_controllers/passthrough_trajectory_controller.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ class PassthroughTrajectoryController : public controller_interface::ControllerI
174174

175175
std::optional<std::reference_wrapper<hardware_interface::LoanedStateInterface>> scaling_state_interface_;
176176
std::optional<std::reference_wrapper<hardware_interface::LoanedCommandInterface>> abort_command_interface_;
177+
std::optional<std::reference_wrapper<hardware_interface::LoanedCommandInterface>> trajectory_size_command_interface_;
177178
std::optional<std::reference_wrapper<hardware_interface::LoanedCommandInterface>> transfer_command_interface_;
178179
std::optional<std::reference_wrapper<hardware_interface::LoanedCommandInterface>> time_from_start_command_interface_;
179180

ur_controllers/src/passthrough_trajectory_controller.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ controller_interface::InterfaceConfiguration PassthroughTrajectoryController::co
132132
config.names.push_back(tf_prefix + "trajectory_passthrough/abort");
133133
config.names.emplace_back(tf_prefix + "trajectory_passthrough/transfer_state");
134134
config.names.emplace_back(tf_prefix + "trajectory_passthrough/time_from_start");
135+
config.names.emplace_back(tf_prefix + "trajectory_passthrough/trajectory_size");
135136

136137
return config;
137138
}
@@ -180,6 +181,19 @@ controller_interface::CallbackReturn PassthroughTrajectoryController::on_activat
180181
}
181182
}
182183

184+
{
185+
const std::string interface_name = passthrough_params_.tf_prefix + "trajectory_passthrough/"
186+
"trajectory_size";
187+
auto it = std::find_if(command_interfaces_.begin(), command_interfaces_.end(),
188+
[&](auto& interface) { return (interface.get_name() == interface_name); });
189+
if (it != command_interfaces_.end()) {
190+
trajectory_size_command_interface_ = *it;
191+
} else {
192+
RCLCPP_ERROR(get_node()->get_logger(), "Did not find '%s' in command interfaces.", interface_name.c_str());
193+
return controller_interface::CallbackReturn::ERROR;
194+
}
195+
}
196+
183197
const std::string tf_prefix = passthrough_params_.tf_prefix;
184198
{
185199
const std::string interface_name = tf_prefix + "trajectory_passthrough/transfer_state";
@@ -255,6 +269,7 @@ controller_interface::return_type PassthroughTrajectoryController::update(const
255269
max_trajectory_time_ =
256270
rclcpp::Duration::from_seconds(duration_to_double(active_joint_traj_.points.back().time_from_start));
257271
write_success &= transfer_command_interface_->get().set_value(TRANSFER_STATE_WAITING_FOR_POINT);
272+
write_success &= trajectory_size_command_interface_->get().set_value(active_joint_traj_.points.size());
258273
}
259274
auto active_goal_time_tol = goal_time_tolerance_.readFromRT();
260275
auto joint_mapping = joint_trajectory_mapping_.readFromRT();

ur_robot_driver/include/ur_robot_driver/hardware_interface.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ class URPositionHardwareInterface : public hardware_interface::SystemInterface
240240
// Passthrough trajectory controller interface values
241241
double passthrough_trajectory_transfer_state_;
242242
double passthrough_trajectory_abort_;
243+
double passthrough_trajectory_size_;
243244
bool passthrough_trajectory_controller_running_;
244245
urcl::vector6d_t passthrough_trajectory_positions_;
245246
urcl::vector6d_t passthrough_trajectory_velocities_;

ur_robot_driver/src/hardware_interface.cpp

Lines changed: 73 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "ur_client_library/exceptions.h"
4646
#include "ur_client_library/ur/tool_communication.h"
4747
#include "ur_client_library/ur/version_information.h"
48+
#include "ur_client_library/ur/robot_receive_timeout.h"
4849

4950
#include <rclcpp/logging.hpp>
5051
#include "hardware_interface/types/hardware_interface_type_values.hpp"
@@ -93,9 +94,10 @@ URPositionHardwareInterface::on_init(const hardware_interface::HardwareInfo& sys
9394
freedrive_mode_abort_ = 0.0;
9495
passthrough_trajectory_transfer_state_ = 0.0;
9596
passthrough_trajectory_abort_ = 0.0;
96-
trajectory_joint_positions_.clear();
97-
trajectory_joint_velocities_.clear();
98-
trajectory_joint_accelerations_.clear();
97+
passthrough_trajectory_size_ = 0.0;
98+
trajectory_joint_positions_.reserve(32768);
99+
trajectory_joint_velocities_.reserve(32768);
100+
trajectory_joint_accelerations_.reserve(32768);
99101

100102
for (const hardware_interface::ComponentInfo& joint : info_.joints) {
101103
if (joint.command_interfaces.size() != 2) {
@@ -381,6 +383,9 @@ std::vector<hardware_interface::CommandInterface> URPositionHardwareInterface::e
381383
command_interfaces.emplace_back(
382384
hardware_interface::CommandInterface(tf_prefix + PASSTHROUGH_GPIO, "abort", &passthrough_trajectory_abort_));
383385

386+
command_interfaces.emplace_back(hardware_interface::CommandInterface(tf_prefix + PASSTHROUGH_GPIO, "trajectory_size",
387+
&passthrough_trajectory_size_));
388+
384389
for (size_t i = 0; i < 6; ++i) {
385390
command_interfaces.emplace_back(hardware_interface::CommandInterface(tf_prefix + PASSTHROUGH_GPIO,
386391
"setpoint_positions_" + std::to_string(i),
@@ -527,6 +532,9 @@ URPositionHardwareInterface::on_configure(const rclcpp_lifecycle::State& previou
527532
std::bind(&URPositionHardwareInterface::handleRobotProgramState, this, std::placeholders::_1), headless_mode,
528533
std::move(tool_comm_setup), (uint32_t)reverse_port, (uint32_t)script_sender_port, servoj_gain,
529534
servoj_lookahead_time, non_blocking_read_, reverse_ip, trajectory_port, script_command_port);
535+
if (ur_driver_->getControlFrequency() != info_.rw_rate) {
536+
ur_driver_->resetRTDEClient(output_recipe_filename, input_recipe_filename, info_.rw_rate);
537+
}
530538
} catch (urcl::ToolCommNotAvailable& e) {
531539
RCLCPP_FATAL_STREAM(rclcpp::get_logger("URPositionHardwareInterface"), "See parameter use_tool_communication");
532540

@@ -773,7 +781,9 @@ hardware_interface::return_type URPositionHardwareInterface::write(const rclcpp:
773781
ur_driver_->writeFreedriveControlMessage(urcl::control::FreedriveControlMessage::FREEDRIVE_NOOP);
774782

775783
} else if (passthrough_trajectory_controller_running_) {
776-
ur_driver_->writeTrajectoryControlMessage(urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP);
784+
ur_driver_->writeTrajectoryControlMessage(
785+
urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP, 0,
786+
urcl::RobotReceiveTimeout::millisec(1000 * 5.0 / static_cast<double>(info_.rw_rate)));
777787
check_passthrough_trajectory_controller();
778788
} else {
779789
ur_driver_->writeKeepalive();
@@ -1309,59 +1319,87 @@ void URPositionHardwareInterface::stop_force_mode()
13091319
void URPositionHardwareInterface::check_passthrough_trajectory_controller()
13101320
{
13111321
static double last_time = 0.0;
1322+
static size_t point_index_received = 0;
1323+
static size_t point_index_sent = 0;
1324+
static bool trajectory_started = false;
13121325
// See passthrough_trajectory_controller.hpp for an explanation of the passthrough_trajectory_transfer_state_ values.
13131326

13141327
// We should abort and are not in state IDLE
13151328
if (passthrough_trajectory_abort_ == 1.0 && passthrough_trajectory_transfer_state_ != 0.0) {
13161329
ur_driver_->writeTrajectoryControlMessage(urcl::control::TrajectoryControlMessage::TRAJECTORY_CANCEL);
1330+
} else if (passthrough_trajectory_transfer_state_ == 1.0) {
1331+
if (passthrough_trajectory_size_ != trajectory_joint_positions_.size()) {
1332+
RCLCPP_INFO(get_logger(), "Got a new trajectory with %lu points.",
1333+
static_cast<size_t>(passthrough_trajectory_size_));
1334+
trajectory_joint_positions_.resize(passthrough_trajectory_size_);
1335+
trajectory_joint_velocities_.resize(passthrough_trajectory_size_);
1336+
trajectory_joint_accelerations_.resize(passthrough_trajectory_size_);
1337+
trajectory_times_.resize(passthrough_trajectory_size_);
1338+
point_index_received = 0;
1339+
point_index_sent = 0;
1340+
trajectory_started = false;
1341+
last_time = 0.0;
1342+
}
13171343
} else if (passthrough_trajectory_transfer_state_ == 2.0) {
13181344
passthrough_trajectory_abort_ = 0.0;
1319-
trajectory_joint_positions_.push_back(passthrough_trajectory_positions_);
1345+
trajectory_joint_positions_[point_index_received] = passthrough_trajectory_positions_;
13201346

1321-
trajectory_times_.push_back(passthrough_trajectory_time_from_start_ - last_time);
1347+
trajectory_times_[point_index_received] = passthrough_trajectory_time_from_start_ - last_time;
13221348
last_time = passthrough_trajectory_time_from_start_;
13231349

1324-
if (!std::isnan(passthrough_trajectory_velocities_[0])) {
1325-
trajectory_joint_velocities_.push_back(passthrough_trajectory_velocities_);
1326-
}
1327-
if (!std::isnan(passthrough_trajectory_accelerations_[0])) {
1328-
trajectory_joint_accelerations_.push_back(passthrough_trajectory_accelerations_);
1329-
}
1350+
// if (!std::isnan(passthrough_trajectory_velocities_[0])) {
1351+
trajectory_joint_velocities_[point_index_received] = passthrough_trajectory_velocities_;
1352+
//}
1353+
// if (!std::isnan(passthrough_trajectory_accelerations_[0])) {
1354+
trajectory_joint_accelerations_[point_index_received] = passthrough_trajectory_accelerations_;
1355+
//}
1356+
1357+
point_index_received++;
13301358
passthrough_trajectory_transfer_state_ = 1.0;
1359+
1360+
// Once we received enough points so we can move for at least 5 cycles, we start executing
1361+
if ((passthrough_trajectory_time_from_start_ > 5.0 / static_cast<double>(info_.rw_rate) ||
1362+
point_index_received == passthrough_trajectory_size_ - 1) &&
1363+
!trajectory_started) {
1364+
ur_driver_->writeTrajectoryControlMessage(urcl::control::TrajectoryControlMessage::TRAJECTORY_START,
1365+
trajectory_joint_positions_.size());
1366+
trajectory_started = true;
1367+
}
13311368
/* When all points have been read, write them to the physical robot controller.*/
13321369
} else if (passthrough_trajectory_transfer_state_ == 3.0) {
1333-
/* Tell robot controller how many points are in the trajectory. */
1334-
ur_driver_->writeTrajectoryControlMessage(urcl::control::TrajectoryControlMessage::TRAJECTORY_START,
1335-
trajectory_joint_positions_.size());
1370+
passthrough_trajectory_abort_ = 0.0;
1371+
passthrough_trajectory_transfer_state_ = 4.0;
1372+
} else if (passthrough_trajectory_transfer_state_ == 4.0) {
1373+
if (point_index_sent == trajectory_joint_positions_.size()) {
1374+
trajectory_joint_positions_.clear();
1375+
trajectory_joint_accelerations_.clear();
1376+
trajectory_joint_velocities_.clear();
1377+
trajectory_times_.clear();
1378+
last_time = 0.0;
1379+
}
1380+
}
1381+
1382+
// We basically get a setpoint from the controller in each cycle. We send all the points that we
1383+
// already received down to the hardware.
1384+
if (trajectory_started && point_index_sent <= trajectory_joint_positions_.size() &&
1385+
point_index_sent < point_index_received) {
13361386
/* Write the appropriate type of point depending on the combination of positions, velocities and accelerations. */
1337-
if (!has_velocities(trajectory_joint_velocities_) && !has_accelerations(trajectory_joint_accelerations_)) {
1338-
for (size_t i = 0; i < trajectory_joint_positions_.size(); i++) {
1387+
for (size_t i = point_index_sent; i < point_index_received; i++) {
1388+
if (!has_velocities(trajectory_joint_velocities_) && !has_accelerations(trajectory_joint_accelerations_)) {
13391389
ur_driver_->writeTrajectorySplinePoint(trajectory_joint_positions_[i], urcl::vector6d_t{ 0, 0, 0, 0, 0, 0 },
13401390
trajectory_times_[i]);
1341-
}
1342-
} else if (has_velocities(trajectory_joint_velocities_) && !has_accelerations(trajectory_joint_accelerations_)) {
1343-
for (size_t i = 0; i < trajectory_joint_positions_.size(); i++) {
1391+
} else if (has_velocities(trajectory_joint_velocities_) && !has_accelerations(trajectory_joint_accelerations_)) {
13441392
ur_driver_->writeTrajectorySplinePoint(trajectory_joint_positions_[i], trajectory_joint_velocities_[i],
13451393
trajectory_times_[i]);
1346-
}
1347-
} else if (!has_velocities(trajectory_joint_velocities_) && has_accelerations(trajectory_joint_accelerations_)) {
1348-
for (size_t i = 0; i < trajectory_joint_positions_.size(); i++) {
1394+
} else if (!has_velocities(trajectory_joint_velocities_) && has_accelerations(trajectory_joint_accelerations_)) {
13491395
ur_driver_->writeTrajectorySplinePoint(trajectory_joint_positions_[i], trajectory_joint_accelerations_[i],
13501396
trajectory_times_[i]);
1351-
}
1352-
} else if (has_velocities(trajectory_joint_velocities_) && has_accelerations(trajectory_joint_accelerations_)) {
1353-
for (size_t i = 0; i < trajectory_joint_positions_.size(); i++) {
1397+
} else if (has_velocities(trajectory_joint_velocities_) && has_accelerations(trajectory_joint_accelerations_)) {
13541398
ur_driver_->writeTrajectorySplinePoint(trajectory_joint_positions_[i], trajectory_joint_velocities_[i],
13551399
trajectory_joint_accelerations_[i], trajectory_times_[i]);
13561400
}
1401+
point_index_sent++;
13571402
}
1358-
trajectory_joint_positions_.clear();
1359-
trajectory_joint_accelerations_.clear();
1360-
trajectory_joint_velocities_.clear();
1361-
trajectory_times_.clear();
1362-
last_time = 0.0;
1363-
passthrough_trajectory_abort_ = 0.0;
1364-
passthrough_trajectory_transfer_state_ = 4.0;
13651403
}
13661404
}
13671405

@@ -1378,12 +1416,12 @@ void URPositionHardwareInterface::trajectory_done_callback(urcl::control::Trajec
13781416

13791417
bool URPositionHardwareInterface::has_velocities(std::vector<std::array<double, 6>> velocities)
13801418
{
1381-
return (velocities.size() > 0);
1419+
return (velocities.size() > 0 && !std::isnan(velocities[0][0]));
13821420
}
13831421

13841422
bool URPositionHardwareInterface::has_accelerations(std::vector<std::array<double, 6>> accelerations)
13851423
{
1386-
return (accelerations.size() > 0);
1424+
return (accelerations.size() > 0 && !std::isnan(accelerations[0][0]));
13871425
}
13881426

13891427
} // namespace ur_robot_driver

ur_robot_driver/urdf/ur.ros2_control.xacro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@
289289
<command_interface name="transfer_state"/>
290290
<command_interface name="time_from_start"/>
291291
<command_interface name="abort"/>
292+
<command_interface name="trajectory_size"/>
292293
</gpio>
293294

294295

0 commit comments

Comments
 (0)