cob_undercarriage_ctrl_new.cpp
Go to the documentation of this file.
1 /****************************************************************
2  *
3  * Copyright (c) 2010
4  *
5  * Fraunhofer Institute for Manufacturing Engineering
6  * and Automation (IPA)
7  *
8  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9  *
10  * Project name: care-o-bot
11  * ROS stack name: cob_driver
12  * ROS package name: cob_undercarriage_ctrl
13  * Description:
14  *
15  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16  *
17  * Author: Christian Connette, email:christian.connette@ipa.fhg.de
18  * Supervised by: Christian Connette, email:christian.connette@ipa.fhg.de
19  *
20  * Date of creation: April 2010:
21  * ToDo: Adapt Interface to controller -> remove last variable (not used anymore)
22  * Rework Ctrl-class to work with SI-Units -> remove conversion
23  * For easier association of joints use platform.urdf!!
24  *
25  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
26  *
27  * Redistribution and use in source and binary forms, with or without
28  * modification, are permitted provided that the following conditions are met:
29  *
30  * * Redistributions of source code must retain the above copyright
31  * notice, this list of conditions and the following disclaimer.
32  * * Redistributions in binary form must reproduce the above copyright
33  * notice, this list of conditions and the following disclaimer in the
34  * documentation and/or other materials provided with the distribution.
35  * * Neither the name of the Fraunhofer Institute for Manufacturing
36  * Engineering and Automation (IPA) nor the names of its
37  * contributors may be used to endorse or promote products derived from
38  * this software without specific prior written permission.
39  *
40  * This program is free software: you can redistribute it and/or modify
41  * it under the terms of the GNU Lesser General Public License LGPL as
42  * published by the Free Software Foundation, either version 3 of the
43  * License, or (at your option) any later version.
44  *
45  * This program is distributed in the hope that it will be useful,
46  * but WITHOUT ANY WARRANTY; without even the implied warranty of
47  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48  * GNU Lesser General Public License LGPL for more details.
49  *
50  * You should have received a copy of the GNU Lesser General Public
51  * License LGPL along with this program.
52  * If not, see <http://www.gnu.org/licenses/>.
53  *
54  ****************************************************************/
55 
56 //##################
57 //#### includes ####
58 
59 // standard includes
60 #include <math.h>
61 
62 // ROS includes
63 #include <ros/ros.h>
64 
65 // ROS message includes
66 #include <diagnostic_msgs/DiagnosticStatus.h>
68 #include <geometry_msgs/Twist.h>
69 #include <nav_msgs/Odometry.h>
71 #include <cob_msgs/EmergencyStopState.h>
72 #include <control_msgs/JointTrajectoryControllerState.h>
73 
74 // external includes
77 #include <vector>
78 #include <angles/angles.h>
79 
80 //####################
81 //#### node class ####
82 class NodeClass
83 {
84  //
85  public:
86  // create a handle for this node, initialize node
87  ros::NodeHandle n; // parameter are uploaded to private space
88 
89  // topics to publish
90  ros::Publisher topic_pub_joint_state_cmd_; // cmd issued for single joints of undercarriage
92  ros::Publisher topic_pub_odometry_; // calculated (measured) velocity, rotation and pose (odometry-based) for the robot
93  tf::TransformBroadcaster tf_broadcast_odometry_; // according transformation for the tf broadcaster
94 
95  // topics to subscribe, callback is called for new messages arriving
96  ros::Subscriber topic_sub_CMD_pltf_twist_; // issued command to be achieved by the platform
97  ros::Subscriber topic_sub_EM_stop_state_; // current emergency stop state (free, active, confirmed)
98  ros::Subscriber topic_sub_drive_diagnostic_; // status of drive chain (initializing, error, normal)
99 
100  //subscribe to JointStates topic
101  //ros::Subscriber topic_sub_joint_states_;
103 
104  // diagnostic stuff
106 
107  // controller Timer
109 
110  // member variables
111  UndercarriageCtrl * ucar_ctrl_; // instantiate undercarriage controller
112  bool is_initialized_bool_; // flag wether node is already up and running
114  bool broadcast_tf_; // flag wether to broadcast the tf from odom to base_link
115  int drive_chain_diagnostic_; // flag whether base drive chain is operating normal
116  ros::Time last_time_; // time Stamp for last odometry measurement
117  ros::Time joint_state_odom_stamp_; // time stamp of joint states used for current odometry calc
121 
123 
127 
129 
130  diagnostic_msgs::DiagnosticStatus diagnostic_status_lookup_; // used to access defines for warning levels
131 
132  // Constructor
134  : ucar_ctrl_(0)
135  {
136  // initialization of variables
137  is_initialized_bool_ = false;
138  is_ucarr_geom_initialized_bool_ = false;
139  broadcast_tf_ = true;
140  iwatchdog_ = 0;
141  last_time_ = ros::Time::now();
142  sample_time_ = 0.020; // TODO: read from parameter server
143  // set status of drive chain to WARN by default
144  drive_chain_diagnostic_ = diagnostic_status_lookup_.OK; //WARN; <- THATS FOR DEBUGGING ONLY!
145  has_target = false;
146 
147  // Parameters are set within the launch file
148  // read in timeout for watchdog stopping the controller.
149  if (n.hasParam("timeout"))
150  {
151  n.getParam("timeout", timeout_);
152  ROS_INFO("Timeout loaded from Parameter-Server is: %fs", timeout_);
153  }
154  else
155  {
156  ROS_WARN("No parameter timeout on Parameter-Server. Using default: 1.0s");
157  timeout_ = 1.0;
158  }
159  if ( timeout_ < sample_time_ )
160  {
161  ROS_WARN("Specified timeout < sample_time. Setting timeout to sample_time = %fs", sample_time_);
162  timeout_ = sample_time_;
163  }
164 
165  if (n.hasParam("max_trans_velocity"))
166  {
167  n.getParam("max_trans_velocity", max_vel_trans_);
168  ROS_INFO("Max translational velocity loaded from Parameter-Server is: %fs", max_vel_trans_);
169  }
170  else
171  {
172  ROS_WARN("No parameter max_trans_velocity on Parameter-Server. Using default: 1.1 m/s");
173  max_vel_trans_ = 1.1;
174  }
175  if (n.hasParam("max_rot_velocity"))
176  {
177  n.getParam("max_rot_velocity", max_vel_rot_);
178  ROS_INFO("Max rotational velocity loaded from Parameter-Server is: %fs", max_vel_rot_);
179  }
180  else
181  {
182  ROS_WARN("No parameter max_rot_velocity on Parameter-Server. Using default: 1.8 rad/s");
183  max_vel_rot_ = 1.8;
184  }
185  if (n.hasParam("broadcast_tf"))
186  {
187  n.getParam("broadcast_tf", broadcast_tf_);
188  }
189 
190  const std::string frame_id = n.param("frame_id", std::string("odom"));
191  const std::string child_frame_id = n.param("child_frame_id", std::string("base_footprint"));
192  const double cov_pose = n.param("cov_pose", 0.1);
193  const double cov_twist = n.param("cov_twist", 0.1);
194 
195  odom_tracker_ = new OdometryTracker(frame_id, child_frame_id, cov_pose, cov_twist);
196 
197  // vector of wheels
198  std::vector<UndercarriageCtrl::WheelParams> wps;
199 
200  // configuration of ucar_ctrl by yaml-files
202 
203  m_iNumWheels = wps.size();
204  m_iNumJoints = m_iNumWheels * 2;
205 
206  ucar_ctrl_ = new UndercarriageCtrl(wps);
207  is_ucarr_geom_initialized_bool_ = true;
208  }
209 
210  // implementation of topics
211  // published topics
212  //topic_pub_joint_state_cmd_ = n.advertise<sensor_msgs::JointState>("joint_command", 1);
213  topic_pub_controller_joint_command_ = n.advertise<control_msgs::JointTrajectoryControllerState> ("joint_command", 1);
214 
215  topic_pub_odometry_ = n.advertise<nav_msgs::Odometry>("odometry", 1);
216 
217  // subscribed topics
218  topic_sub_CMD_pltf_twist_ = n.subscribe("command", 1, &NodeClass::topicCallbackTwistCmd, this);
219  topic_sub_EM_stop_state_ = n.subscribe("/emergency_stop_state", 1, &NodeClass::topicCallbackEMStop, this);
220  topic_sub_drive_diagnostic_ = n.subscribe("diagnostic", 1, &NodeClass::topicCallbackDiagnostic, this);
221 
222 
223 
224  //topic_sub_joint_states_ = n.subscribe("/joint_states", 1, &NodeClass::topicCallbackJointStates, this);
225  topic_sub_joint_controller_states_ = n.subscribe("state", 1, &NodeClass::topicCallbackJointControllerStates, this);
226 
227  // diagnostics
229  updater_.add("initialization", this, &NodeClass::diag_init);
230 
231  //set up timer to cyclically call controller-step
232  timer_ctrl_step_ = n.createTimer(ros::Duration(sample_time_), &NodeClass::timerCallbackCtrlStep, this);
233 
234  if (is_ucarr_geom_initialized_bool_)
235  is_initialized_bool_ = true;
236  }
237 
238 
239  // Destructor
241  {
242  topic_sub_CMD_pltf_twist_.shutdown();
243  topic_sub_EM_stop_state_.shutdown();
244  topic_sub_drive_diagnostic_.shutdown();
245  topic_sub_joint_controller_states_.shutdown();
246 
247  timer_ctrl_step_.stop();
248  delete ucar_ctrl_;
249  delete odom_tracker_;
250  }
251 
253  {
254  if(is_initialized_bool_)
255  stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "");
256  else
257  stat.summary(diagnostic_msgs::DiagnosticStatus::WARN, "");
258  stat.add("Initialized", is_initialized_bool_);
259  }
260 
261  // Listen for Pltf Cmds
262  void topicCallbackTwistCmd(const geometry_msgs::Twist::ConstPtr& msg)
263  {
264  // create instance of pltState which is initialized with zero values
265  PlatformState pltState;
266 
267  if( (fabs(msg->linear.x) > max_vel_trans_) || (fabs(msg->linear.y) > max_vel_trans_) || (fabs(msg->angular.z) > max_vel_rot_)){
268  if(fabs(msg->linear.x) > max_vel_trans_){
269  ROS_DEBUG_STREAM("Recevied cmdVelX: " << msg->linear.x <<
270  ", which is bigger than the maximal allowed translational velocity: " << max_vel_trans_ << " so stop the robot");
271  }
272  if(fabs(msg->linear.y) > max_vel_trans_){
273  ROS_DEBUG_STREAM("Recevied cmdVelY: " << msg->linear.x <<
274  ", which is bigger than the maximal allowed translational velocity: " << max_vel_trans_ << " so stop the robot");
275  }
276  if(fabs(msg->angular.z) > max_vel_rot_){
277  ROS_DEBUG_STREAM("Recevied cmdVelTh: " << msg->angular.z <<
278  ", which is bigger than the maximal allowed rotational velocity: " << max_vel_rot_ << " so stop the robot");
279  }
280 
281  // pltState is initialized with zero values, so it isnt necessary to set them explicitly
282 
283  }
284  else{
285  // setter-methods convert SI-Units (m/s) to mm/s because controller works with those
286  pltState.setVelX(msg->linear.x);
287  pltState.setVelY(msg->linear.y);
288  pltState.dRotRobRadS = msg->angular.z;
289  }
290 
291  iwatchdog_ = 0;
292 
293  // only process if controller is already initialized
294  if (is_initialized_bool_ && drive_chain_diagnostic_ == diagnostic_status_lookup_.OK){
295  ROS_DEBUG("received new velocity command [cmdVelX=%3.5f,cmdVelY=%3.5f,cmdVelTh=%3.5f]",
296  msg->linear.x, msg->linear.y, msg->angular.z);
297 
298  //std::cout << "PLT_VELO_NEW: " << pltState.dVelLongMMS << " , " << pltState.dVelLatMMS << " , " << pltState.dRotRobRadS << std::endl;
299  // Set desired values for Plattform State to UndercarriageCtrl (setpoint setting
300  has_target = msg->linear.x!= 0 || msg->linear.y!=0 || msg->angular.z != 0;
301  ucar_ctrl_->setTarget(pltState);
302  }
303  else{
304  //std::cout << "PLT_VELO_NEW: " << pltState.dVelLongMMS << " , " << pltState.dVelLatMMS << " , " << pltState.dRotRobRadS << std::endl;
305  // Set desired values for Plattform State to zero (setpoint setting)
306  // pltState will be initialized with zero values
307  pltState = PlatformState();
308  ucar_ctrl_->setTarget(pltState);
309 
310  ROS_DEBUG("Forced platform-velocity cmds to zero");
311  }
312  }
313 
314  // Listen for Emergency Stop
315  void topicCallbackEMStop(const cob_msgs::EmergencyStopState::ConstPtr& msg)
316  {
317  int current_EM_state = msg->emergency_state;
318 
319  if (current_EM_state == msg->EMFREE){
320  // Reset EM flag in Ctrlr
321  if (is_initialized_bool_){
322  setEMStopActive(false);
323  ROS_DEBUG("Undercarriage Controller EM-Stop released");
324  }
325  }
326  else{
327  ROS_DEBUG("Undercarriage Controller stopped due to EM-Stop");
328 
329  // Set desired values for Plattform State to zero (setpoint setting)
330  // pltState will be initialized with zero values
331  PlatformState pltState;
332  ucar_ctrl_->setTarget(pltState);
333 
334  ROS_DEBUG("Forced platform-velocity cmds to zero");
335 
336  // Set EM flag and stop Ctrlr
337  setEMStopActive(true);
338  }
339  }
340 
341  // Listens for status of underlying hardware (base drive chain)
342  void topicCallbackDiagnostic(const diagnostic_msgs::DiagnosticStatus::ConstPtr& msg)
343  {
344  control_msgs::JointTrajectoryControllerState joint_state_cmd;
345 
346  // prepare joint_cmds for heartbeat (compose header)
347  joint_state_cmd.header.stamp = ros::Time::now();
348  //joint_state_cmd.header.frame_id = frame_id; //Where to get this id from?
349  // ToDo: configure over Config-File (number of motors) and Msg
350  // assign right size to JointState data containers
351  //joint_state_cmd.set_name_size(m_iNumMotors);
352  joint_state_cmd.desired.positions.resize(m_iNumJoints);
353  joint_state_cmd.desired.velocities.resize(m_iNumJoints);
354  //joint_state_cmd.desired.effort.resize(m_iNumJoints);
355 
356  // TODO: Generic adapation reqiuerd for joint_names when base_drive_chain will be updated
357  joint_state_cmd.joint_names.push_back("fl_caster_r_wheel_joint");
358  joint_state_cmd.joint_names.push_back("fl_caster_rotation_joint");
359  joint_state_cmd.joint_names.push_back("bl_caster_r_wheel_joint");
360  joint_state_cmd.joint_names.push_back("bl_caster_rotation_joint");
361  joint_state_cmd.joint_names.push_back("br_caster_r_wheel_joint");
362  joint_state_cmd.joint_names.push_back("br_caster_rotation_joint");
363  joint_state_cmd.joint_names.push_back("fr_caster_r_wheel_joint");
364  joint_state_cmd.joint_names.push_back("fr_caster_rotation_joint");
365  joint_state_cmd.joint_names.resize(m_iNumJoints);
366 
367  // compose jointcmds
368  for(int i=0; i<m_iNumJoints; i++)
369  {
370  joint_state_cmd.desired.positions[i] = 0.0;
371  joint_state_cmd.desired.velocities[i] = 0.0;
372  //joint_state_cmd.desired.effort[i] = 0.0;
373  }
374 
375  // set status of underlying drive chain to member variable
376  drive_chain_diagnostic_ = msg->level;
377 
378  // if controller is already started up ...
379  if (is_initialized_bool_){
380  // ... but underlying drive chain is not yet operating normal
381  if (drive_chain_diagnostic_ != diagnostic_status_lookup_.OK){
382  has_target = false;
383  // halt controller
384  ROS_DEBUG("drive chain not availlable: halt Controller");
385 
386  // Set EM flag to Ctrlr (resets internal states)
387  setEMStopActive(true);
388 
389  // Set desired values for Plattform State to zero (setpoint setting)
390  // pltState will be initialized with zero values
391  PlatformState pltState;
392  ucar_ctrl_->setTarget(pltState);
393 
394  ROS_DEBUG("Forced platform-velocity cmds to zero");
395  }
396  }
397  // ... while controller is not initialized send heartbeats to keep motors alive
398  else
399  {
400  // ... as soon as base drive chain is initialized
401  if(drive_chain_diagnostic_ != diagnostic_status_lookup_.WARN)
402  {
403  // publish zero-vel. jointcmds to avoid Watchdogs stopping ctrlr
404  topic_pub_controller_joint_command_.publish(joint_state_cmd);
405  }
406  }
407  }
408 
409  void topicCallbackJointControllerStates(const control_msgs::JointTrajectoryControllerState::ConstPtr& msg) {
410  int num_joints = msg->joint_names.size();
411 
412  // replaces the vectors per parameter with a vector of wheelStates which combines the wheel specfic params
413  std::vector<WheelState> wStates;
414  wStates.assign(m_iNumWheels, WheelState());
415 
416  joint_state_odom_stamp_ = msg->header.stamp;
417 
418  for(int i = 0; i < num_joints; i++)
419  {
420  // associate inputs to according steer and drive joints
421  // ToDo: specify this globally (Prms-File or config-File or via msg-def.)
422  if(msg->joint_names[i] == "fl_caster_r_wheel_joint")
423  {
424  wStates[0].dVelGearDriveRadS = msg->actual.velocities[i];
425  }
426  if(msg->joint_names[i] == "bl_caster_r_wheel_joint")
427  {
428  wStates[1].dVelGearDriveRadS = msg->actual.velocities[i];
429  }
430  if(msg->joint_names[i] == "br_caster_r_wheel_joint")
431  {
432  wStates[2].dVelGearDriveRadS = msg->actual.velocities[i];
433  }
434  if(msg->joint_names[i] == "fr_caster_r_wheel_joint")
435  {
436  wStates[3].dVelGearDriveRadS = msg->actual.velocities[i];
437  }
438  if(msg->joint_names[i] == "fl_caster_rotation_joint")
439  {
440  wStates[0].dAngGearSteerRad = msg->actual.positions[i];
441  wStates[0].dVelGearSteerRadS = msg->actual.velocities[i];
442  }
443  if(msg->joint_names[i] == "bl_caster_rotation_joint")
444  {
445  wStates[1].dAngGearSteerRad = msg->actual.positions[i];
446  wStates[1].dVelGearSteerRadS = msg->actual.velocities[i];
447  }
448  if(msg->joint_names[i] == "br_caster_rotation_joint")
449  {
450  wStates[2].dAngGearSteerRad = msg->actual.positions[i];
451  wStates[2].dVelGearSteerRadS = msg->actual.velocities[i];
452  }
453  if(msg->joint_names[i] == "fr_caster_rotation_joint")
454  {
455  wStates[3].dAngGearSteerRad = msg->actual.positions[i];
456  wStates[3].dVelGearSteerRadS = msg->actual.velocities[i];
457  }
458  }
459 
460  // Set measured Wheel Velocities and Angles to Controler Class (implements inverse kinematic)
461  ucar_ctrl_->updateWheelStates(wStates);
462 
463  // calculate odometry every time
464  UpdateOdometry();
465  }
466 
468  CalcCtrlStep();
469  }
470 
471  // other function declarations
472  // Initializes controller
473  bool InitCtrl();
474  // perform one control step, calculate inverse kinematics and publish updated joint cmd's (if no EMStop occurred)
475  void CalcCtrlStep();
476  // acquires the current undercarriage configuration from base_drive_chain
477  // calculates odometry from current measurement values and publishes it via an odometry topic and the tf broadcaster
478  void UpdateOdometry();
479 
480  // set EM Flag and stop ctrlr if active
481  void setEMStopActive(bool bEMStopActive);
482 
483 };
484 
485 //#######################
486 //#### main programm ####
487 int main(int argc, char** argv)
488 {
489  // initialize ROS, spezify name of node
490  ros::init(argc, argv, "undercarriage_ctrl");
491 
492  // construct nodeClass
493  // automatically do initializing of controller, because it's not directly depending any hardware components
494  NodeClass nodeClass;
495 
496  // verify init status
497  if( nodeClass.is_initialized_bool_ ) {
498  nodeClass.last_time_ = ros::Time::now();
499  ROS_INFO("New Undercarriage control successfully initialized.");
500  } else {
501  ROS_FATAL("Undercarriage control initialization failed!");
502  throw std::runtime_error("Undercarriage control initialization failed, check yaml-Files!");
503  }
504 
505  /*
506  CALLBACKS being executed are:
507  - actual motor values -> calculating direct kinematics and doing odometry (topicCallbackJointControllerStates)
508  - timer callback -> calculate controller step at a rate of sample_time_ (timerCallbackCtrlStep)
509  - other topic callbacks (diagnostics, command, em_stop_state)
510  */
511  ros::spin();
512 
513  return 0;
514 }
515 
516 //##################################
517 //#### function implementations ####
518 
519 // perform one control step, calculate inverse kinematics and publish updated joint cmd's (if no EMStop occurred)
521 {
522  // WheelStates will be initialized with zero-values
523  std::vector<WheelCommand> wStates;
524  wStates.assign(m_iNumWheels, WheelCommand());
525 
526  // create control_msg
527  control_msgs::JointTrajectoryControllerState joint_state_cmd;
528 
529  int j = 0, k = 0;
530  iwatchdog_ += 1;
531 
532  // if controller is initialized and underlying hardware is operating normal
533  if (is_initialized_bool_) // && (drive_chain_diagnostic_ != diagnostic_status_lookup_.OK))
534  {
535  // as soon as (but only as soon as) platform drive chain is initialized start to send velocity commands
536  // Note: topicCallbackDiagnostic checks whether drives are operating nominal.
537  // -> if warning or errors are issued target velocity is set to zero
538 
539  // perform one control step,
540  // get the resulting cmd's for the wheel velocities and -angles from the controller class
541  // and output the achievable pltf velocity-cmds (if velocity limits where exceeded)
542  ucar_ctrl_->calcControlStep(wStates, sample_time_, false);
543 
544  // if drives not operating nominal -> force commands to zero
546  for(int i = 0; i < wStates.size(); i++){
547  wStates[i].dAngGearSteerRad = 0.0;
548  wStates[i].dVelGearSteerRadS = 0.0;
549  }
550  }
551 
552  // compose jointcmds of control_msg
553 
554  // compose header of control_msg
555  joint_state_cmd.header.stamp = ros::Time::now();
556 
557  //Where to get this id from?
558  //joint_state_cmd.header.frame_id = frame_id;
559 
560  // ToDo: configure over Config-File (number of motors) and Msg
561  // assign right size to JointState data containers
562  //joint_state_cmd.set_name_size(m_iNumJoints);
563 
564  joint_state_cmd.desired.positions.resize(m_iNumJoints);
565  joint_state_cmd.desired.velocities.resize(m_iNumJoints);
566  //joint_state_cmd.effort.resize(m_iNumJoints);
567  joint_state_cmd.joint_names.push_back("fl_caster_r_wheel_joint");
568  joint_state_cmd.joint_names.push_back("fl_caster_rotation_joint");
569  joint_state_cmd.joint_names.push_back("bl_caster_r_wheel_joint");
570  joint_state_cmd.joint_names.push_back("bl_caster_rotation_joint");
571  joint_state_cmd.joint_names.push_back("br_caster_r_wheel_joint");
572  joint_state_cmd.joint_names.push_back("br_caster_rotation_joint");
573  joint_state_cmd.joint_names.push_back("fr_caster_r_wheel_joint");
574  joint_state_cmd.joint_names.push_back("fr_caster_rotation_joint");
575  joint_state_cmd.joint_names.resize(m_iNumJoints);
576 
577  // compose data body of control_msg
578  for(int i = 0; i<m_iNumJoints; i++)
579  {
580  if(iwatchdog_ < (int) std::floor(timeout_/sample_time_) && has_target)
581  {
582  // for steering motors
583  if( i == 1 || i == 3 || i == 5 || i == 7) // ToDo: specify this via the Msg
584  {
585  joint_state_cmd.desired.positions[i] = wStates[j].dAngGearSteerRad;
586  joint_state_cmd.desired.velocities[i] = wStates[j].dVelGearSteerRadS;
587  j = j + 1;
588  }
589  else
590  {
591  joint_state_cmd.desired.positions[i] = 0.0;
592  joint_state_cmd.desired.velocities[i] = wStates[k].dVelGearDriveRadS;
593  k = k + 1;
594  }
595  }
596  else
597  {
598  joint_state_cmd.desired.positions[i] = 0.0;
599  joint_state_cmd.desired.velocities[i] = 0.0;
600  }
601  }
602 
603  // publish jointcmds
605  }
606 
607 }
608 
609 // calculates odometry from current measurement values
610 // and publishes it via an odometry topic and the tf broadcaster
612 {
613  // if drive chain already initialized process joint data
614  //if (drive_chain_diagnostic_ != diagnostic_status_lookup_.OK)
615  PlatformState pltState;
617  {
618 
619  // Get resulting Pltf Velocities from Ctrl-Class (result of forward kinematics)
620  // !Careful! Controller internally calculates with mm instead of m
621  // ToDo: change internal calculation to SI-Units
622  ucar_ctrl_->calcDirect(pltState);
623  }
626 
627  nav_msgs::Odometry odom_top = odom_tracker_->getOdometry();
628 
629  if (broadcast_tf_ == true)
630  {
631  // compose and publish transform for tf package
632  geometry_msgs::TransformStamped odom_tf;
633  // compose header
634  odom_tf.header.stamp = odom_top.header.stamp;
635  odom_tf.header.frame_id = "/odom_combined";
636  odom_tf.child_frame_id = "/base_footprint";
637  // compose data container
638  odom_tf.transform.translation.x = odom_top.pose.pose.position.x;
639  odom_tf.transform.translation.y = odom_top.pose.pose.position.y;
640  odom_tf.transform.rotation = odom_top.pose.pose.orientation;
641 
642  // publish the transform (for debugging, conflicts with robot-pose-ekf)
644  }
645 
646  // publish odometry msg
647  topic_pub_odometry_.publish(odom_top);
648 }
649 
650 // set EM Flag and stop ctrlr if active
651 void NodeClass::setEMStopActive(bool bEMStopActive)
652 {
653  m_bEMStopActive = bEMStopActive;
654 
655  std::vector<WheelState> wStates;
656  wStates.assign(m_iNumWheels, WheelState());
657 
658  std::vector<WheelCommand> wCommands;
659  wCommands.assign(m_iNumWheels, WheelCommand());
660 
661  // if emergency stop reset ctrlr to zero
662  if(m_bEMStopActive)
663  {
664 // std::cout << "EMStop: " << "Active" << std::endl;
665  has_target = false;
666  // reset and update current wheel states but keep current dAngGearSteerRad per wheelState
667  ucar_ctrl_->calcControlStep(wCommands, sample_time_, true);
668 
669  // set current wheel states with previous reset and updated wheelStates
670  ucar_ctrl_->updateWheelStates(wStates);
671  }
672 // else
673 // std::cout << "EMStop: " << "Inactive" << std::endl;
674 }
675 
676 
677 
bool InitCtrl()
void setVelY(const double val)
void topicCallbackEMStop(const cob_msgs::EmergencyStopState::ConstPtr &msg)
bool parseWheelParams(std::vector< UndercarriageGeom::WheelParams > &params, const ros::NodeHandle &nh, bool read_urdf=true)
ros::Subscriber topic_sub_joint_controller_states_
#define ROS_FATAL(...)
virtual void calcDirect(PlatformState &state) const
void setEMStopActive(bool bEMStopActive)
const double getVelY()
void setTarget(const PlatformState &state)
void publish(const boost::shared_ptr< M > &message) const
void summary(unsigned char lvl, const std::string s)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
void setHardwareID(const std::string &hwid)
void stop()
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
tf::TransformBroadcaster tf_broadcast_odometry_
int main(int argc, char **argv)
UndercarriageCtrl * ucar_ctrl_
void add(const std::string &name, TaskFunction f)
ROSCPP_DECL const std::string & getName()
virtual void updateWheelStates(const std::vector< WheelState > &states)
#define ROS_WARN(...)
diagnostic_msgs::DiagnosticStatus diagnostic_status_lookup_
void topicCallbackTwistCmd(const geometry_msgs::Twist::ConstPtr &msg)
double dRotRobRadS
const nav_msgs::Odometry & getOdometry()
void calcControlStep(std::vector< WheelCommand > &commands, double dCmdRateS, bool reset)
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
const double getVelX()
ros::Subscriber topic_sub_CMD_pltf_twist_
void sendTransform(const StampedTransform &transform)
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
void track(const ros::Time &now, double dt, double vel_x, double vel_y, double vel_theta)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ROSCPP_DECL void spin()
#define ROS_DEBUG_STREAM(args)
ros::Subscriber topic_sub_drive_diagnostic_
void timerCallbackCtrlStep(const ros::TimerEvent &e)
diagnostic_updater::Updater updater_
ros::Publisher topic_pub_joint_state_cmd_
OdometryTracker * odom_tracker_
void diag_init(diagnostic_updater::DiagnosticStatusWrapper &stat)
ros::Subscriber topic_sub_EM_stop_state_
bool getParam(const std::string &key, std::string &s) const
void topicCallbackDiagnostic(const diagnostic_msgs::DiagnosticStatus::ConstPtr &msg)
ros::Publisher topic_pub_controller_joint_command_
static Time now()
void add(const std::string &key, const T &val)
bool hasParam(const std::string &key) const
void setVelX(const double val)
ros::Publisher topic_pub_odometry_
void topicCallbackJointControllerStates(const control_msgs::JointTrajectoryControllerState::ConstPtr &msg)
#define ROS_DEBUG(...)


cob_undercarriage_ctrl_node
Author(s): Mathias Luedtke, Christian Connette
autogenerated on Thu Jul 20 2017 02:43:39