action_module.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright 2018 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 /*
18  * action_module.h
19  *
20  * Created on: 2016. 2. 23.
21  * Author: Jay Song
22  */
23 
24 #include <stdio.h>
25 #include <sstream>
26 
28 
29 using namespace thormang3;
30 
32  std::ostringstream ostr;
33  ostr << n;
34  return ostr.str();
35 }
36 
39  PRE_SECTION(0),
40  MAIN_SECTION(1),
41  POST_SECTION(2),
42  PAUSE_SECTION(3),
43  ZERO_FINISH(0),
45 {
47  /**************************************
48  * Section /----\
49  * /| |\
50  * /+---------/ | | \
51  * / | | | | \
52  * -----/ | | | | \----
53  * PRE MAIN PRE MAIN POST PAUSE
54  ***************************************/
55 
56  enable_ = false;
57  module_name_ = "action_module"; // set unique module name
59 
61  action_file_ = 0;
62  playing_ = false;
63  first_driving_start_ = false;
64  playing_finished_ = true;
65  page_step_count_ = 0;
66  play_page_idx_ = 0;
67  stop_playing_ = true;
68 
69  action_module_enabled_ = false;
70  previous_running_ = false;
71  present_running_ = false;
72 
73 }
74 
76 {
77  queue_thread_.join();
78 
80  if(action_file_ != 0)
81  fclose( action_file_ );
82 }
83 
84 void ActionModule::initialize(const int control_cycle_msec, robotis_framework::Robot *robot)
85 {
86  control_cycle_msec_ = control_cycle_msec;
87  queue_thread_ = boost::thread(boost::bind(&ActionModule::queueThread, this));
88 
89  for(std::map<std::string, robotis_framework::Dynamixel*>::iterator it = robot->dxls_.begin(); it != robot->dxls_.end(); it++)
90  {
91  std::string joint_name = it->first;
92  robotis_framework::Dynamixel* dxl_info = it->second;
93 
94  joint_name_to_id_[joint_name] = dxl_info->id_;
95  joint_id_to_name_[dxl_info->id_] = joint_name;
97  action_result_[joint_name]->goal_position_ = dxl_info->dxl_state_->goal_position_;
98  result_[joint_name] = new robotis_framework::DynamixelState();
99  result_[joint_name]->goal_position_ = dxl_info->dxl_state_->goal_position_;
100  action_joints_enable_[joint_name] = false;
101  }
102 
103  ros::NodeHandle ros_node;
104 
105  std::string path = ros::package::getPath("thormang3_action_module") + "/data/motion_4095.bin";
106  std::string action_file_path = ros_node.param<std::string>("action_file_path", path);
107 
108  loadFile(action_file_path);
109 
110  playing_ = false;
111 }
112 
114 {
115  ros::NodeHandle ros_node;
116  ros::CallbackQueue callback_queue;
117 
118  ros_node.setCallbackQueue(&callback_queue);
119 
120  /* publisher */
121  status_msg_pub_ = ros_node.advertise<robotis_controller_msgs::StatusMsg>("/robotis/status", 0);
122  done_msg_pub_ = ros_node.advertise<std_msgs::String>("/robotis/movement_done", 1);
123 
124  /* subscriber */
125  ros::Subscriber action_page_sub = ros_node.subscribe("/robotis/action/page_num", 0, &ActionModule::pageNumberCallback, this);
126  ros::Subscriber start_action_sub = ros_node.subscribe("/robotis/action/start_action", 0, &ActionModule::startActionCallback, this);
127 
128  /* ROS Service Callback Functions */
129  ros::ServiceServer is_running_server = ros_node.advertiseService("/robotis/action/is_running", &ActionModule::isRunningServiceCallback, this);
130 
131  ros::WallDuration duration(control_cycle_msec_ / 1000.0);
132  while(ros_node.ok())
133  callback_queue.callAvailable(duration);
134 }
135 
136 bool ActionModule::isRunningServiceCallback(thormang3_action_module_msgs::IsRunning::Request &req,
137  thormang3_action_module_msgs::IsRunning::Response &res)
138 {
139  res.is_running = isRunning();
140  return true;
141 }
142 
143 void ActionModule::pageNumberCallback(const std_msgs::Int32::ConstPtr& msg)
144 {
145  if(enable_ == false)
146  {
147  std::string status_msg = "Action Module is not enabled";
148  ROS_INFO_STREAM(status_msg);
149  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_ERROR, status_msg);
150  return;
151  }
152 
153  if(msg->data == -1)
154  {
155  stop();
156  }
157  else if(msg->data == -2)
158  {
159  brake();
160  }
161  else
162  {
163  for(std::map<std::string, bool>::iterator joints_enable_it = action_joints_enable_.begin(); joints_enable_it != action_joints_enable_.end(); joints_enable_it++)
164  joints_enable_it->second = true;
165 
166  if(start(msg->data) == true)
167  {
168  std::string status_msg = "Succeed to start page " + convertIntToString(msg->data);
169  ROS_INFO_STREAM(status_msg);
170  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_INFO, status_msg);
171  }
172  else
173  {
174  std::string status_msg = "Failed to start page " + convertIntToString(msg->data);
175  ROS_ERROR_STREAM(status_msg);
176  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_ERROR, status_msg);
177  publishDoneMsg("action_failed");
178  }
179  }
180 }
181 
182 
183 void ActionModule::startActionCallback(const thormang3_action_module_msgs::StartAction::ConstPtr& msg)
184 {
185  if(enable_ == false)
186  {
187  std::string status_msg = "Action Module is not enabled";
188  ROS_INFO_STREAM(status_msg);
189  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_ERROR, status_msg);
190  return;
191  }
192 
193  if(msg->page_num == -1)
194  {
195  stop();
196  }
197  else if(msg->page_num == -2)
198  {
199  brake();
200  }
201  else
202  {
203  for(std::map<std::string, bool>::iterator joints_enable_it = action_joints_enable_.begin(); joints_enable_it != action_joints_enable_.end(); joints_enable_it++)
204  joints_enable_it->second = false;
205 
206  int joint_name_array_size = msg->joint_name_array.size();
207  std::map<std::string, bool>::iterator joints_enable_it = action_joints_enable_.begin();
208  for(int joint_idx = 0; joint_idx < joint_name_array_size; joint_idx++)
209  {
210  joints_enable_it = action_joints_enable_.find(msg->joint_name_array[joint_idx]);
211  if(joints_enable_it == action_joints_enable_.end())
212  {
213  std::string status_msg = "Invalid Joint Name : " + msg->joint_name_array[joint_idx];
214  ROS_INFO_STREAM(status_msg);
215  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_ERROR, status_msg);
216  publishDoneMsg("action_failed");
217  return;
218  }
219  else
220  {
221  joints_enable_it->second = true;
222  }
223  }
224 
225  if(start(msg->page_num) == true)
226  {
227  std::string status_msg = "Succeed to start page " + convertIntToString(msg->page_num);
228  ROS_INFO_STREAM(status_msg);
229  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_INFO, status_msg);
230  }
231  else
232  {
233  std::string status_msg = "Failed to start page " + convertIntToString(msg->page_num);
234  ROS_ERROR_STREAM(status_msg);
235  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_ERROR, status_msg);
236  publishDoneMsg("action_failed");
237  }
238  }
239 }
240 
241 void ActionModule::process(std::map<std::string, robotis_framework::Dynamixel *> dxls, std::map<std::string, double> sensors)
242 {
243  if(enable_ == false)
244  return;
245 
246  if(action_module_enabled_ == true)
247  {
248  for(std::map<std::string, robotis_framework::Dynamixel *>::iterator dxls_it = dxls.begin() ; dxls_it != dxls.end(); dxls_it++)
249  {
250  std::string joint_name = dxls_it->first;
251 
252  std::map<std::string, robotis_framework::DynamixelState*>::iterator result_it = result_.find(joint_name);
253  if(result_it == result_.end())
254  continue;
255  else
256  {
257  result_it->second->goal_position_ = dxls_it->second->dxl_state_->goal_position_;
258  action_result_[joint_name]->goal_position_ = dxls_it->second->dxl_state_->goal_position_;
259  }
260  }
261  action_module_enabled_ = false;
262  }
263 
264  actionPlayProcess(dxls);
265 
266  for(std::map<std::string, bool>::iterator action_enable_it = action_joints_enable_.begin(); action_enable_it != action_joints_enable_.end(); action_enable_it++)
267  {
268  if(action_enable_it->second == true)
269  result_[action_enable_it->first]->goal_position_ = action_result_[action_enable_it->first]->goal_position_;
270  }
271 
274 
276  {
277  if(present_running_ == true)
278  {
279  std::string status_msg = "Action_Start";
280  ROS_INFO_STREAM(status_msg);
281  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_INFO, status_msg);
282  }
283  else
284  {
285  for(std::map<std::string, robotis_framework::DynamixelState*>::iterator action_result_it = action_result_.begin(); action_result_it != action_result_.end(); action_result_it++)
286  action_result_it->second->goal_position_ = result_[action_result_it->first]->goal_position_;
287 
288  std::string status_msg = "Action_Finish";
289  ROS_INFO_STREAM(status_msg);
290  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_INFO, status_msg);
291  publishDoneMsg("action");
292  }
293  }
294 }
295 
297 {
298  action_module_enabled_ = true;
299 }
300 
302 {
303  action_module_enabled_ = false;
304  brake();
305 }
306 
308 {
309  stop_playing_ = true;
310 }
311 
313 {
314  return playing_;
315 }
316 
318 {
319  return (int)((rad + M_PI)*2048.0/M_PI);
320 }
321 
323 {
324  return (w4095 - 2048)*M_PI/2048.0;
325 }
326 
328 {
329  unsigned char checksum = 0x00;
330  unsigned char* pt = (unsigned char*)page;
331 
332  for(unsigned int i = 0; i < sizeof(action_file_define::Page); i++)
333  {
334  checksum += *pt;
335  pt++;
336  }
337 
338  if(checksum != 0xff)
339  return false;
340 
341  return true;
342 }
343 
345 {
346  unsigned char checksum = 0x00;
347  unsigned char* pt = (unsigned char*)page;
348 
349  page->header.checksum = 0x00;
350 
351  for(unsigned int i = 0; i < sizeof(action_file_define::Page); i++)
352  {
353  checksum += *pt;
354  pt++;
355  }
356 
357  page->header.checksum = (unsigned char)(0xff - checksum);
358 }
359 
360 bool ActionModule::loadFile(std::string file_name)
361 {
362  FILE* action = fopen( file_name.c_str(), "r+b" );
363  if( action == 0 )
364  {
365  std::string status_msg = "Can not open Action file!";
366  ROS_ERROR_STREAM(status_msg);
367  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_ERROR, status_msg);
368  return false;
369  }
370 
371  fseek( action, 0, SEEK_END );
372  if( ftell(action) != (long)(sizeof(action_file_define::Page) * action_file_define::MAXNUM_PAGE) )
373  {
374  std::string status_msg = "It's not an Action file!";
375  ROS_ERROR_STREAM(status_msg);
376  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_ERROR, status_msg);
377  fclose( action );
378  return false;
379  }
380 
381  if(action_file_ != 0)
382  fclose( action_file_ );
383 
384  action_file_ = action;
385  return true;
386 }
387 
388 bool ActionModule::createFile(std::string file_name)
389 {
390  FILE* action = fopen( file_name.c_str(), "ab" );
391  if( action == 0 )
392  {
393  std::string status_msg = "Can not create Action file!";
394  ROS_ERROR_STREAM(status_msg);
395  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_ERROR, status_msg);
396  return false;
397  }
398 
400  resetPage(&page);
401 
402  for(int i = 0; i < action_file_define::MAXNUM_PAGE; i++)
403  fwrite((const void *)&page, 1, sizeof(action_file_define::Page), action);
404 
405  if(action_file_ != 0)
406  fclose( action_file_ );
407 
408  action_file_ = action;
409 
410  return true;
411 }
412 
413 bool ActionModule::start(int page_number)
414 {
415  if( page_number < 1 || page_number >= action_file_define::MAXNUM_PAGE )
416  {
417  return false;
418  }
419 
421  if( loadPage(page_number, &page) == false )
422  return false;
423 
424  return start(page_number, &page);
425 }
426 
427 bool ActionModule::start(std::string page_name)
428 {
429  int index;
431 
432  for(index=1; index < action_file_define::MAXNUM_PAGE; index++)
433  {
434  if(loadPage(index, &page) == false)
435  return false;
436 
437  if(strcmp(page_name.c_str(), (char*)page.header.name) == 0)
438  break;
439  }
440 
441  if(index == action_file_define::MAXNUM_PAGE)
442  {
443  return false;
444  }
445  else
446  return start(index, &page);
447 }
448 
449 bool ActionModule::start(int page_number, action_file_define::Page* page)
450 {
451  if(enable_ == false)
452  {
453  std::string status_msg = "Action Module is disabled";
454  ROS_ERROR_STREAM(status_msg);
455  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_ERROR, status_msg);
456  return false;
457  }
458 
459  if(playing_ == true)
460  {
461  std::string status_msg = "Can not play page " + convertIntToString(page_number) + ".(Now playing)";
462  ROS_ERROR_STREAM(status_msg);
463  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_ERROR, status_msg);
464  return false;
465  }
466 
467  play_page_ = *page;
468 
469  if( play_page_.header.repeat == 0 || play_page_.header.stepnum == 0 )
470  {
471  std::string status_msg = "Page " + convertIntToString(page_number) + " has no action\n";
472  ROS_ERROR_STREAM(status_msg);
473  publishStatusMsg(robotis_controller_msgs::StatusMsg::STATUS_ERROR, status_msg);
474  return false;
475  }
476 
477  play_page_idx_ = page_number;
478  first_driving_start_ = true;
479  playing_ = true;
480 
481  return true;
482 }
483 
485 {
486  playing_ = false;
487 }
488 
489 bool ActionModule::isRunning(int* playing_page_num, int* playing_step_num)
490 {
491  if(playing_page_num != 0)
492  *playing_page_num = play_page_idx_;
493 
494  if(playing_step_num != 0)
495  *playing_step_num = page_step_count_ - 1;
496 
497  return isRunning();
498 }
499 
501 {
502  if(page_number < 0 || page_number >= action_file_define::MAXNUM_PAGE)
503  return false;
504 
505  long position = (long)(sizeof(action_file_define::Page)*page_number);
506 
507  if( fseek( action_file_, position, SEEK_SET ) != 0 )
508  return false;
509 
510  if( fread( page, 1, sizeof(action_file_define::Page), action_file_ ) != sizeof(action_file_define::Page) )
511  return false;
512 
513  if( verifyChecksum( page ) == false )
514  resetPage( page );
515 
516  return true;
517 }
518 
520 {
521  long position = (long)(sizeof(action_file_define::Page)*page_number);
522 
523  if( verifyChecksum(page) == false )
524  setChecksum(page);
525 
526  if( fseek( action_file_, position, SEEK_SET ) != 0 )
527  return false;
528 
529  if( fwrite( page, 1, sizeof(action_file_define::Page), action_file_ ) != sizeof(action_file_define::Page) )
530  return false;
531 
532  return true;
533 }
534 
536 {
537  unsigned char *pt = (unsigned char*)page;
538 
539  for(unsigned int i=0; i<sizeof(action_file_define::Page); i++)
540  {
541  *pt = 0x00;
542  pt++;
543  }
544 
545  page->header.schedule = action_file_define::TIME_BASE_SCHEDULE; // default time base
546  page->header.repeat = 1;
547  page->header.speed = 32;
548  page->header.accel = 32;
549 
550  for(int i=0; i < action_file_define::MAXNUM_JOINTS; i++)
551  page->header.pgain[i] = 0x55;
552 
553  for(int i=0; i < action_file_define::MAXNUM_STEP; i++)
554  {
555  for(int j=0; j < action_file_define::MAXNUM_JOINTS; j++)
557 
558  page->step[i].pause = 0;
559  page->step[i].time = 0;
560  }
561 
562  setChecksum( page );
563 }
564 
566 {
567  for (std::map<std::string, bool>::iterator it = action_joints_enable_.begin();
568  it != action_joints_enable_.end();
569  it++)
570  {
571  it->second = true;
572  }
573 }
574 
575 void ActionModule::actionPlayProcess(std::map<std::string, robotis_framework::Dynamixel *> dxls)
576 {
578  uint8_t id;
579  uint32_t total_time_256t;
580  uint32_t pre_section_time_256t;
581  uint32_t main_time_256t;
582  int32_t start_speed1024_pre_time_256t;
583  int32_t moving_angle_speed1024_scale_256t_2t;
584  int32_t divider1,divider2;
585 
586  int16_t max_angle;
587  int16_t max_speed;
588  int16_t tmp;
589  int16_t prev_target_angle; // Start position
590  int16_t curr_target_angle; // Target position
591  int16_t next_target_angle; // Next target position
592  uint8_t direction_changed;
593  int16_t speed_n;
594 
596  static uint16_t start_angle[action_file_define::MAXNUM_JOINTS]; // Start point of interpolation
597  static uint16_t target_angle[action_file_define::MAXNUM_JOINTS]; // Target point of interpolation
598  static int16_t moving_angle[action_file_define::MAXNUM_JOINTS]; // Total Moving Angle
599  static int16_t main_angle[action_file_define::MAXNUM_JOINTS]; // Moving angle at Constant Velocity Section
600  static int16_t accel_angle[action_file_define::MAXNUM_JOINTS]; // Moving angle at Acceleration Section
601  static int16_t main_speed[action_file_define::MAXNUM_JOINTS]; // Target constant velocity
602  static int16_t last_out_speed[action_file_define::MAXNUM_JOINTS]; // Velocity of Previous State
603  static int16_t goal_speed[action_file_define::MAXNUM_JOINTS]; // Target velocity
604  static uint8_t finish_type[action_file_define::MAXNUM_JOINTS]; // Desired State at Target angle
605 
606  static uint16_t unit_time_count;
607  static uint16_t unit_time_num;
608  static uint16_t pause_time;
609  static uint16_t unit_time_total_num;
610  static uint16_t accel_step;
611  static uint8_t section;
612  static uint8_t play_repeat_count;
613  static uint16_t next_play_page;
614 
615 
617  /**************************************
618  * Section /----\
619  * /| |\
620  * /+---------/ | | \
621  * / | | | | \
622  * -----/ | | | | \----
623  * PRE MAIN PRE MAIN POST PAUSE
624  ***************************************/
625 
626  if( playing_ == false )
627  return;
628 
629  if( first_driving_start_ == true ) // First of Start Process
630  {
631  first_driving_start_ = false; //First Process end
632  playing_finished_ = false;
633  stop_playing_ = false;
634  unit_time_count = 0;
635  unit_time_num = 0;
636  pause_time = 0;
637  section = PAUSE_SECTION;
638  page_step_count_ = 0;
639  play_repeat_count = play_page_.header.repeat;
640  next_play_page = 0;
641 
642  for(unsigned int joint_index = 0; joint_index < action_file_define::MAXNUM_JOINTS; joint_index++)
643  {
644  id = joint_index;
645  std::string joint_name = "";
646 
647  std::map<int, std::string>::iterator id_to_name_it = joint_id_to_name_.find(id);
648  if(id_to_name_it == joint_id_to_name_.end())
649  continue;
650  else
651  joint_name = id_to_name_it->second;
652 
653 
654  std::map<std::string, robotis_framework::Dynamixel *>::iterator dxls_it = dxls.find(joint_name);
655  if(dxls_it == dxls.end())
656  continue;
657  else
658  {
659  double goal_joint_angle_rad = dxls_it->second->dxl_state_->goal_position_;
660  target_angle[id] = convertRadTow4095(goal_joint_angle_rad);
661  last_out_speed[id] = 0;
662  moving_angle[id] = 0;
663  goal_speed[id] = 0;
664  }
665  }
666  }
667 
668 
669  if( unit_time_count < unit_time_num ) // If state is ongoing
670  {
671  unit_time_count++;
672  if( section == PAUSE_SECTION )
673  {
674  }
675  else
676  {
677  for(unsigned int joint_index = 0; joint_index < action_file_define::MAXNUM_JOINTS; joint_index++ )
678  {
679  id = joint_index;
680  std::string joint_name = "";
681 
682  std::map<int, std::string>::iterator id_to_name_it = joint_id_to_name_.find(id);
683  if(id_to_name_it == joint_id_to_name_.end())
684  continue;
685  else
686  joint_name = id_to_name_it->second;
687 
688 
689  std::map<std::string, robotis_framework::Dynamixel *>::iterator dxls_it = dxls.find(joint_name);
690  if(dxls_it == dxls.end())
691  {
692  continue;
693  }
694  else
695  {
696  if( moving_angle[id] == 0 )
697  {
698  action_result_[joint_name]->goal_position_ = convertw4095ToRad(start_angle[id]);
699  }
700  else
701  {
702  if( section == PRE_SECTION )
703  {
704  speed_n = (short)( ( (long)(main_speed[id] - last_out_speed[id]) * unit_time_count ) / unit_time_num );
705  goal_speed[id] = last_out_speed[id] + speed_n;
706  accel_angle[id] = (short)( ( ( (long)( last_out_speed[id] + (speed_n >> 1) ) * unit_time_count * 144 ) / 15 ) >> 9);
707 
708  action_result_[joint_name]->goal_position_ = convertw4095ToRad(start_angle[id] + accel_angle[id]);
709  }
710  else if( section == MAIN_SECTION )
711  {
712  action_result_[joint_name]->goal_position_ = convertw4095ToRad(start_angle[id] + (short int)(((long)(main_angle[id])*unit_time_count) / unit_time_num));
713 
714  goal_speed[id] = main_speed[id];
715  }
716  else // POST_SECTION
717  {
718  if( unit_time_count == (unit_time_num-1) )
719  {
720  // use target angle in order to reduce the last step error
721  action_result_[joint_name]->goal_position_ = convertw4095ToRad(target_angle[id]);
722  }
723  else
724  {
725  if( finish_type[id] == ZERO_FINISH )
726  {
727  speed_n = (short int)(((long)(0 - last_out_speed[id]) * unit_time_count) / unit_time_num);
728  goal_speed[id] = last_out_speed[id] + speed_n;
729 
730  action_result_[joint_name]->goal_position_
731  = convertw4095ToRad(start_angle[id] + (short)((((long)(last_out_speed[id] + (speed_n>>1)) * unit_time_count * 144) / 15) >> 9));
732 
733  }
734  else // NONE_ZERO_FINISH
735  {
736  // Same as MAIN Section
737  // because some servos need to be rotate, others do not.
738  action_result_[joint_name]->goal_position_
739  = convertw4095ToRad(start_angle[id] + (short int)(((long)(main_angle[id]) * unit_time_count) / unit_time_num));
740 
741  goal_speed[id] = main_speed[id];
742  }
743  }
744  }
745  }
746  //action_result_[_joint_name]->position_p_gain = ( 256 >> (play_page_.header.pgain[bID] >> 4) ) << 2 ;
747  }
748  }
749  }
750  }
751  else if( unit_time_count >= unit_time_num ) // If current section is completed
752  {
753  unit_time_count = 0;
754 
755  for(unsigned int joint_index = 0; joint_index < action_file_define::MAXNUM_JOINTS; joint_index++)
756  {
757  id = joint_index;
758  std::string joint_name = "";
759  std::map<int, std::string>::iterator id_to_name_it = joint_id_to_name_.find(id);
760  if(id_to_name_it == joint_id_to_name_.end())
761  continue;
762  else
763  joint_name = id_to_name_it->second;
764 
765 
766  std::map<std::string, robotis_framework::Dynamixel *>::iterator dxls_it = dxls.find(joint_name);
767  if(dxls_it == dxls.end())
768  continue;
769  else
770  {
771  double _goal_joint_angle_rad = dxls_it->second->dxl_state_->goal_position_;
772  start_angle[id] = convertRadTow4095(_goal_joint_angle_rad);
773  last_out_speed[id] = goal_speed[id];
774  }
775  }
776 
777  // Section will be updated ( PRE -> MAIN -> POST -> (PAUSE or PRE) ... )
778  if( section == PRE_SECTION )
779  {
780  //preparations for MAIN section
781  section = MAIN_SECTION;
782  unit_time_num = unit_time_total_num - (accel_step << 1);
783 
784  for(unsigned int joint_index = 0; joint_index < action_file_define::MAXNUM_JOINTS; joint_index++)
785  {
786  id = joint_index;
787 
788  if( finish_type[id] == NONE_ZERO_FINISH )
789  {
790  if( (unit_time_total_num - accel_step) == 0 ) // if there is not any constant velocity section
791  main_angle[id] = 0;
792  else
793  main_angle[id] = (short)((((long)(moving_angle[id] - accel_angle[id])) * unit_time_num) / (unit_time_total_num - accel_step));
794  }
795  else // ZERO_FINISH
796  main_angle[id] = moving_angle[id] - accel_angle[id] - (short int)((((long)main_speed[id] * accel_step * 12) / 5) >> 8);
797  }
798  }
799  else if( section == MAIN_SECTION )
800  {
801  //preparations for POST Section
802  section = POST_SECTION;
803  unit_time_num = accel_step;
804 
805  for(unsigned int joint_index = 0; joint_index < action_file_define::MAXNUM_JOINTS; joint_index++)
806  {
807  id = joint_index;
808  main_angle[id] = moving_angle[id] - main_angle[id] - accel_angle[id];
809  }
810  }
811  else if( section == POST_SECTION )
812  {
813  //it will be decided by Pause time exist or not
814  if( pause_time )
815  {
816  section = PAUSE_SECTION;
817  unit_time_num = pause_time;
818  }
819  else
820  {
821  section = PRE_SECTION;
822  }
823  }
824  else if( section == PAUSE_SECTION )
825  {
826  //preparations for PRE Section
827  section = PRE_SECTION;
828 
829  for(unsigned int joint_index = 0; joint_index < action_file_define::MAXNUM_JOINTS; joint_index++)
830  {
831  id = joint_index;
832  last_out_speed[id] = 0;
833  }
834  }
835 
836  // all is prepared in PRE Section
837  if( section == PRE_SECTION )
838  {
839  if( playing_finished_ == true ) // If motion is finished
840  {
841  playing_ = false;
842  return;
843  }
844 
846 
847  if( page_step_count_ > play_page_.header.stepnum ) // If motion playing for present page is finished
848  {
849  // copy next page to play page
851  if( play_page_idx_ != next_play_page )
852  play_repeat_count = play_page_.header.repeat;
853  page_step_count_ = 1;
854  play_page_idx_ = next_play_page;
855  }
856 
857  if( page_step_count_ == play_page_.header.stepnum ) // If this step is last
858  {
859  // load next page
860  if( stop_playing_ == true ) // If there is STOP command
861  {
862  next_play_page = play_page_.header.exit; // Next page will be set to exit page
863  }
864  else
865  {
866  play_repeat_count--;
867  if( play_repeat_count > 0 ) // If repeat number is remained
868  next_play_page = play_page_idx_; // Next page will be set to current page
869  else // If repeat is finished
870  next_play_page = play_page_.header.next; // Next page will be set to NEXT page
871  }
872 
873  if( next_play_page == 0 ) // If there is no NEXT page, the motion playing will be finished after current step.
874  playing_finished_ = true;
875  else
876  {
877  // load NEXT Page(If page is same, memory copy will be conducted. If not, read from file will be conducted)
878  if( play_page_idx_ != next_play_page )
879  loadPage( next_play_page, &next_play_page_ );
880  else
882 
883  // If there is no playing information, the motion playing will be finished after current step.
885  playing_finished_ = true;
886  }
887  }
888 
890  pause_time = (((unsigned short)play_page_.step[page_step_count_-1].pause) << 5) / play_page_.header.speed;
891  max_speed = ((unsigned short)play_page_.step[page_step_count_-1].time * (unsigned short)play_page_.header.speed) >> 5;
892  if( max_speed == 0 )
893  max_speed = 1;
894  max_angle = 0;
895 
897  for(unsigned int joint_index = 0; joint_index < action_file_define::MAXNUM_JOINTS; joint_index++)
898  {
899  id = joint_index;
900  //Calculate the trajectory using previous, present and future
901  accel_angle[id] = 0;
902 
903  // Find current target angle
905  curr_target_angle = target_angle[id];
906  else
907  curr_target_angle = play_page_.step[page_step_count_ - 1].position[id];
908 
909  // Update start, prev_target, curr_target
910  start_angle[id] = target_angle[id];
911  prev_target_angle = target_angle[id];
912  target_angle[id] = curr_target_angle;
913 
914  // Find Moving offset
915  moving_angle[id] = (int)(target_angle[id] - start_angle[id]);
916 
917  // Find Next target angle
918  if( page_step_count_ == play_page_.header.stepnum ) // If current step is last step
919  {
920  if( playing_finished_ == true ) // If it will be finished
921  next_target_angle = curr_target_angle;
922  else
923  {
924  if( next_play_page_.step[0].position[id] & action_file_define::INVALID_BIT_MASK )
925  next_target_angle = curr_target_angle;
926  else
927  next_target_angle = next_play_page_.step[0].position[id];
928  }
929  }
930  else
931  {
932  if( play_page_.step[page_step_count_].position[id] & action_file_define::INVALID_BIT_MASK )
933  next_target_angle = curr_target_angle;
934  else
935  next_target_angle = play_page_.step[page_step_count_].position[id];
936  }
937 
938  // Find direction change
939  if( ((prev_target_angle < curr_target_angle) && (curr_target_angle < next_target_angle))
940  || ((prev_target_angle > curr_target_angle) && (curr_target_angle > next_target_angle)) )
941  {
942  // if there is no discontinuous point
943  direction_changed = 0;
944  }
945  else
946  {
947  direction_changed = 1;
948  }
949 
950  // Find finish type
951  if( direction_changed || pause_time || playing_finished_ == true )
952  finish_type[id] = ZERO_FINISH;
953  else
954  finish_type[id] = NONE_ZERO_FINISH;
955 
957  {
958  //MaxAngle1024 update
959  if( moving_angle[id] < 0 )
960  tmp = -moving_angle[id];
961  else
962  tmp = moving_angle[id];
963 
964  if( tmp > max_angle )
965  max_angle = tmp;
966  }
967 
968  }
969 
970  // calculation the time. And, the calculated time will be divided by 7.8msec(<<7)- calculate there are how many 7.8msec
971  // after unit conversion, calculate angle/velocity, and the following code computes how many units of 7.8s occurs within the specified time
972  // unit conversion --- angle :1024->300deg, velocity: 256 ->720
973  // wUnitTimeNum = ((wMaxAngle1024*300/1024) /(wMaxSpeed256 * 720/256)) /7.8msec;
974  // = ((128*wMaxAngle1024*300/1024) /(wMaxSpeed256 * 720/256)) ; (/7.8msec == *128)
975  // = (wMaxAngle1024*40) /(wMaxSpeed256 *3);
977  unit_time_total_num = max_speed; //TIME BASE 051025
978  else
979  unit_time_total_num = (max_angle * 40) / (max_speed * 3);
980 
981  accel_step = play_page_.header.accel;
982  if( unit_time_total_num <= (accel_step << 1) )
983  {
984  if( unit_time_total_num == 0 )
985  {
986  accel_step = 0;
987  }
988  else
989  {
990  accel_step = (unit_time_total_num - 1) >> 1;
991  if( accel_step == 0 )
992  unit_time_total_num = 0; //If motor will be rotated, acceleration and constant velocity step should exist more than one step
993  }
994  }
995 
996  total_time_256t = ((unsigned long)unit_time_total_num) << 1;// /128 * 256
997  pre_section_time_256t = ((unsigned long)accel_step) << 1;// /128 * 256
998  main_time_256t = total_time_256t - pre_section_time_256t;
999  divider1 = pre_section_time_256t + (main_time_256t << 1);
1000  divider2 = (main_time_256t << 1);
1001 
1002  if(divider1 == 0)
1003  divider1 = 1;
1004 
1005  if(divider2 == 0)
1006  divider2 = 1;
1007 
1008  for(unsigned int joint_index = 0; joint_index < action_file_define::MAXNUM_JOINTS; joint_index++)
1009  {
1010  id = joint_index;
1011  start_speed1024_pre_time_256t = (long)last_out_speed[id] * pre_section_time_256t; // *300/1024 * 1024/720 * 256 * 2
1012  moving_angle_speed1024_scale_256t_2t = (((long)moving_angle[id]) * 2560L) / 12;
1013 
1014  if( finish_type[id] == ZERO_FINISH )
1015  main_speed[id] = (short int)((moving_angle_speed1024_scale_256t_2t - start_speed1024_pre_time_256t) / divider2);
1016  else
1017  main_speed[id] = (short int)((moving_angle_speed1024_scale_256t_2t - start_speed1024_pre_time_256t) / divider1);
1018 
1019  if( main_speed[id] > 1023 )
1020  main_speed[id] = 1023;
1021 
1022  if( main_speed[id] < -1023 )
1023  main_speed[id] = -1023;
1024  }
1025  unit_time_num = accel_step; //PreSection
1026  }
1027  }
1028 }
1029 
1030 
1031 void ActionModule::publishStatusMsg(unsigned int type, std::string msg)
1032 {
1033  robotis_controller_msgs::StatusMsg status;
1034  status.header.stamp = ros::Time::now();
1035  status.type = type;
1036  status.module_name = "Action";
1037  status.status_msg = msg;
1038 
1039  status_msg_pub_.publish(status);
1040 }
1041 
1042 void ActionModule::publishDoneMsg(std::string msg)
1043 {
1044  std_msgs::String done_msg;
1045  done_msg.data = msg;
1046 
1047  done_msg_pub_.publish(done_msg);
1048 }
1049 
void publishStatusMsg(unsigned int type, std::string msg)
action_file_define::Page play_page_
void initialize(const int control_cycle_msec, robotis_framework::Robot *robot)
void setChecksum(action_file_define::Page *page)
std::map< std::string, DynamixelState * > result_
void publish(const boost::shared_ptr< M > &message) const
unsigned short position[MAXNUM_JOINTS]
void startActionCallback(const thormang3_action_module_msgs::StartAction::ConstPtr &msg)
void pageNumberCallback(const std_msgs::Int32::ConstPtr &msg)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ros::Publisher status_msg_pub_
void actionPlayProcess(std::map< std::string, robotis_framework::Dynamixel * > dxls)
bool loadFile(std::string file_name)
bool savePage(int page_number, action_file_define::Page *page)
std::map< int, std::string > joint_id_to_name_
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
std::map< std::string, int > joint_name_to_id_
void publishDoneMsg(std::string msg)
void resetPage(action_file_define::Page *page)
std::map< std::string, Dynamixel * > dxls_
ros::Publisher done_msg_pub_
std::map< std::string, bool > action_joints_enable_
Definition: action_module.h:99
bool loadPage(int page_number, action_file_define::Page *page)
bool verifyChecksum(action_file_define::Page *page)
boost::thread queue_thread_
bool param(const std::string &param_name, T &param_val, const T &default_val) const
void setCallbackQueue(CallbackQueueInterface *queue)
int convertRadTow4095(double rad)
action_file_define::Page next_play_page_
void process(std::map< std::string, robotis_framework::Dynamixel * > dxls, std::map< std::string, double > sensors)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ROSLIB_DECL std::string getPath(const std::string &package_name)
#define ROS_INFO_STREAM(args)
bool isRunningServiceCallback(thormang3_action_module_msgs::IsRunning::Request &req, thormang3_action_module_msgs::IsRunning::Response &res)
DynamixelState * dxl_state_
static Time now()
bool createFile(std::string file_name)
double convertw4095ToRad(int w4095)
bool ok() const
bool start(int page_number)
#define ROS_ERROR_STREAM(args)
std::string convertIntToString(int n)
std::map< std::string, robotis_framework::DynamixelState * > action_result_


thormang3_action_module
Author(s): Kayman , Jay Song
autogenerated on Mon Jun 10 2019 15:37:44