robotiq_2f_gripper_action_server.cpp
Go to the documentation of this file.
1 
7 
8 // To keep the fully qualified names managable
9 
10 //Anonymous namespaces are file local -> sort of like global static objects
11 namespace
12 {
13  using namespace robotiq_2f_gripper_action_server;
14 
15  /* This struct is declared for the sole purpose of being used as an exception internally
16  to keep the code clean (i.e. no output params). It is caught by the action_server and
17  should not propogate outwards. If you use these functions yourself, beware.
18  */
19  struct BadArgumentsError {};
20 
21 
22  GripperOutput goalToRegisterState(const GripperCommandGoal& goal, const Robotiq2FGripperParams& params)
23  {
24  GripperOutput result;
25  result.rACT = 0x1; // active gripper
26  result.rGTO = 0x1; // go to position
27  result.rATR = 0x0; // No emergency release
28  result.rSP = 128; // Middle ground speed
29 
30  if (goal.command.position > params.max_gap_ || goal.command.position < params.min_gap_)
31  {
32  ROS_WARN("Goal gripper gap size is out of range(%f to %f): %f m",
33  params.min_gap_, params.max_gap_, goal.command.position);
34  throw BadArgumentsError();
35  }
36 
37  if (goal.command.max_effort < params.min_effort_ || goal.command.max_effort > params.max_effort_)
38  {
39  ROS_WARN("Goal gripper effort out of range (%f to %f N): %f N",
40  params.min_effort_, params.max_effort_, goal.command.max_effort);
41  throw BadArgumentsError();
42  }
43 
44  double dist_per_tick = (params.max_gap_ - params.min_gap_) / 255;
45  double eff_per_tick = (params.max_effort_ - params.min_effort_) / 255;
46 
47  result.rPR = static_cast<uint8_t>((params.max_gap_ - goal.command.position) / dist_per_tick);
48  result.rFR = static_cast<uint8_t>((goal.command.max_effort - params.min_effort_) / eff_per_tick);
49 
50  ROS_INFO("Setting goal position register to %hhu", result.rPR);
51 
52  return result;
53  }
54 
55  /* This function is templatized because both GripperCommandResult and GripperCommandFeedback consist
56  of the same fields yet have different types. Templates here act as a "duck typing" mechanism to avoid
57  code duplication.
58  */
59  template<typename T>
60  T registerStateToResultT(const GripperInput& input, const Robotiq2FGripperParams& params, uint8_t goal_pos)
61  {
62  T result;
63  double dist_per_tick = (params.max_gap_ - params.min_gap_) / 255;
64  double eff_per_tick = (params.max_effort_ - params.min_effort_) / 255;
65 
66  result.position = input.gPO * dist_per_tick + params.min_gap_;
67  result.effort = input.gCU * eff_per_tick + params.min_effort_;
68  result.stalled = input.gOBJ == 0x1 || input.gOBJ == 0x2;
69  result.reached_goal = input.gPO == goal_pos;
70 
71  return result;
72  }
73 
74  // Inline api-transformers to avoid confusion when reading the action_server source
75  inline
76  GripperCommandResult registerStateToResult(const GripperInput& input, const Robotiq2FGripperParams& params, uint8_t goal_pos)
77  {
78  return registerStateToResultT<GripperCommandResult>(input, params, goal_pos);
79  }
80 
81  inline
82  GripperCommandFeedback registerStateToFeedback(const GripperInput& input, const Robotiq2FGripperParams& params, uint8_t goal_pos)
83  {
84  return registerStateToResultT<GripperCommandFeedback>(input, params, goal_pos);
85  }
86 
87 } // end of anon namespace
88 
90 {
91 
93  : nh_()
94  , as_(nh_, name, false)
95  , action_name_(name)
96  , gripper_params_(params)
97 {
100 
102  goal_pub_ = nh_.advertise<GripperOutput>("output", 1);
103 
104  as_.start();
105 }
106 
108 {
109  // Check to see if the gripper is in an active state where it can take goals
110  if (current_reg_state_.gSTA != 0x3)
111  {
112  ROS_WARN("%s could not accept goal because the gripper is not yet active", action_name_.c_str());
113  return;
114  }
115 
116  GripperCommandGoal current_goal (*(as_.acceptNewGoal()));
117 
118  if (as_.isPreemptRequested())
119  {
120  as_.setPreempted();
121  }
122 
123  try
124  {
125  goal_reg_state_ = goalToRegisterState(current_goal, gripper_params_);
127  }
128  catch (BadArgumentsError& e)
129  {
130  ROS_INFO("%s No goal issued to gripper", action_name_.c_str());
131  }
132 }
133 
135 {
136  ROS_INFO("%s: Preempted", action_name_.c_str());
137  as_.setPreempted();
138 }
139 
140 void Robotiq2FGripperActionServer::analysisCB(const GripperInput::ConstPtr& msg)
141 {
142  current_reg_state_ = *msg;
143 
144  if (!as_.isActive()) return;
145 
146  // Check to see if the gripper is in its activated state
147  if (current_reg_state_.gSTA != 0x3)
148  {
149  // Check to see if the gripper is active or if it has been asked to be active
150  if (current_reg_state_.gSTA == 0x0 && goal_reg_state_.rACT != 0x1)
151  {
152  // If it hasn't been asked, active it
153  issueActivation();
154  }
155 
156  // Otherwise wait for the gripper to activate
157  // TODO: If message delivery isn't guaranteed, then we may want to resend activate
158  return;
159  }
160 
161  // Check for errors
162  if (current_reg_state_.gFLT)
163  {
164  ROS_WARN("%s faulted with code: %x", action_name_.c_str(), current_reg_state_.gFLT);
165  as_.setAborted(registerStateToResult(current_reg_state_,
167  goal_reg_state_.rPR));
168  }
169  else if (current_reg_state_.gGTO && current_reg_state_.gOBJ && current_reg_state_.gPR == goal_reg_state_.rPR)
170  {
171  // If commanded to move and if at a goal state and if the position request matches the echo'd PR, we're
172  // done with a move
173  ROS_INFO("%s succeeded", action_name_.c_str());
174  as_.setSucceeded(registerStateToResult(current_reg_state_,
176  goal_reg_state_.rPR));
177  }
178  else
179  {
180  // Publish feedback
181  as_.publishFeedback(registerStateToFeedback(current_reg_state_,
183  goal_reg_state_.rPR));
184  }
185 }
186 
188 {
189  ROS_INFO("Activating gripper for gripper action server: %s", action_name_.c_str());
190  GripperOutput out;
191  out.rACT = 0x1;
192  // other params should be zero
193  goal_reg_state_ = out;
194  goal_pub_.publish(out);
195 }
196 } // end robotiq_2f_gripper_action_server namespace
control_msgs::GripperCommandResult GripperCommandResult
boost::shared_ptr< const Goal > acceptNewGoal()
void publishFeedback(const FeedbackConstPtr &feedback)
void publish(const boost::shared_ptr< M > &message) const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
robotiq_2f_gripper_control::Robotiq2FGripper_robot_output GripperOutput
unsigned char uint8_t
#define ROS_WARN(...)
void setSucceeded(const Result &result=Result(), const std::string &text=std::string(""))
robotiq_2f_gripper_control::Robotiq2FGripper_robot_input GripperInput
void setPreempted(const Result &result=Result(), const std::string &text=std::string(""))
control_msgs::GripperCommandFeedback GripperCommandFeedback
actionlib::SimpleActionServer< control_msgs::GripperCommandAction > as_
#define ROS_INFO(...)
void registerPreemptCallback(boost::function< void()> cb)
Robotiq2FGripperActionServer(const std::string &name, const Robotiq2FGripperParams &params)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
control_msgs::GripperCommandGoal GripperCommandGoal
void setAborted(const Result &result=Result(), const std::string &text=std::string(""))
void registerGoalCallback(boost::function< void()> cb)
Structure containing the parameters necessary to translate GripperCommand actions to register-based c...


robotiq_2f_gripper_action_server
Author(s): Jonathan Meyer
autogenerated on Tue Jun 1 2021 02:29:56