franka_combinable_hw.cpp
Go to the documentation of this file.
1 // Copyright (c) 2019 Franka Emika GmbH
2 // Use of this source code is governed by the Apache-2.0 license, see LICENSE
4 
8 #include <std_msgs/Bool.h>
9 
10 #include <franka_hw/services.h>
11 
12 namespace franka_hw {
13 
14 FrankaCombinableHW::FrankaCombinableHW() : has_error_(false), error_recovered_(false) {}
15 
20  setupLimitInterface<joint_limits_interface::EffortJointSoftLimitsHandle>(
24 
25  has_error_pub_ = robot_hw_nh.advertise<std_msgs::Bool>("has_error", 1, true);
27 
28  setupServicesAndActionServers(robot_hw_nh);
29 }
30 
33  control_loop_thread_ = std::make_unique<std::thread>(&FrankaCombinableHW::controlLoop, this);
34 }
35 
36 void FrankaCombinableHW::publishErrorState(const bool error) {
37  std_msgs::Bool msg;
38  msg.data = static_cast<int>(error);
40 }
41 
43  while (ros::ok()) {
44  ros::Time last_time = ros::Time::now();
45 
46  // Wait until controller has been activated or error has been recovered
47  while (!controllerActive() || has_error_) {
48  if (!controllerActive()) {
49  ROS_DEBUG_THROTTLE(1, "FrankaCombinableHW::%s::control_loop(): controller is not active.",
50  arm_id_.c_str());
51  }
52  if (has_error_) {
53  ROS_DEBUG_THROTTLE(1, "FrankaCombinableHW::%s::control_loop(): an error has occured.",
54  arm_id_.c_str());
55  }
56 
58 
59  {
60  std::lock_guard<std::mutex> ros_state_lock(ros_state_mutex_);
61  std::lock_guard<std::mutex> libfranka_state_lock(libfranka_state_mutex_);
62  robot_state_libfranka_ = robot_->readOnce();
63  robot_state_ros_ = robot_->readOnce();
64  }
65 
66  if (!ros::ok()) {
67  return;
68  }
69  }
70  ROS_INFO("FrankaCombinableHW::%s::control_loop(): controller is active.", arm_id_.c_str());
71 
72  // Reset commands
73  {
74  std::lock_guard<std::mutex> command_lock(libfranka_cmd_mutex_);
75  effort_joint_command_libfranka_ = franka::Torques({0., 0., 0., 0., 0., 0., 0.});
76  }
77 
78  try {
79  control();
80  } catch (const franka::ControlException& e) {
81  // Reflex could be caught and it needs to wait for automatic error recovery
82  ROS_ERROR("%s: %s", arm_id_.c_str(), e.what());
83  has_error_ = true;
84  publishErrorState(has_error_);
85  }
86  }
87 }
88 
90  setupServices(*robot_, node_handle, services_);
92  std::make_unique<actionlib::SimpleActionServer<franka_msgs::ErrorRecoveryAction>>(
93  node_handle, "error_recovery",
94  [&](const franka_msgs::ErrorRecoveryGoalConstPtr&) {
95  try {
96  robot_->automaticErrorRecovery();
97  // error recovered => reset controller
98  if (has_error_) {
99  error_recovered_ = true;
100  }
101  has_error_ = false;
103  recovery_action_server_->setSucceeded();
104  } catch (const franka::Exception& ex) {
105  recovery_action_server_->setAborted(franka_msgs::ErrorRecoveryResult(), ex.what());
106  }
107  },
108  false);
109  recovery_action_server_->start();
110 }
111 
112 void FrankaCombinableHW::control( // NOLINT (google-default-arguments)
113  const std::function<bool(const ros::Time&, const ros::Duration&)>& /*ros_callback*/) const {
114  if (!controller_active_) {
115  return;
116  }
117  auto empty_method = [](const franka::RobotState&, franka::Duration) { return true; };
118  run_function_(*robot_, empty_method);
119 }
120 
122  const std::list<hardware_interface::ControllerInfo>& info) const {
123  ResourceWithClaimsMap resource_map = getResourceMap(info);
124 
125  if (hasConflictingMultiClaim(resource_map)) {
126  return true;
127  }
128 
129  ArmClaimedMap arm_claim_map;
130  if (!getArmClaimedMap(resource_map, arm_claim_map)) {
131  ROS_ERROR("FrankaCombinableHW: Unknown interface claimed. Conflict!");
132  return true;
133  }
134 
135  // check for any claim to trajectory interfaces (non-torque) which are not supported.
136  if (hasTrajectoryClaim(arm_claim_map, arm_id_)) {
137  ROS_ERROR_STREAM("FrankaCombinableHW: Invalid claim joint position or velocity interface."
138  << "Note: joint position and joint velocity interfaces are not supported"
139  << " in FrankaCombinableHW. Arm:" << arm_id_ << ". Conflict!");
140  return true;
141  }
142 
143  return partiallyClaimsArmJoints(arm_claim_map, arm_id_);
144 }
145 
146 void FrankaCombinableHW::read(const ros::Time& time, const ros::Duration& period) {
148  FrankaHW::read(time, period);
149 }
150 
151 void FrankaCombinableHW::write(const ros::Time& time, const ros::Duration& period) {
152  // if flag `controller_needs_reset_` was updated, then controller_manager. update(...,
153  // reset_controller) must
154  // have been executed to reset the controller.
156  controller_needs_reset_ = false;
157  error_recovered_ = false;
158  }
159 
160  enforceLimits(period);
161 
162  FrankaHW::write(time, period);
163 }
164 
165 std::string FrankaCombinableHW::getArmID() const noexcept {
166  return arm_id_;
167 }
168 
170  has_error_ = true;
172 }
173 
174 bool FrankaCombinableHW::hasError() const noexcept {
175  return has_error_;
176 }
177 
179  robot_->automaticErrorRecovery();
180  // error recovered => reset controller
181  if (has_error_) {
182  error_recovered_ = true;
183  }
184  has_error_ = false;
186 }
187 
190 }
191 
192 bool FrankaCombinableHW::setRunFunction(const ControlMode& requested_control_mode,
193  const bool limit_rate,
194  const double cutoff_frequency,
195  const franka::ControllerMode /*internal_controller*/) {
196  using Callback = std::function<bool(const franka::RobotState&, franka::Duration)>;
197 
198  if (requested_control_mode == ControlMode::None) {
199  return true;
200  }
201  if (requested_control_mode == ControlMode::JointTorque) {
202  run_function_ = [this, limit_rate, cutoff_frequency](franka::Robot& robot,
203  Callback /*callback*/) {
204  robot.control(std::bind(&FrankaCombinableHW::libfrankaUpdateCallback<franka::Torques>, this,
205  std::cref(effort_joint_command_libfranka_), std::placeholders::_1,
206  std::placeholders::_2),
207  limit_rate, cutoff_frequency);
208  };
209  return true;
210  }
211 
212  ROS_ERROR("FrankaCombinableHW: No valid control mode selected; cannot set run function.");
213  return false;
214 }
215 
216 } // namespace franka_hw
217 
virtual void enforceLimits(const ros::Duration &period)
Enforces limits on position, velocity, and torque level.
Definition: franka_hw.cpp:211
virtual void setupFrankaModelInterface(franka::RobotState &robot_state)
Configures and registers the model interface offering kinematics and dynamics in ros_control.
Definition: franka_hw.cpp:391
std::unique_ptr< actionlib::SimpleActionServer< franka_msgs::ErrorRecoveryAction > > recovery_action_server_
void initRobot() override
Uses the robot_ip_ to connect to the robot via libfranka and loads the libfranka model.
virtual bool controllerActive() const noexcept
Indicates whether there is an active controller.
Definition: franka_hw.cpp:184
std::unique_ptr< std::thread > control_loop_thread_
void publish(const boost::shared_ptr< M > &message) const
void triggerError()
Triggers a stop of the controlLoop.
#define ROS_DEBUG_THROTTLE(rate,...)
franka::Torques effort_joint_command_ros_
Definition: franka_hw.h:492
A hardware class for a Panda robot based on the ros_control framework.
std::string getArmID() const noexcept
Getter method for the arm_id which is used to distinguish between multiple instances of FrankaCombina...
void initROSInterfaces(ros::NodeHandle &robot_hw_nh) override
Initializes the class in terms of ros_control interfaces.
virtual void checkJointLimits()
Checks the proximity of each joint to its joint position limits and prints a warning whenever a joint...
Definition: franka_hw.cpp:300
bool getArmClaimedMap(ResourceWithClaimsMap &resource_map, ArmClaimedMap &arm_claim_map)
bool setRunFunction(const ControlMode &requested_control_mode, bool limit_rate, double cutoff_frequency, franka::ControllerMode internal_controller) override
Configures the run function which is used as libfranka control callback based on the requested contro...
bool hasError() const noexcept
Getter for the error flag of the class.
franka::Torques effort_joint_command_libfranka_
Definition: franka_hw.h:485
std::string arm_id_
Definition: franka_hw.h:500
void control(const std::function< bool(const ros::Time &, const ros::Duration &)> &ros_callback=[](const ros::Time &, const ros::Duration &){return true;}) const override
Runs the currently active controller in a realtime loop.
std::map< std::string, ResourceClaims > ArmClaimedMap
franka::RobotState robot_state_ros_
Definition: franka_hw.h:480
std::mutex ros_state_mutex_
Definition: franka_hw.h:478
virtual void write(const ros::Time &time, const ros::Duration &period) override
Writes data to the franka robot.
Definition: franka_hw.cpp:349
void read(const ros::Time &, const ros::Duration &) override
Reads data from the franka robot.
virtual void initRobot()
Uses the robot_ip_ to connect to the robot via libfranka and loads the libfranka model.
Definition: franka_hw.cpp:510
std::mutex libfranka_cmd_mutex_
Definition: franka_hw.h:482
std::unique_ptr< franka::Robot > robot_
Definition: franka_hw.h:496
franka::RobotState robot_state_libfranka_
Definition: franka_hw.h:479
void setupServices(franka::Robot &robot, ros::NodeHandle &node_handle, ServiceContainer &services)
Sets up all services relevant for a libfranka robot inside a service container.
Definition: services.cpp:7
void resetError()
Recovers the libfranka robot, resets the error flag and publishes the error state.
hardware_interface::EffortJointInterface effort_joint_interface_
Definition: franka_hw.h:469
#define ROS_INFO(...)
void setupServicesAndActionServers(ros::NodeHandle &node_handle)
ROSCPP_DECL bool ok()
std::atomic_bool controller_active_
Definition: franka_hw.h:507
FrankaCombinableHW()
Creates an instance of FrankaCombinableHW.
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
std::map< std::string, std::vector< std::vector< std::string >>> ResourceWithClaimsMap
void setupJointCommandInterface(std::array< double, 7 > &command, franka::RobotState &state, bool use_q_d, T &interface)
Configures and registers a joint command interface for positions velocities or efforts in ros_control...
Definition: franka_hw.h:366
void write(const ros::Time &, const ros::Duration &period) override
Writes data to the franka robot.
virtual void read(const ros::Time &time, const ros::Duration &period) override
Reads data from the franka robot.
Definition: franka_hw.cpp:343
bool hasTrajectoryClaim(const ArmClaimedMap &arm_claim_map, const std::string &arm_id)
bool checkForConflict(const std::list< hardware_interface::ControllerInfo > &info) const override
Checks whether a requested controller can be run, based on the resources and interfaces it claims...
virtual void setupJointStateInterface(franka::RobotState &robot_state)
Configures and registers the joint state interface in ros_control.
Definition: franka_hw.cpp:359
virtual franka::Robot & robot() const
Getter for the libfranka robot instance.
Definition: franka_hw.cpp:334
bool partiallyClaimsArmJoints(const ArmClaimedMap &arm_claim_map, const std::string &arm_id)
static Time now()
virtual void setupFrankaStateInterface(franka::RobotState &robot_state)
Configures and registers the state interface offering the full franka::RobotState in ros_control...
Definition: franka_hw.cpp:368
std::function< void(franka::Robot &, Callback)> run_function_
Definition: franka_hw.h:513
std::array< double, 7 > tau_J
#define ROS_ERROR_STREAM(args)
bool controllerNeedsReset() const noexcept
Returns whether the controller needs to be reset e.g.
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
#define ROS_ERROR(...)
std::function< bool(const franka::RobotState &, franka::Duration)> Callback
Definition: franka_hw.h:269
ResourceWithClaimsMap getResourceMap(const std::list< hardware_interface::ControllerInfo > &info)
bool hasConflictingMultiClaim(const ResourceWithClaimsMap &resource_map)
std::mutex libfranka_state_mutex_
Definition: franka_hw.h:477
joint_limits_interface::EffortJointSoftLimitsInterface effort_joint_limit_interface_
Definition: franka_hw.h:475


franka_hw
Author(s): Franka Emika GmbH
autogenerated on Fri Oct 23 2020 03:47:05