franka_control_node.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017 Franka Emika GmbH
2 // Use of this source code is governed by the Apache-2.0 license, see LICENSE
3 #include <algorithm>
4 #include <atomic>
5 #include <chrono>
6 #include <thread>
7 
10 #include <franka/exception.h>
11 #include <franka/robot.h>
12 #include <franka_hw/franka_hw.h>
13 #include <franka_hw/services.h>
14 #include <franka_msgs/ErrorRecoveryAction.h>
15 #include <ros/ros.h>
16 #include <std_srvs/Trigger.h>
17 
19 using namespace std::chrono_literals;
20 
21 int main(int argc, char** argv) {
22  ros::init(argc, argv, "franka_control_node");
23 
24  ros::NodeHandle public_node_handle;
25  ros::NodeHandle node_handle("~");
26 
28  if (!franka_control.init(public_node_handle, node_handle)) {
29  ROS_ERROR("franka_control_node: Failed to initialize FrankaHW class. Shutting down!");
30  return 1;
31  }
32 
33  auto services = std::make_unique<ServiceContainer>();
34  std::unique_ptr<actionlib::SimpleActionServer<franka_msgs::ErrorRecoveryAction>>
35  recovery_action_server;
36 
37  std::atomic_bool has_error(false);
38 
39  auto connect = [&]() {
40  franka_control.connect();
41  std::lock_guard<std::mutex> lock(franka_control.robotMutex());
42  auto& robot = franka_control.robot();
43 
44  services = std::make_unique<ServiceContainer>();
45  franka_hw::setupServices(robot, franka_control.robotMutex(), node_handle, *services);
46 
47  recovery_action_server =
48  std::make_unique<actionlib::SimpleActionServer<franka_msgs::ErrorRecoveryAction>>(
49  node_handle, "error_recovery",
50  [&](const franka_msgs::ErrorRecoveryGoalConstPtr&) {
51  try {
52  std::lock_guard<std::mutex> lock(franka_control.robotMutex());
53  robot.automaticErrorRecovery();
54  has_error = false;
55  recovery_action_server->setSucceeded();
56  ROS_INFO("Recovered from error");
57  } catch (const franka::Exception& ex) {
58  recovery_action_server->setAborted(franka_msgs::ErrorRecoveryResult(), ex.what());
59  }
60  },
61  false);
62 
63  recovery_action_server->start();
64 
65  // Initialize robot state before loading any controller
66  franka_control.update(robot.readOnce());
67  };
68 
69  auto disconnect_handler = [&](std_srvs::Trigger::Request& request,
70  std_srvs::Trigger::Response& response) -> bool {
71  if (franka_control.controllerActive()) {
72  response.success = 0u;
73  response.message = "Controller is active. Cannot disconnect while a controller is running.";
74  return true;
75  }
76  services.reset();
77  recovery_action_server.reset();
78  auto result = franka_control.disconnect();
79  response.success = result ? 1u : 0u;
80  response.message = result ? "" : "Failed to disconnect robot.";
81  return true;
82  };
83 
84  auto connect_handler = [&](std_srvs::Trigger::Request& request,
85  std_srvs::Trigger::Response& response) -> bool {
86  if (franka_control.connected()) {
87  response.success = 0u;
88  response.message = "Already connected to robot. Cannot connect twice.";
89  return true;
90  }
91 
92  connect();
93 
94  response.success = 1u;
95  response.message = "";
96  return true;
97  };
98 
99  connect();
100 
101  ros::ServiceServer connect_server =
102  node_handle.advertiseService<std_srvs::Trigger::Request, std_srvs::Trigger::Response>(
103  "connect", connect_handler);
104  ros::ServiceServer disconnect_server =
105  node_handle.advertiseService<std_srvs::Trigger::Request, std_srvs::Trigger::Response>(
106  "disconnect", disconnect_handler);
107 
108  controller_manager::ControllerManager control_manager(&franka_control, public_node_handle);
109 
110  // Start background threads for message handling
112  spinner.start();
113 
114  while (ros::ok()) {
115  ros::Time last_time = ros::Time::now();
116 
117  // Wait until controller has been activated or error has been recovered
118  while (!franka_control.controllerActive() || has_error) {
119  if (franka_control.connected()) {
120  try {
121  std::lock_guard<std::mutex> lock(franka_control.robotMutex());
122  franka_control.update(franka_control.robot().readOnce());
123  ros::Time now = ros::Time::now();
124  control_manager.update(now, now - last_time);
125  franka_control.checkJointLimits();
126  last_time = now;
127  } catch (const std::logic_error& e) {
128  }
129  } else {
130  std::this_thread::sleep_for(1ms);
131  }
132 
133  if (!ros::ok()) {
134  return 0;
135  }
136  }
137 
138  if (franka_control.connected()) {
139  try {
140  // Run control loop. Will exit if the controller is switched.
141  franka_control.control([&](const ros::Time& now, const ros::Duration& period) {
142  if (period.toSec() == 0.0) {
143  // Reset controllers before starting a motion
144  control_manager.update(now, period, true);
145  franka_control.checkJointLimits();
146  franka_control.reset();
147  } else {
148  control_manager.update(now, period);
149  franka_control.checkJointLimits();
150  franka_control.enforceLimits(period);
151  }
152  return ros::ok();
153  });
154  } catch (const franka::ControlException& e) {
155  ROS_ERROR("%s", e.what());
156  has_error = true;
157  }
158  }
159  ROS_INFO_THROTTLE(1, "franka_control, main loop");
160  }
161 
162  return 0;
163 }
virtual std::mutex & robotMutex()
virtual void enforceLimits(const ros::Duration &period)
RobotState readOnce()
virtual void connect()
virtual void reset()
void setupServices(franka::Robot &robot, std::mutex &robot_mutex, ros::NodeHandle &node_handle, ServiceContainer &services)
virtual bool controllerActive() const noexcept
virtual void update(const franka::RobotState &robot_state)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
virtual void checkJointLimits()
#define ROS_ERROR(...)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
void spinner()
virtual bool connected()
int main(int argc, char **argv)
#define ROS_INFO_THROTTLE(period,...)
#define ROS_INFO(...)
virtual bool disconnect()
ROSCPP_DECL bool ok()
virtual void control(const std::function< bool(const ros::Time &, const ros::Duration &)> &ros_callback)
static Time now()
virtual bool init(ros::NodeHandle &root_nh, ros::NodeHandle &robot_hw_nh) override
virtual franka::Robot & robot() const
const std::string response


franka_control
Author(s): Franka Emika GmbH
autogenerated on Mon Sep 19 2022 03:05:59