open_cr_module.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright 2017 ROBOTIS CO., LTD.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16 
17 /* Author: Kayman */
18 
19 #include <stdio.h>
20 
22 
23 namespace robotis_op
24 {
25 
27  : control_cycle_msec_(8),
28  DEBUG_PRINT(false),
29  present_volt_(0.0)
30 {
31  module_name_ = "open_cr_module"; // set unique module name
32 
33  result_["gyro_x"] = 0.0;
34  result_["gyro_y"] = 0.0;
35  result_["gyro_z"] = 0.0;
36 
37  result_["acc_x"] = 0.0;
38  result_["acc_y"] = 0.0;
39  result_["acc_z"] = 0.0;
40 
41  result_["button_mode"] = 0;
42  result_["button_start"] = 0;
43  result_["button_user"] = 0;
44 
45  result_["present_voltage"] = 0.0;
46 
47  buttons_["button_mode"] = false;
48  buttons_["button_start"] = false;
49  buttons_["button_user"] = false;
50  buttons_["published_mode"] = false;
51  buttons_["published_start"] = false;
52  buttons_["published_user"] = false;
53 
54  previous_result_["gyro_x"] = 0.0;
55  previous_result_["gyro_y"] = 0.0;
56  previous_result_["gyro_z"] = 0.0;
57 
58  previous_result_["gyro_x_prev"] = 0.0;
59  previous_result_["gyro_y_prev"] = 0.0;
60  previous_result_["gyro_z_prev"] = 0.0;
61 
62  previous_result_["acc_x"] = 0.0;
63  previous_result_["acc_y"] = 0.0;
64  previous_result_["acc_z"] = 0.0;
65 
67 }
68 
70 {
71  queue_thread_.join();
72 }
73 
74 void OpenCRModule::initialize(const int control_cycle_msec, robotis_framework::Robot *robot)
75 {
76  control_cycle_msec_ = control_cycle_msec;
77  queue_thread_ = boost::thread(boost::bind(&OpenCRModule::queueThread, this));
78 }
79 
81 {
82  ros::NodeHandle ros_node;
83  ros::CallbackQueue callback_queue;
84 
85  ros_node.setCallbackQueue(&callback_queue);
86 
87  /* publisher */
88  status_msg_pub_ = ros_node.advertise<robotis_controller_msgs::StatusMsg>("/robotis/status", 1);
89  imu_pub_ = ros_node.advertise<sensor_msgs::Imu>("/robotis/open_cr/imu", 1);
90  button_pub_ = ros_node.advertise<std_msgs::String>("/robotis/open_cr/button", 1);
91  dxl_power_msg_pub_ = ros_node.advertise<robotis_controller_msgs::SyncWriteItem>("/robotis/sync_write_item", 0);
92 
93  ros::WallDuration duration(control_cycle_msec_ / 1000.0);
94  while (ros_node.ok())
95  callback_queue.callAvailable(duration);
96 }
97 
98 void OpenCRModule::process(std::map<std::string, robotis_framework::Dynamixel *> dxls,
99  std::map<std::string, robotis_framework::Sensor *> sensors)
100 {
101  if (sensors["open-cr"] == NULL)
102  return;
103 
104  int16_t gyro_x = sensors["open-cr"]->sensor_state_->bulk_read_table_["gyro_x"];
105  int16_t gyro_y = sensors["open-cr"]->sensor_state_->bulk_read_table_["gyro_y"];
106  int16_t gyro_z = sensors["open-cr"]->sensor_state_->bulk_read_table_["gyro_z"];
107 
108  int16_t acc_x = sensors["open-cr"]->sensor_state_->bulk_read_table_["acc_x"];
109  int16_t acc_y = sensors["open-cr"]->sensor_state_->bulk_read_table_["acc_y"];
110  int16_t acc_z = sensors["open-cr"]->sensor_state_->bulk_read_table_["acc_z"];
111 
112  uint16_t present_volt = sensors["open-cr"]->sensor_state_->bulk_read_table_["present_voltage"];
113 
114  result_["gyro_x"] = lowPassFilter(0.4, -getGyroValue(gyro_x), previous_result_["gyro_x"]);
115  result_["gyro_y"] = lowPassFilter(0.4, -getGyroValue(gyro_y), previous_result_["gyro_y"]);
116  result_["gyro_z"] = lowPassFilter(0.4, getGyroValue(gyro_z), previous_result_["gyro_z"]);
117 
118  ROS_INFO_COND(DEBUG_PRINT, " ======================= Gyro ======================== ");
119  ROS_INFO_COND(DEBUG_PRINT, "Raw : %d, %d, %d", gyro_x, gyro_y, gyro_z);
120  ROS_INFO_COND(DEBUG_PRINT, "Filtered : %f, %f, %f", result_["gyro_x"], result_["gyro_y"], result_["gyro_z"]);
121 
122  // align axis of Accelerometer to robot and
123  result_["acc_x"] = lowPassFilter(0.4, -getAccValue(acc_x), previous_result_["acc_x"]);
124  result_["acc_y"] = lowPassFilter(0.4, -getAccValue(acc_y), previous_result_["acc_y"]);
125  result_["acc_z"] = lowPassFilter(0.4, getAccValue(acc_z), previous_result_["acc_z"]);
126 
127  ROS_INFO_COND(DEBUG_PRINT, " ======================= Acc ======================== ");
128  ROS_INFO_COND(DEBUG_PRINT, "Raw : %d, %d, %d", acc_x, acc_y, acc_z);
129  ROS_INFO_COND(DEBUG_PRINT, "Filtered : %f, %f, %f", result_["acc_x"], result_["acc_y"], result_["acc_z"]);
130 
131  ros::Time update_time;
132  update_time.sec = sensors["open-cr"]->sensor_state_->update_time_stamp_.sec_;
133  update_time.nsec = sensors["open-cr"]->sensor_state_->update_time_stamp_.nsec_;
134  ros::Duration update_duration = ros::Time::now() - update_time;
135  if ((update_duration.sec * 1000000000 + update_duration.nsec) > 100000000)
137 
138  uint8_t button_flag = sensors["open-cr"]->sensor_state_->bulk_read_table_["button"];
139  result_["button_mode"] = button_flag & 0x01;
140  result_["button_start"] = (button_flag & 0x02) >> 1;
141  result_["button_user"] = (button_flag & 0x04) >> 2;
142 
143  handleButton("mode");
144  handleButton("start");
145  handleButton("user");
146 
147  result_["present_voltage"] = present_volt * 0.1;
148  handleVoltage(result_["present_voltage"]);
149 
150  publishIMU();
151 
152  previous_result_["gyro_x_prev"] = result_["gyro_x"];
153  previous_result_["gyro_y_prev"] = result_["gyro_y"];
154  previous_result_["gyro_z_prev"] = result_["gyro_z"];
155 }
156 
157 // -2000 ~ 2000dps(-32800 ~ 32800), scale factor : 16.4, dps -> rps
158 double OpenCRModule::getGyroValue(int raw_value)
159 {
160  return (double) raw_value * GYRO_FACTOR * DEGREE2RADIAN;
161 }
162 
163 // -2.0 ~ 2.0g(-32768 ~ 32768), 1g = 9.8 m/s^2
164 double OpenCRModule::getAccValue(int raw_value)
165 {
166  return (double) raw_value * ACCEL_FACTOR;
167 }
168 
170 {
171  // fusion imu data
172  imu_msg_.header.stamp = ros::Time::now();
173  imu_msg_.header.frame_id = "body_link";
174  double filter_alpha = 0.4;
175 
176  //in rad/s
177  long int _value = 0;
178  int _arrd_length = 2;
179 
180  imu_msg_.angular_velocity.x = result_["gyro_x"];
181  imu_msg_.angular_velocity.y = result_["gyro_y"];
182  imu_msg_.angular_velocity.z = result_["gyro_z"];
183 
184  //in m/s^2
185  imu_msg_.linear_acceleration.x = result_["acc_x"] * G_ACC;
186  imu_msg_.linear_acceleration.y = result_["acc_y"] * G_ACC;
187  imu_msg_.linear_acceleration.z = result_["acc_z"] * G_ACC;
188 
189  //Estimation of roll and pitch based on accelometer data, see http://www.nxp.com/files/sensors/doc/app_note/AN3461.pdf
190  double mui = 0.01;
191  double sign = copysignf(1.0, result_["acc_z"]);
192  double roll = atan2(result_["acc_y"],
193  sign * sqrt(result_["acc_z"] * result_["acc_z"] + mui * result_["acc_x"] * result_["acc_x"]));
194  double pitch = atan2(-result_["acc_x"],
195  sqrt(result_["acc_y"] * result_["acc_y"] + result_["acc_z"] * result_["acc_z"]));
196  double yaw = 0.0;
197 
198  Eigen::Quaterniond orientation = robotis_framework::convertRPYToQuaternion(roll, pitch, yaw);
199 
200  imu_msg_.orientation.x = orientation.x();
201  imu_msg_.orientation.y = orientation.y();
202  imu_msg_.orientation.z = orientation.z();
203  imu_msg_.orientation.w = orientation.w();
204 
206 }
207 
208 void OpenCRModule::handleButton(const std::string &button_name)
209 {
210  std::string button_key = "button_" + button_name;
211  std::string button_published = "published_" + button_name;
212 
213  bool pushed = (result_[button_key] == 1.0);
214  // same state
215  if (buttons_[button_key] == pushed)
216  {
217  if (pushed == true && buttons_[button_published] == false)
218  {
219  // check long press
220  ros::Duration button_duration = ros::Time::now() - buttons_press_time_[button_name];
221  if (button_duration.toSec() > 2.0)
222  {
223  publishButtonMsg(button_name + "_long");
224  buttons_[button_published] = true;
225  }
226  }
227  }
228  else // state is changed
229  {
230  buttons_[button_key] = pushed;
231 
232  if (pushed == true)
233  {
234  buttons_press_time_[button_name] = ros::Time::now();
235  buttons_[button_published] = false;
236  }
237  else
238  {
239  ros::Duration button_duration = ros::Time::now() - buttons_press_time_[button_name];
240 
241  if (button_duration.toSec() < 2.0) // short press
242  publishButtonMsg(button_name);
243  else
244  // long press
245  ;
246  }
247  }
248 }
249 
250 void OpenCRModule::publishButtonMsg(const std::string &button_name)
251 {
252  std_msgs::String button_msg;
253  button_msg.data = button_name;
254 
255  button_pub_.publish(button_msg);
256  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_INFO, "Button : " + button_name);
257 }
258 
259 void OpenCRModule::handleVoltage(double present_volt)
260 {
261  double voltage_ratio = 0.4;
263  (previous_volt_ != 0) ? previous_volt_ * (1 - voltage_ratio) + present_volt * voltage_ratio : present_volt;
264 
265  if (fabs(present_volt_ - previous_volt_) >= 0.1)
266  {
267  // check last publised time
268  ros::Time now = ros::Time::now();
269  ros::Duration dur = now - last_msg_time_;
270  if (dur.sec < 1)
271  return;
272 
273  last_msg_time_ = now;
274 
276  std::stringstream log_stream;
277  log_stream << "Present Volt : " << present_volt_ << "V";
279  (present_volt_ < 11 ?
280  robotis_controller_msgs::StatusMsg::STATUS_WARN : robotis_controller_msgs::StatusMsg::STATUS_INFO),
281  log_stream.str());
282  ROS_INFO_COND(DEBUG_PRINT, "Present Volt : %fV, Read Volt : %fV", previous_volt_, result_["present_voltage"]);
283  }
284 }
285 
286 void OpenCRModule::publishStatusMsg(unsigned int type, std::string msg)
287 {
288  robotis_controller_msgs::StatusMsg status_msg;
289  status_msg.header.stamp = ros::Time::now();
290  status_msg.type = type;
291  status_msg.module_name = "SENSOR";
292  status_msg.status_msg = msg;
293 
294  status_msg_pub_.publish(status_msg);
295 }
296 
297 void OpenCRModule::publishDXLPowerMsg(unsigned int value)
298 {
299  robotis_controller_msgs::SyncWriteItem sync_write_msg;
300  sync_write_msg.item_name = "dynamixel_power";
301  sync_write_msg.joint_name.push_back("open-cr");
302  sync_write_msg.value.push_back(value);
303 
304  dxl_power_msg_pub_.publish(sync_write_msg);
305 }
306 
307 double OpenCRModule::lowPassFilter(double alpha, double x_new, double &x_old)
308 {
309  double filtered_value = alpha * x_new + (1.0 - alpha) * x_old;
310  x_old = filtered_value;
311 
312  return filtered_value;
313 }
314 
315 }
void process(std::map< std::string, robotis_framework::Dynamixel * > dxls, std::map< std::string, robotis_framework::Sensor * > sensors)
ros::Publisher button_pub_
void publish(const boost::shared_ptr< M > &message) const
std::map< std::string, ros::Time > buttons_press_time_
ros::Publisher dxl_power_msg_pub_
double sign(double x)
Eigen::Quaterniond convertRPYToQuaternion(double roll, double pitch, double yaw)
void handleVoltage(double present_volt)
double lowPassFilter(double alpha, double x_new, double &x_old)
void publishStatusMsg(unsigned int type, std::string msg)
double getAccValue(int raw_value)
std::map< std::string, double > result_
boost::thread queue_thread_
ros::Publisher status_msg_pub_
void publishButtonMsg(const std::string &button_name)
void setCallbackQueue(CallbackQueueInterface *queue)
#define DEGREE2RADIAN
sensor_msgs::Imu imu_msg_
std::map< std::string, double > previous_result_
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define ROS_INFO_COND(cond,...)
static Time now()
void publishDXLPowerMsg(unsigned int value)
bool ok() const
void handleButton(const std::string &button_name)
double getGyroValue(int raw_value)
void initialize(const int control_cycle_msec, robotis_framework::Robot *robot)
std::map< std::string, bool > buttons_


open_cr_module
Author(s): Kayman
autogenerated on Mon Jun 10 2019 14:41:27