srh_example_controller.cpp
Go to the documentation of this file.
1 
27 #include "../example/srh_example_controller.hpp"
28 #include <angles/angles.h>
30 #include <string>
31 
32 #include <std_msgs/Float64.h>
33 
34 // Register the controller to be able to load it with the controller manager.
36 
37 namespace controller
38 {
39 
40  SrhExampleController::SrhExampleController()
41  : SrController()
42  {
43  // This constructor is kept empty: the init functions
44  // are called by the controller manager when the controllers are started.
45  }
46 
48  {
49  // Stop subscribing to the command topic.
51  }
52 
53  bool SrhExampleController::init(ros_ethercat_model::RobotStateInterface *robot, ros::NodeHandle &n)
54  {
55  assert(robot);
56  node_ = n;
57 
58  // read the joint we're controlling from the parameter server.
59  std::string joint_name;
60  if (!node_.getParam("joint", joint_name))
61  {
62  ROS_ERROR("No joint given (namespace: %s)", node_.getNamespace().c_str());
63  return false;
64  }
65 
66  // set the state publisher for this controller:
67  // This publisher publishes interesting data for the current controller.
68  // (useful for debugging / tuning)
69  // Feel free to create a different message type, to publish more meaningful
70  // information for your controller (cf srh_mixed_position_velocity_controller.cpp)
73  (node_, "state", 1));
74 
75  // Calls the 2nd init function to finish initializing
76  return init(robot, joint_name);
77  }
78 
79  bool SrhExampleController::init(ros_ethercat_model::RobotStateInterface *robot, const std::string &joint_name)
80  {
81  ROS_ASSERT(robot);
82 
83  std::string robot_state_name;
84  node_.param<std::string>("robot_state_name", robot_state_name, "unique_robot_hw");
85 
86  try
87  {
88  robot_ = robot->getHandle(robot_state_name).getState();
89  }
91  {
92  ROS_ERROR_STREAM("Could not find robot state: " << robot_state_name << " Not loading the controller. " <<
93  e.what());
94  return false;
95  }
96 
97  // We need to store 2 different joint states for the joint 0s:
98  // They control the distal and the middle joint with the same control.
99  if (joint_name.substr(3, 1).compare("0") == 0)
100  {
101  has_j2 = true;
102 
103  // The joint 0 is name *FJ0, and is controlling *J1 + *J2.
104  std::string j1 = joint_name.substr(0, 3) + "1";
105  std::string j2 = joint_name.substr(0, 3) + "2";
106 
107  // Get the pointer to the joint state for *J1
108  joint_state_ = robot_->getJointState(j1);
109  if (!joint_state_)
110  {
111  ROS_ERROR("SrhMixedPositionVelocityController could not find joint named \"%s\"\n",
112  joint_name.c_str());
113  return false;
114  }
115 
116  // Get the pointer to the joint state for *J2
117  joint_state_2 = robot_->getJointState(j2);
118  if (!joint_state_2)
119  {
120  ROS_ERROR("SrhMixedPositionVelocityController could not find joint named \"%s\"\n",
121  joint_name.c_str());
122  return false;
123  }
124  }
125  else // "normal" joints: one controller controls one joint
126  {
127  has_j2 = false;
128 
129  // get the pointer to the joint state
130  joint_state_ = robot_->getJointState(joint_name);
131  if (!joint_state_)
132  {
133  ROS_ERROR("SrhMixedPositionVelocityController could not find joint named \"%s\"\n",
134  joint_name.c_str());
135  return false;
136  }
137  }
138 
139  // after init creates the subscriber to the /command topic
140  after_init();
141  return true;
142  }
143 
144 
146  {
147  // Here we set the command to be = to the current position
148  if (has_j2)
149  { // if it's *J0, then pos = *J1->pos + *J2->pos
150  command_ = joint_state_->position_ + joint_state_2->position_;
151  }
152  else
153  {
154  command_ = joint_state_->position_;
155  }
156  }
157 
158  void SrhExampleController::update(const ros::Time &time, const ros::Duration &period)
159  {
160  assert(robot_ != NULL);
161  assert(joint_state_->joint_);
162 
163  // make sure the controller has been initialised,
164  // to avoid sending a crazy command.
165  if (!initialized_)
166  {
167  starting(time);
168 
169  initialized_ = true;
170  }
171 
172  // compute the commanded effort you want to send
173  // to the motor: you can use whatever algorithm
174  // you want. To see more complex examples on how
175  // to use a pid loop / more than one loop, just
176  // go to the src directory, and have a look at
177  // srh_mixed_position_velocity_controller.cpp
178 
179  // we start by computing the position error
180  double error_position = 0.0;
181  if (has_j2)
182  {
183  // For *J0, the position error is equal to the command - (*J1 + *J2)
184  error_position = command_ - (joint_state_->position_ + joint_state_2->position_);
185  }
186  else
187  {
188  error_position = command_ - joint_state_->position_;
189  }
190 
191  // Here I'm simply doing a dummy P controller, with a fixed gain.
192  // It can't be used in the real life obviously. That's where you
193  // should WRITE YOUR ALGORITHM
194  double commanded_effort = 10 * error_position;
195 
196  // Update the commanded effort.
197  if (has_j2)
198  { // The motor in *J0 is attached to the *J2
199  joint_state_2->commanded_effort_ = commanded_effort;
200  }
201  else
202  {
203  joint_state_->commanded_effort_ = commanded_effort;
204  }
205 
206  if (loop_count_ % 10 == 0) // publishes the joint state at 100Hz
207  {
209  {
210  controller_state_publisher_->msg_.header.stamp = time;
211  controller_state_publisher_->msg_.set_point = command_;
212 
213  if (has_j2)
214  {
215  controller_state_publisher_->msg_.process_value = joint_state_->position_ + joint_state_2->position_;
216  controller_state_publisher_->msg_.process_value_dot = joint_state_->velocity_ + joint_state_2->velocity_;
217  }
218  else
219  {
220  controller_state_publisher_->msg_.process_value = joint_state_->position_;
221  controller_state_publisher_->msg_.process_value_dot = joint_state_->velocity_;
222  }
223 
224  controller_state_publisher_->msg_.error = error_position;
225  controller_state_publisher_->msg_.time_step = period.toSec();
226  controller_state_publisher_->msg_.command = commanded_effort;
227 
228  controller_state_publisher_->unlockAndPublish();
229  }
230  }
231  loop_count_++;
232  }
233 } // namespace controller
234 
235 /* For the emacs weenies in the crowd.
236 Local Variables:
237  c-basic-offset: 2
238 End:
239 */
240 
241 
ros_ethercat_model::JointState * joint_state_
boost::scoped_ptr< realtime_tools::RealtimePublisher< control_msgs::JointControllerState > > controller_state_publisher_
virtual void update(const ros::Time &time, const ros::Duration &period)
virtual void starting(const ros::Time &time)
ros_ethercat_model::JointState * joint_state_2
ros::Subscriber sub_command_
ros_ethercat_model::RobotState * robot_
bool init(ros_ethercat_model::RobotStateInterface *robot, ros::NodeHandle &n)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
const std::string & getNamespace() const
bool getParam(const std::string &key, std::string &s) const
#define ROS_ERROR_STREAM(args)
#define ROS_ASSERT(cond)
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
#define ROS_ERROR(...)
void after_init()
call this function at the end of the init function in the inheriting classes.


sr_mechanism_controllers
Author(s): Ugo Cupcic
autogenerated on Tue Oct 13 2020 03:55:58