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),
@@ -540,6 +545,9 @@ URPositionHardwareInterface::on_configure(const rclcpp_lifecycle::State& previou
540545 driver_config.handle_program_state =
541546 std::bind (&URPositionHardwareInterface::handleRobotProgramState, this , std::placeholders::_1);
542547 ur_driver_ = std::make_unique<urcl::UrDriver>(driver_config);
548+ if (ur_driver_->getControlFrequency () != info_.rw_rate ) {
549+ ur_driver_->resetRTDEClient (output_recipe_filename, input_recipe_filename, info_.rw_rate );
550+ }
543551 } catch (urcl::ToolCommNotAvailable& e) {
544552 RCLCPP_FATAL_STREAM (rclcpp::get_logger (" URPositionHardwareInterface" ), " See parameter use_tool_communication" );
545553
@@ -786,7 +794,9 @@ hardware_interface::return_type URPositionHardwareInterface::write(const rclcpp:
786794 ur_driver_->writeFreedriveControlMessage (urcl::control::FreedriveControlMessage::FREEDRIVE_NOOP);
787795
788796 } else if (passthrough_trajectory_controller_running_) {
789- ur_driver_->writeTrajectoryControlMessage (urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP);
797+ ur_driver_->writeTrajectoryControlMessage (
798+ urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP, 0 ,
799+ urcl::RobotReceiveTimeout::millisec (1000 * 5.0 / static_cast <double >(info_.rw_rate )));
790800 check_passthrough_trajectory_controller ();
791801 } else {
792802 ur_driver_->writeKeepalive ();
@@ -1335,59 +1345,102 @@ void URPositionHardwareInterface::stop_force_mode()
13351345void URPositionHardwareInterface::check_passthrough_trajectory_controller ()
13361346{
13371347 static double last_time = 0.0 ;
1348+ static size_t point_index_received = 0 ;
1349+ static size_t point_index_sent = 0 ;
1350+ static bool trajectory_started = false ;
13381351 // See passthrough_trajectory_controller.hpp for an explanation of the passthrough_trajectory_transfer_state_ values.
13391352
13401353 // We should abort and are not in state IDLE
13411354 if (passthrough_trajectory_abort_ == 1.0 && passthrough_trajectory_transfer_state_ != 0.0 ) {
13421355 ur_driver_->writeTrajectoryControlMessage (urcl::control::TrajectoryControlMessage::TRAJECTORY_CANCEL);
1356+ } else if (passthrough_trajectory_transfer_state_ == 6.0 ) {
1357+ if (passthrough_trajectory_size_ != trajectory_joint_positions_.size ()) {
1358+ RCLCPP_INFO (get_logger (), " Got a new trajectory with %lu points." ,
1359+ static_cast <size_t >(passthrough_trajectory_size_));
1360+ trajectory_joint_positions_.resize (passthrough_trajectory_size_);
1361+ trajectory_joint_velocities_.resize (passthrough_trajectory_size_);
1362+ trajectory_joint_accelerations_.resize (passthrough_trajectory_size_);
1363+ trajectory_times_.resize (passthrough_trajectory_size_);
1364+ point_index_received = 0 ;
1365+ point_index_sent = 0 ;
1366+ trajectory_started = false ;
1367+ last_time = 0.0 ;
1368+ passthrough_trajectory_transfer_state_ = 1.0 ;
1369+ }
13431370 } else if (passthrough_trajectory_transfer_state_ == 2.0 ) {
13441371 passthrough_trajectory_abort_ = 0.0 ;
1345- trajectory_joint_positions_. push_back ( passthrough_trajectory_positions_) ;
1372+ trajectory_joint_positions_[point_index_received] = passthrough_trajectory_positions_;
13461373
1347- trajectory_times_. push_back ( passthrough_trajectory_time_from_start_ - last_time) ;
1374+ trajectory_times_[point_index_received] = passthrough_trajectory_time_from_start_ - last_time;
13481375 last_time = passthrough_trajectory_time_from_start_;
13491376
1350- if (!std::isnan (passthrough_trajectory_velocities_[0 ])) {
1351- trajectory_joint_velocities_.push_back (passthrough_trajectory_velocities_);
1352- }
1353- if (!std::isnan (passthrough_trajectory_accelerations_[0 ])) {
1354- trajectory_joint_accelerations_.push_back (passthrough_trajectory_accelerations_);
1355- }
1377+ trajectory_joint_velocities_[point_index_received] = passthrough_trajectory_velocities_;
1378+ trajectory_joint_accelerations_[point_index_received] = passthrough_trajectory_accelerations_;
1379+
1380+ point_index_received++;
13561381 passthrough_trajectory_transfer_state_ = 1.0 ;
1357- /* When all points have been read, write them to the physical robot controller.*/
1382+
1383+ // Once we received enough points so we can move for at least 5 cycles, we start executing
1384+ if ((passthrough_trajectory_time_from_start_ > 5.0 / static_cast <double >(info_.rw_rate ) ||
1385+ point_index_received == passthrough_trajectory_size_ - 1 ) &&
1386+ !trajectory_started) {
1387+ ur_driver_->writeTrajectoryControlMessage (urcl::control::TrajectoryControlMessage::TRAJECTORY_START,
1388+ trajectory_joint_positions_.size ());
1389+ trajectory_started = true ;
1390+ }
13581391 } else if (passthrough_trajectory_transfer_state_ == 3.0 ) {
1359- /* Tell robot controller how many points are in the trajectory. */
1360- ur_driver_->writeTrajectoryControlMessage (urcl::control::TrajectoryControlMessage::TRAJECTORY_START,
1361- trajectory_joint_positions_.size ());
1392+ passthrough_trajectory_abort_ = 0.0 ;
1393+ passthrough_trajectory_transfer_state_ = 4.0 ;
1394+ } else if (passthrough_trajectory_transfer_state_ == 4.0 ) {
1395+ if (point_index_sent == trajectory_joint_positions_.size ()) {
1396+ trajectory_joint_positions_.clear ();
1397+ trajectory_joint_accelerations_.clear ();
1398+ trajectory_joint_velocities_.clear ();
1399+ trajectory_times_.clear ();
1400+ last_time = 0.0 ;
1401+ }
1402+ }
1403+
1404+ // We basically get a setpoint from the controller in each cycle. We send all the points that we
1405+ // already received down to the hardware.
1406+ if (trajectory_started && point_index_sent <= trajectory_joint_positions_.size () &&
1407+ point_index_sent < point_index_received) {
1408+ bool error = false ;
13621409 /* Write the appropriate type of point depending on the combination of positions, velocities and accelerations. */
1363- if (!has_velocities (trajectory_joint_velocities_) && !has_accelerations (trajectory_joint_accelerations_)) {
1364- for (size_t i = 0 ; i < trajectory_joint_positions_.size (); i++) {
1365- ur_driver_->writeTrajectorySplinePoint (trajectory_joint_positions_[i], urcl::vector6d_t { 0 , 0 , 0 , 0 , 0 , 0 },
1366- trajectory_times_[i]);
1367- }
1368- } else if (has_velocities (trajectory_joint_velocities_) && !has_accelerations (trajectory_joint_accelerations_)) {
1369- for (size_t i = 0 ; i < trajectory_joint_positions_.size (); i++) {
1370- ur_driver_->writeTrajectorySplinePoint (trajectory_joint_positions_[i], trajectory_joint_velocities_[i],
1371- trajectory_times_[i]);
1372- }
1373- } else if (!has_velocities (trajectory_joint_velocities_) && has_accelerations (trajectory_joint_accelerations_)) {
1374- for (size_t i = 0 ; i < trajectory_joint_positions_.size (); i++) {
1375- ur_driver_->writeTrajectorySplinePoint (trajectory_joint_positions_[i], trajectory_joint_accelerations_[i],
1376- trajectory_times_[i]);
1377- }
1378- } else if (has_velocities (trajectory_joint_velocities_) && has_accelerations (trajectory_joint_accelerations_)) {
1379- for (size_t i = 0 ; i < trajectory_joint_positions_.size (); i++) {
1380- ur_driver_->writeTrajectorySplinePoint (trajectory_joint_positions_[i], trajectory_joint_velocities_[i],
1381- trajectory_joint_accelerations_[i], trajectory_times_[i]);
1410+ for (size_t i = point_index_sent; i < point_index_received; i++) {
1411+ if (is_valid_joint_information (trajectory_joint_positions_)) {
1412+ if (!is_valid_joint_information (trajectory_joint_velocities_) &&
1413+ !is_valid_joint_information (trajectory_joint_accelerations_)) {
1414+ ur_driver_->writeTrajectorySplinePoint (trajectory_joint_positions_[i], urcl::vector6d_t { 0 , 0 , 0 , 0 , 0 , 0 },
1415+ trajectory_times_[i]);
1416+ } else if (is_valid_joint_information (trajectory_joint_velocities_) &&
1417+ !is_valid_joint_information (trajectory_joint_accelerations_)) {
1418+ ur_driver_->writeTrajectorySplinePoint (trajectory_joint_positions_[i], trajectory_joint_velocities_[i],
1419+ trajectory_times_[i]);
1420+ } else if (!is_valid_joint_information (trajectory_joint_velocities_) &&
1421+ is_valid_joint_information (trajectory_joint_accelerations_)) {
1422+ RCLCPP_ERROR (get_logger (), " Accelerations but no velocities given. If you want to specify accelerations with "
1423+ " a 0 velocity, please do that explicitly." );
1424+ error = true ;
1425+ break ;
1426+
1427+ } else if (is_valid_joint_information (trajectory_joint_velocities_) &&
1428+ is_valid_joint_information (trajectory_joint_accelerations_)) {
1429+ ur_driver_->writeTrajectorySplinePoint (trajectory_joint_positions_[i], trajectory_joint_velocities_[i],
1430+ trajectory_joint_accelerations_[i], trajectory_times_[i]);
1431+ }
1432+ } else {
1433+ RCLCPP_ERROR (get_logger (), " Trajectory points without position information are not supported." );
1434+ error = true ;
1435+ break ;
13821436 }
1437+ point_index_sent++;
1438+ }
1439+ if (error) {
1440+ passthrough_trajectory_abort_ = 1.0 ;
1441+ passthrough_trajectory_transfer_state_ = 5.0 ;
1442+ return ;
13831443 }
1384- trajectory_joint_positions_.clear ();
1385- trajectory_joint_accelerations_.clear ();
1386- trajectory_joint_velocities_.clear ();
1387- trajectory_times_.clear ();
1388- last_time = 0.0 ;
1389- passthrough_trajectory_abort_ = 0.0 ;
1390- passthrough_trajectory_transfer_state_ = 4.0 ;
13911444 }
13921445}
13931446
@@ -1402,14 +1455,9 @@ void URPositionHardwareInterface::trajectory_done_callback(urcl::control::Trajec
14021455 return ;
14031456}
14041457
1405- bool URPositionHardwareInterface::has_velocities (std::vector<std::array<double , 6 >> velocities)
1406- {
1407- return (velocities.size () > 0 );
1408- }
1409-
1410- bool URPositionHardwareInterface::has_accelerations (std::vector<std::array<double , 6 >> accelerations)
1458+ bool URPositionHardwareInterface::is_valid_joint_information (std::vector<std::array<double , 6 >> data)
14111459{
1412- return (accelerations .size () > 0 );
1460+ return (data .size () > 0 && ! std::isnan (data[ 0 ][ 0 ]) );
14131461}
14141462
14151463} // namespace ur_robot_driver
0 commit comments