noid_robot_hardware.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2018, Yohei Kakiuchi (JSK lab.)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the Open Source Robotics Foundation
18  * nor the names of its contributors may be
19  * used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *********************************************************************/
35 
36 /*
37  Author: Yohei Kakiuchi
38 */
39 
40 #include "noid_robot_hardware.h"
41 
42 #include <thread>
43 
44 namespace noid_robot_hardware
45 {
46 
47  bool NoidRobotHW::init(ros::NodeHandle& root_nh, ros::NodeHandle &robot_hw_nh)// add joint list
48  {
49  std::string port_upper("/dev/aero_upper");
50  std::string port_lower("/dev/aero_lower");
51 
52  // reading paramerters
53  if (robot_hw_nh.hasParam("port_upper")) robot_hw_nh.getParam("port_upper", port_upper);
54  if (robot_hw_nh.hasParam("port_lower")) robot_hw_nh.getParam("port_lower", port_lower);
55  if (robot_hw_nh.hasParam("robot_model")) robot_hw_nh.getParam("robot_model", robot_model);
56  if (robot_hw_nh.hasParam("/joint_settings/upper")) robot_hw_nh.getParam("/joint_settings/upper/name",joint_names_upper_);
57  else ROS_WARN("/joint_settings/upper read error");
58  if (robot_hw_nh.hasParam("/joint_settings/lower")) robot_hw_nh.getParam("/joint_settings/lower/name",joint_names_lower_);
59  else ROS_WARN("/joint_settings/lower read error");
60  if (robot_hw_nh.hasParam("controller_rate")) {
61  double rate;
62  robot_hw_nh.getParam("controller_rate", rate);
63  CONTROL_PERIOD_US_ = (1000*1000)/rate;
64  } else {
65  CONTROL_PERIOD_US_ = 50*1000; // 50ms
66  }
67  if (robot_hw_nh.hasParam("overlap_scale")) {
68  double scl;
69  robot_hw_nh.getParam("overlap_scale", scl);
70  OVERLAP_SCALE_ = scl; //
71  } else {
72  OVERLAP_SCALE_ = 2.8; //
73  }
74 
75  ROS_INFO("upper_port: %s", port_upper.c_str());
76  ROS_INFO("lower_port: %s", port_lower.c_str());
77  ROS_INFO("cycle: %f [ms], overlap_scale %f", CONTROL_PERIOD_US_*0.001, OVERLAP_SCALE_);
78 
79  // create controllersd
80  controller_upper_.reset(new NoidUpperController(port_upper));
81  controller_lower_.reset(new NoidLowerController(port_lower));
82 
83  // joint list
85 
87  for(int i = 0; i < number_of_angles_; i++) {
88  if(i < joint_names_upper_.size() ) joint_list_[i] = joint_names_upper_[i];
90  }
91 
92  prev_ref_positions_.resize(number_of_angles_);
93  initialized_flag_ = false;
94 
95  std::string model_str;
96  if (!root_nh.getParam("robot_description", model_str)) {
97  ROS_ERROR("Failed to get model from robot_description");
98  return false;
99  }
100  urdf::Model model;
101  if (!model.initString(model_str)) {
102  ROS_ERROR("Failed to parse robot_description");
103  return false;
104  }
105 
106  ROS_DEBUG("read %d joints", number_of_angles_);
107  for (int i = 0; i < number_of_angles_; i++) {
108  ROS_DEBUG(" %d: %s", i, joint_list_[i].c_str());
109  if(!model.getJoint(joint_list_[i])) {
110  ROS_ERROR("Joint %s does not exist in urdf model", joint_list_[i].c_str());
111  return false;
112  }
113  }
114 
115  // joint_names_.resize(number_of_angles_);
116  joint_types_.resize(number_of_angles_);
117  joint_control_methods_.resize(number_of_angles_);
118  joint_position_.resize(number_of_angles_);
119  joint_velocity_.resize(number_of_angles_);
120  joint_effort_.resize(number_of_angles_);
121  joint_position_command_.resize(number_of_angles_);
122  joint_velocity_command_.resize(number_of_angles_);
123  joint_effort_command_.resize(number_of_angles_);
124 
125  readPos(ros::Time::now(), ros::Duration(0.0), true);
126 
127  // Initialize values
128  for(unsigned int j = 0; j < number_of_angles_; j++) {
129  joint_velocity_[j] = 0.0;
130  joint_velocity_command_[j] = 0.0;
131  joint_effort_[j] = 0.0; // N/m for continuous joints
132  joint_effort_command_[j] = 0.0;
133 
134  std::string jointname = joint_list_[j];
135  // Create joint state interface for all joints
137 
140  pj_interface_.registerHandle(joint_handle);
141 
143  const bool urdf_limits_ok = joint_limits_interface::getJointLimits(model.getJoint(jointname), limits);
144  if (!urdf_limits_ok) {
145  ROS_WARN("urdf limits of joint %s is not defined", jointname.c_str());
146  }
147  // Register handle in joint limits interface
148  joint_limits_interface::PositionJointSaturationHandle limits_handle(joint_handle,limits); // Limits spec
149  pj_sat_interface_.registerHandle(limits_handle);
150  }
151  // Register interfaces
154 
155  return true;
156  }
157 
158  void NoidRobotHW::readPos(const ros::Time& time, const ros::Duration& period, bool update)
159  {
160 
161  mutex_lower_.lock();
162  mutex_upper_.lock();
163  if (update) {
164  std::thread t1([&](){
165  controller_upper_->getPosition();
166  });
167  std::thread t2([&](){
168  controller_lower_->getPosition();
169  });
170  t1.join();
171  t2.join();
172  }
173  mutex_upper_.unlock();
174  mutex_lower_.unlock();
175 
176  // whole body strokes
177  std::vector<int16_t> act_strokes(0);
178  std::vector<int16_t> act_upper_strokes (controller_upper_->DOF_);
179  std::vector<int16_t> act_lower_strokes (controller_lower_->DOF_);
180 
181  //remap
182  controller_upper_->remapAeroToRos(controller_upper_->raw_data_,act_upper_strokes);
183  controller_lower_->remapAeroToRos(controller_lower_->raw_data_,act_lower_strokes);
184 
185  act_strokes.insert(act_strokes.end(),act_upper_strokes.begin(),act_upper_strokes.end());
186  act_strokes.insert(act_strokes.end(),act_lower_strokes.begin(),act_lower_strokes.end());
187 
188  // whole body positions from strokes
189  std::vector<double> act_positions;
190  act_positions.resize(number_of_angles_);
191  //aero::common::Stroke2Angle(act_positions, act_strokes);
192  if(robot_model == "typeF") typef::Stroke2Angle(act_positions, act_strokes);
193  else ROS_ERROR("Not defined robot model, please check robot_model_name");
194 
195 
196  double tm = period.toSec();
197  for(unsigned int j=0; j < number_of_angles_; j++) {
198  float position = act_positions[j];
199  float velocity = 0.0;
200 
201  joint_position_[j] = position;
202  joint_velocity_[j] = velocity; // read velocity from HW
203  joint_effort_[j] = 0; // read effort from HW
204  }
205 
206  if (!initialized_flag_) {
207  for(unsigned int j = 0; j < number_of_angles_; j++) {
209  ROS_DEBUG("%d: %s - %f", j, joint_list_[j].c_str(), joint_position_command_[j]);
210  }
211  initialized_flag_ = true;
212  }
213 
214  return;
215  }
216 
217  void NoidRobotHW::read(const ros::Time& time, const ros::Duration& period)
218  {
219  return;
220  }
221 
222  void NoidRobotHW::write(const ros::Time& time, const ros::Duration& period)
223  {
225 
227  std::vector<double > ref_positions(number_of_angles_);
228  for(unsigned int j=0; j < number_of_angles_; j++) {
229  switch (joint_control_methods_[j]) {
230  case POSITION:
231  {
232  ref_positions[j] = joint_position_command_[j];
233  }
234  break;
235  case VELOCITY:
236  {
237  }
238  break;
239  case EFFORT:
240  {
241  }
242  break;
243  case POSITION_PID:
244  {
245  }
246  break;
247  case VELOCITY_PID:
248  {
249  }
250  break;
251  } // switch
252  } // for
253 
254  std::vector<bool > mask_positions(number_of_angles_);
255  std::fill(mask_positions.begin(), mask_positions.end(), true); // send if true
256 
257  for(int i = 0; i < number_of_angles_; i++) {
258  double tmp = ref_positions[i];
259  if (tmp == prev_ref_positions_[i]) {
260  mask_positions[i] = false;
261  }
262  prev_ref_positions_[i] = tmp;
263  }
264 
265  std::vector<int16_t> ref_strokes(controller_upper_->DOF_ + controller_lower_->DOF_);
266 
267  //aero::common::Angle2Stroke(ref_strokes, ref_positions);
268  if(robot_model == "typeF") typef::Angle2Stroke(ref_strokes, ref_positions);
269  else ROS_ERROR("Not defined robot model, please check robot_model_name");
270 
271  std::vector<int16_t> snt_strokes(ref_strokes);
272  noid::common::MaskRobotCommand(snt_strokes, mask_positions);
273 
274  // split strokes into upper and lower
275  size_t aero_array_size = 30;
276  std::vector<int16_t> upper_strokes(aero_array_size);
277  std::vector<int16_t> lower_strokes(aero_array_size);
278 
279  //remap
280  if(controller_upper_->is_open_) controller_upper_->remapRosToAero(snt_strokes, upper_strokes);
281  else controller_upper_->remapRosToAero(ref_strokes, upper_strokes);
282  if(controller_lower_->is_open_) controller_lower_->remapRosToAero(snt_strokes, lower_strokes);
283  else controller_lower_->remapRosToAero(ref_strokes, lower_strokes);
284 
285  uint16_t time_csec = static_cast<uint16_t>((OVERLAP_SCALE_ * CONTROL_PERIOD_US_)/(1000*10));
286 
287  mutex_lower_.lock();
288  mutex_upper_.lock();
289  {
290  std::thread t1([&](){
291  controller_upper_->sendPosition(time_csec, upper_strokes);
292  });
293  std::thread t2([&](){
294  controller_lower_->sendPosition(time_csec, lower_strokes);
295  });
296  t1.join();
297  t2.join();
298  }
299  mutex_upper_.unlock();
300  mutex_lower_.unlock();
301 
302  // read
303  readPos(time, period, false);
304  return;
305  }
306 
308 // specific functions are below: ///
310  void NoidRobotHW::runHandScript(uint8_t _number, uint16_t _script, uint8_t _current)
311  {
312  mutex_upper_.lock();
313  if(_script == 2){
314  controller_upper_->runScript(_number, 4);
315  usleep(20 * 1000); //magic number
316  controller_upper_->setCurrent(_number, _current, _current);
317  }
318  controller_upper_->runScript(_number, _script);
319  ROS_INFO("sendnum : %d, script : %d", _number, _script);
320  mutex_upper_.unlock();
321  }
322 
323  void NoidRobotHW::writeWheel(std::vector<int16_t> &_vel)
324  {
325  mutex_lower_.lock();
326  controller_lower_->sendVelocity(_vel);
327  mutex_lower_.unlock();
328  }
329 
330  void NoidRobotHW::onWheelServo(bool _value)
331  {
332  mutex_lower_.lock();
333  controller_lower_->onServo(_value);
334  mutex_lower_.unlock();
335  }
336 
337 }
boost::shared_ptr< NoidLowerController > controller_lower_
boost::shared_ptr< NoidUpperController > controller_upper_
std::vector< std::string > joint_names_upper_
std::vector< std::string > joint_list_
URDF_EXPORT bool initString(const std::string &xmlstring)
hardware_interface::PositionJointInterface pj_interface_
std::vector< double > prev_ref_positions_
void Angle2Stroke(std::vector< int16_t > &_strokes, const std::vector< double > _angles)
std::vector< JointType > joint_types_
joint_limits_interface::PositionJointSaturationInterface pj_sat_interface_
std::vector< double > joint_position_command_
#define ROS_WARN(...)
void enforceLimits(const ros::Duration &period)
virtual void write(const ros::Time &time, const ros::Duration &period)
void writeWheel(const std::vector< std::string > &_names, const std::vector< int16_t > &_vel, double _tm_sec)
rate
#define ROS_INFO(...)
void readPos(const ros::Time &time, const ros::Duration &period, bool update)
void Stroke2Angle(std::vector< double > &_angles, const std::vector< int16_t > _strokes)
std::vector< ControlMethod > joint_control_methods_
void registerHandle(const JointStateHandle &handle)
std::vector< double > joint_effort_command_
void MaskRobotCommand(std::vector< int16_t > &_strokes, const std::vector< bool > _angles)
JointStateHandle getHandle(const std::string &name)
hardware_interface::JointStateInterface js_interface_
bool getParam(const std::string &key, std::string &s) const
void runHandScript(uint8_t _number, uint16_t _script, uint8_t _current)
bool getJointLimits(urdf::JointConstSharedPtr urdf_joint, JointLimits &limits)
static Time now()
virtual bool init(ros::NodeHandle &root_nh, ros::NodeHandle &robot_hw_nh)
bool hasParam(const std::string &key) const
std::vector< double > joint_velocity_command_
#define ROS_ERROR(...)
std::vector< std::string > joint_names_lower_
virtual void read(const ros::Time &time, const ros::Duration &period)
#define ROS_DEBUG(...)


noid_ros_controller
Author(s): Yohei Kakiuchi
autogenerated on Sat Jul 20 2019 03:44:30