00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <string>
00019 #include <vector>
00020 #include <limits>
00021 #include <ros/ros.h>
00022
00023 #include <cob_twist_controller/cob_twist_controller.h>
00024
00025 #include <kdl_conversions/kdl_msg.h>
00026 #include <tf/transform_datatypes.h>
00027 #include <visualization_msgs/Marker.h>
00028 #include <visualization_msgs/MarkerArray.h>
00029 #include <cob_srvs/SetString.h>
00030
00031 #include <Eigen/Dense>
00032
00033 bool CobTwistController::initialize()
00034 {
00035 ros::NodeHandle nh_twist("twist_controller");
00036
00037
00038 if (!nh_.getParam("joint_names", twist_controller_params_.joints))
00039 {
00040 ROS_ERROR("Parameter 'joint_names' not set");
00041 return false;
00042 }
00043
00044 twist_controller_params_.dof = twist_controller_params_.joints.size();
00045
00046
00047 if (!nh_.getParam("chain_base_link", twist_controller_params_.chain_base_link))
00048 {
00049 ROS_ERROR("Parameter 'chain_base_link' not set");
00050 return false;
00051 }
00052
00053 if (!nh_.getParam("chain_tip_link", twist_controller_params_.chain_tip_link))
00054 {
00055 ROS_ERROR("Parameter 'chain_tip_link' not set");
00056 return false;
00057 }
00058
00059
00060 if (!nh_twist.getParam("collision_check_links", twist_controller_params_.collision_check_links))
00061 {
00062 ROS_WARN_STREAM("Parameter 'collision_check_links' not set. Collision Avoidance constraint will not do anything.");
00063 twist_controller_params_.collision_check_links.clear();
00064 }
00065
00067 KDL::Tree my_tree;
00068 if (!kdl_parser::treeFromParam("/robot_description", my_tree))
00069 {
00070 ROS_ERROR("Failed to construct kdl tree");
00071 return false;
00072 }
00073
00074 my_tree.getChain(twist_controller_params_.chain_base_link, twist_controller_params_.chain_tip_link, chain_);
00075 if (chain_.getNrOfJoints() == 0)
00076 {
00077 ROS_ERROR("Failed to initialize kinematic chain");
00078 return false;
00079 }
00080
00082 urdf::Model model;
00083 if (!model.initParam("/robot_description"))
00084 {
00085 ROS_ERROR("Failed to parse urdf file for JointLimits");
00086 return false;
00087 }
00088
00089 for (uint16_t i = 0; i < twist_controller_params_.dof; i++)
00090 {
00091 if (model.getJoint(twist_controller_params_.joints[i])->type == urdf::Joint::CONTINUOUS)
00092 {
00093 twist_controller_params_.limiter_params.limits_min.push_back(-std::numeric_limits<double>::max());
00094 twist_controller_params_.limiter_params.limits_max.push_back(std::numeric_limits<double>::max());
00095 }
00096 else
00097 {
00098 twist_controller_params_.limiter_params.limits_min.push_back(model.getJoint(twist_controller_params_.joints[i])->limits->lower);
00099 twist_controller_params_.limiter_params.limits_max.push_back(model.getJoint(twist_controller_params_.joints[i])->limits->upper);
00100 }
00101 twist_controller_params_.limiter_params.limits_vel.push_back(model.getJoint(twist_controller_params_.joints[i])->limits->velocity);
00102 }
00103
00104
00105 if ((!nh_twist.getParam("limits_acc", twist_controller_params_.limiter_params.limits_acc)) || (twist_controller_params_.limiter_params.limits_acc.size() != twist_controller_params_.dof))
00106 {
00107
00108 for (uint16_t i = 0; i < twist_controller_params_.dof; i++)
00109 {
00110 twist_controller_params_.limiter_params.limits_acc.push_back(std::numeric_limits<double>::max());
00111 }
00112 }
00113
00114
00115 if (nh_twist.hasParam("lookat_axis_type"))
00116 {
00117 int lookat_axis_type;
00118 nh_twist.getParam("lookat_axis_type", lookat_axis_type);
00119 twist_controller_params_.lookat_offset.lookat_axis_type = static_cast<LookatAxisTypes>(lookat_axis_type);
00120 }
00121 if (nh_twist.hasParam("lookat_offset"))
00122 {
00123 if (nh_twist.hasParam("lookat_offset/translation"))
00124 {
00125 twist_controller_params_.lookat_offset.translation_x = nh_twist.param("lookat_offset/translation/x", 0.0);
00126 twist_controller_params_.lookat_offset.translation_y = nh_twist.param("lookat_offset/translation/y", 0.0);
00127 twist_controller_params_.lookat_offset.translation_z = nh_twist.param("lookat_offset/translation/z", 0.0);
00128 }
00129 if (nh_twist.hasParam("lookat_offset/rotation"))
00130 {
00131 twist_controller_params_.lookat_offset.rotation_x = nh_twist.param("lookat_offset/rotation/x", 0.0);
00132 twist_controller_params_.lookat_offset.rotation_y = nh_twist.param("lookat_offset/rotation/y", 0.0);
00133 twist_controller_params_.lookat_offset.rotation_z = nh_twist.param("lookat_offset/rotation/z", 0.0);
00134 twist_controller_params_.lookat_offset.rotation_w = nh_twist.param("lookat_offset/rotation/w", 1.0);
00135 }
00136 }
00137
00138
00139 if (!nh_twist.getParam("controller_interface", twist_controller_params_.controller_interface))
00140 {
00141 ROS_ERROR("Parameter 'controller_interface' not set");
00142 return false;
00143 }
00144 nh_twist.param<double>("integrator_smoothing", twist_controller_params_.integrator_smoothing, 0.2);
00145 try
00146 {
00147 interface_loader_.reset(new pluginlib::ClassLoader<cob_twist_controller::ControllerInterfaceBase>("cob_twist_controller", "cob_twist_controller::ControllerInterfaceBase"));
00148 this->controller_interface_ = interface_loader_->createInstance(twist_controller_params_.controller_interface);
00149 this->controller_interface_->initialize(this->nh_, this->twist_controller_params_);
00150 }
00151 catch(pluginlib::PluginlibException& ex)
00152 {
00153 ROS_ERROR("The controller_interface plugin failed to load. Error: %s", ex.what());
00154 return false;
00155 }
00156
00157 twist_controller_params_.frame_names.clear();
00158 for (uint16_t i = 0; i < chain_.getNrOfSegments(); ++i)
00159 {
00160 twist_controller_params_.frame_names.push_back(chain_.getSegment(i).getName());
00161 }
00162 register_link_client_ = nh_.serviceClient<cob_srvs::SetString>("obstacle_distance/registerLinkOfInterest");
00163 register_link_client_.waitForExistence(ros::Duration(5.0));
00164 twist_controller_params_.constraint_ca = CA_OFF;
00165
00167 p_inv_diff_kin_solver_.reset(new InverseDifferentialKinematicsSolver(twist_controller_params_, chain_, callback_data_mediator_));
00168 p_inv_diff_kin_solver_->resetAll(twist_controller_params_);
00169
00171 reconfigure_server_.reset(new dynamic_reconfigure::Server<cob_twist_controller::TwistControllerConfig>(reconfig_mutex_, nh_twist));
00172 reconfigure_server_->setCallback(boost::bind(&CobTwistController::reconfigureCallback, this, _1, _2));
00173
00175 this->joint_states_.current_q_ = KDL::JntArray(chain_.getNrOfJoints());
00176 this->joint_states_.current_q_dot_ = KDL::JntArray(chain_.getNrOfJoints());
00177 this->joint_states_.last_q_ = KDL::JntArray(chain_.getNrOfJoints());
00178 this->joint_states_.last_q_dot_ = KDL::JntArray(chain_.getNrOfJoints());
00179
00181 ros::Duration(1.0).sleep();
00182
00184 obstacle_distance_sub_ = nh_.subscribe("obstacle_distance", 1, &CallbackDataMediator::distancesToObstaclesCallback, &callback_data_mediator_);
00185 jointstate_sub_ = nh_.subscribe("joint_states", 1, &CobTwistController::jointstateCallback, this);
00186 twist_sub_ = nh_twist.subscribe("command_twist", 1, &CobTwistController::twistCallback, this);
00187 twist_stamped_sub_ = nh_twist.subscribe("command_twist_stamped", 1, &CobTwistController::twistStampedCallback, this);
00188
00189 odometry_sub_ = nh_.subscribe("base/odometry", 1, &CobTwistController::odometryCallback, this);
00190
00192 twist_direction_pub_ = nh_.advertise<visualization_msgs::MarkerArray>("twist_direction", 1);
00193
00194 ROS_INFO_STREAM(nh_.getNamespace() << "/twist_controller...initialized!");
00195 return true;
00196 }
00197
00198 bool CobTwistController::registerCollisionLinks()
00199 {
00200 ROS_WARN_COND(twist_controller_params_.collision_check_links.size() <= 0,
00201 "No collision_check_links set for this chain. Nothing will be registered. Ensure parameters are set correctly.");
00202
00203 for (std::vector<std::string>::const_iterator it = twist_controller_params_.collision_check_links.begin();
00204 it != twist_controller_params_.collision_check_links.end();
00205 it++)
00206 {
00207 ROS_INFO_STREAM("Trying to register for " << *it);
00208 cob_srvs::SetString r;
00209 r.request.data = *it;
00210 if (register_link_client_.call(r))
00211 {
00212 ROS_INFO_STREAM("Called registration service with success: " << int(r.response.success) << ". Got message: " << r.response.message);
00213 if (!r.response.success)
00214 {
00215 return false;
00216 }
00217 }
00218 else
00219 {
00220 ROS_WARN_STREAM("Failed to call registration service for namespace: " << nh_.getNamespace());
00221 return false;
00222 }
00223 }
00224
00225 return true;
00226 }
00227
00228 void CobTwistController::reconfigureCallback(cob_twist_controller::TwistControllerConfig& config, uint32_t level)
00229 {
00230 this->checkSolverAndConstraints(config);
00231
00232 twist_controller_params_.numerical_filtering = config.numerical_filtering;
00233 twist_controller_params_.damping_method = static_cast<DampingMethodTypes>(config.damping_method);
00234 twist_controller_params_.damping_factor = config.damping_factor;
00235 twist_controller_params_.lambda_max = config.lambda_max;
00236 twist_controller_params_.w_threshold = config.w_threshold;
00237 twist_controller_params_.slope_damping = config.slope_damping;
00238 twist_controller_params_.beta = config.beta;
00239 twist_controller_params_.eps_damping = config.eps_damping;
00240 twist_controller_params_.eps_truncation = config.eps_truncation;
00241
00242 twist_controller_params_.solver = static_cast<SolverTypes>(config.solver);
00243 twist_controller_params_.priority_main = config.priority;
00244 twist_controller_params_.k_H = config.k_H;
00245
00246 twist_controller_params_.constraint_jla = static_cast<ConstraintTypesJLA>(config.constraint_jla);
00247 twist_controller_params_.constraint_ca = static_cast<ConstraintTypesCA>(config.constraint_ca);
00248
00249 ConstraintParams cp_jla;
00250 cp_jla.priority = config.priority_jla;
00251 cp_jla.k_H = config.k_H_jla;
00252 cp_jla.damping = config.damping_jla;
00253 const double activation_jla_in_percent = config.activation_threshold_jla;
00254 const double activation_buffer_jla_in_percent = config.activation_buffer_jla;
00255 const double critical_jla_in_percent = config.critical_threshold_jla;
00256 cp_jla.thresholds.activation = activation_jla_in_percent / 100.0;
00257 cp_jla.thresholds.critical = critical_jla_in_percent / 100.0;
00258 cp_jla.thresholds.activation_with_buffer = cp_jla.thresholds.activation * (1.0 + activation_buffer_jla_in_percent / 100.0);
00259 twist_controller_params_.constraint_params[JLA] = cp_jla;
00260
00261 ConstraintParams cp_ca;
00262 cp_ca.priority = config.priority_ca;
00263 cp_ca.k_H = config.k_H_ca;
00264 cp_ca.damping = config.damping_ca;
00265 const double activaton_buffer_ca_in_percent = config.activation_buffer_ca;
00266 cp_ca.thresholds.activation = config.activation_threshold_ca;
00267 cp_ca.thresholds.critical = config.critical_threshold_ca;
00268 cp_ca.thresholds.activation_with_buffer = cp_ca.thresholds.activation * (1.0 + activaton_buffer_ca_in_percent / 100.0);
00269 twist_controller_params_.constraint_params[JLA] = cp_ca;
00270
00271 twist_controller_params_.ujs_solver_params.sigma = config.sigma;
00272 twist_controller_params_.ujs_solver_params.sigma_speed = config.sigma_speed;
00273 twist_controller_params_.ujs_solver_params.delta_pos = config.delta_pos;
00274 twist_controller_params_.ujs_solver_params.delta_speed = config.delta_speed;
00275
00276 twist_controller_params_.limiter_params.keep_direction = config.keep_direction;
00277 twist_controller_params_.limiter_params.enforce_input_limits = config.enforce_input_limits;
00278 twist_controller_params_.limiter_params.enforce_pos_limits = config.enforce_pos_limits;
00279 twist_controller_params_.limiter_params.enforce_vel_limits = config.enforce_vel_limits;
00280 twist_controller_params_.limiter_params.enforce_acc_limits = config.enforce_acc_limits;
00281 twist_controller_params_.limiter_params.limits_tolerance = config.limits_tolerance;
00282 twist_controller_params_.limiter_params.max_lin_twist = config.max_lin_twist;
00283 twist_controller_params_.limiter_params.max_rot_twist = config.max_rot_twist;
00284 twist_controller_params_.limiter_params.max_vel_lin_base = config.max_vel_lin_base;
00285 twist_controller_params_.limiter_params.max_vel_rot_base = config.max_vel_rot_base;
00286
00287 twist_controller_params_.kinematic_extension = static_cast<KinematicExtensionTypes>(config.kinematic_extension);
00288 twist_controller_params_.extension_ratio = config.extension_ratio;
00289
00290 p_inv_diff_kin_solver_->resetAll(this->twist_controller_params_);
00291 }
00292
00293 void CobTwistController::checkSolverAndConstraints(cob_twist_controller::TwistControllerConfig& config)
00294 {
00295 bool warning = false;
00296
00297 DampingMethodTypes damping = static_cast<DampingMethodTypes>(config.damping_method);
00298 if (damping != twist_controller_params_.damping_method)
00299 {
00300
00301 if (damping == CONSTANT)
00302 {
00303 config.damping_factor = 0.01;
00304 }
00305 else if (damping == MANIPULABILITY)
00306 {
00307 config.lambda_max = 0.1;
00308 config.w_threshold = 0.005;
00309 }
00310 else if (damping == LEAST_SINGULAR_VALUE)
00311 {
00312 config.lambda_max = 0.1;
00313 config.w_threshold = 0.005;
00314 }
00315 else if (damping == SIGMOID)
00316 {
00317 config.lambda_max = 0.001;
00318 config.w_threshold = 0.001;
00319 }
00320 }
00321
00322 SolverTypes solver = static_cast<SolverTypes>(config.solver);
00323
00324 if (DEFAULT_SOLVER == solver && (JLA_OFF != static_cast<ConstraintTypesJLA>(config.constraint_jla) || CA_OFF != static_cast<ConstraintTypesCA>(config.constraint_ca)))
00325 {
00326 ROS_ERROR("The selection of Default solver and a constraint doesn\'t make any sense. Switch settings back ...");
00327 twist_controller_params_.constraint_jla = JLA_OFF;
00328 twist_controller_params_.constraint_ca = CA_OFF;
00329 config.constraint_jla = static_cast<int>(twist_controller_params_.constraint_jla);
00330 config.constraint_ca = static_cast<int>(twist_controller_params_.constraint_ca);
00331 warning = true;
00332 }
00333
00334 if (WLN == solver && CA_OFF != static_cast<ConstraintTypesCA>(config.constraint_ca))
00335 {
00336 ROS_ERROR("The WLN solution doesn\'t support collision avoidance. Currently WLN is only implemented for Identity and JLA ...");
00337 twist_controller_params_.constraint_ca = CA_OFF;
00338 config.constraint_ca = static_cast<int>(twist_controller_params_.constraint_ca);
00339 warning = true;
00340 }
00341
00342 if (GPM == solver && CA_OFF == static_cast<ConstraintTypesCA>(config.constraint_ca) && JLA_OFF == static_cast<ConstraintTypesJLA>(config.constraint_jla))
00343 {
00344 ROS_ERROR("You have chosen GPM but without constraints! The behaviour without constraints will be the same like for DEFAULT_SOLVER.");
00345 warning = true;
00346 }
00347
00348 if (TASK_2ND_PRIO == solver && (JLA_ON == static_cast<ConstraintTypesJLA>(config.constraint_jla) || CA_OFF == static_cast<ConstraintTypesCA>(config.constraint_ca)))
00349 {
00350 ROS_ERROR("The projection of a task into the null space of the main EE task is currently only for the CA constraint supported!");
00351 twist_controller_params_.constraint_jla = JLA_OFF;
00352 twist_controller_params_.constraint_ca = CA_ON;
00353 config.constraint_jla = static_cast<int>(twist_controller_params_.constraint_jla);
00354 config.constraint_ca = static_cast<int>(twist_controller_params_.constraint_ca);
00355 warning = true;
00356 }
00357
00358 if (UNIFIED_JLA_SA == solver && CA_OFF != static_cast<ConstraintTypesCA>(config.constraint_ca))
00359 {
00360 ROS_ERROR("The Unified JLA and SA solution doesn\'t support collision avoidance. Currently UNIFIED_JLA_SA is only implemented for SA and JLA ...");
00361 twist_controller_params_.constraint_ca = CA_OFF;
00362 config.constraint_ca = static_cast<int>(twist_controller_params_.constraint_ca);
00363 warning = true;
00364 }
00365
00366 if (CA_OFF != static_cast<ConstraintTypesCA>(config.constraint_ca))
00367 {
00368 if (!register_link_client_.exists())
00369 {
00370 ROS_ERROR("ServiceServer 'obstacle_distance/registerLinkOfInterest' does not exist. CA not possible");
00371 twist_controller_params_.constraint_ca = CA_OFF;
00372 config.constraint_ca = static_cast<int>(twist_controller_params_.constraint_ca);
00373 warning = true;
00374 }
00375 else if (twist_controller_params_.constraint_ca != static_cast<ConstraintTypesCA>(config.constraint_ca))
00376 {
00377 ROS_INFO("Collision Avoidance has been activated! Register links!");
00378 if (!this->registerCollisionLinks())
00379 {
00380 ROS_ERROR("Registration of links failed. CA not possible");
00381 twist_controller_params_.constraint_ca = CA_OFF;
00382 config.constraint_ca = static_cast<int>(twist_controller_params_.constraint_ca);
00383 warning = true;
00384 }
00385 }
00386 }
00387
00388 if (twist_controller_params_.limiter_params.limits_tolerance <= DIV0_SAFE)
00389 {
00390 ROS_ERROR("The limits_tolerance for enforce limits is smaller than DIV/0 threshold. Therefore output limiting is disabled");
00391 twist_controller_params_.limiter_params.enforce_pos_limits = config.enforce_pos_limits = false;
00392 twist_controller_params_.limiter_params.enforce_vel_limits = config.enforce_vel_limits = false;
00393 twist_controller_params_.limiter_params.enforce_acc_limits = config.enforce_acc_limits = false;
00394 }
00395 if (twist_controller_params_.limiter_params.max_lin_twist <= DIV0_SAFE ||
00396 twist_controller_params_.limiter_params.max_rot_twist <= DIV0_SAFE)
00397 {
00398 ROS_ERROR("The limits used to limit Cartesian velocities are smaller than DIV/0 threshold. Therefore input limiting is disabled");
00399 twist_controller_params_.limiter_params.enforce_input_limits = config.enforce_input_limits = false;
00400 }
00401
00402 if (!warning)
00403 {
00404 ROS_INFO("Parameters seem to be ok.");
00405 }
00406 }
00407
00409 void CobTwistController::twistStampedCallback(const geometry_msgs::TwistStamped::ConstPtr& msg)
00410 {
00411 tf::StampedTransform transform_tf;
00412 KDL::Frame frame;
00413 KDL::Twist twist, twist_transformed;
00414
00415 try
00416 {
00417 tf_listener_.lookupTransform(twist_controller_params_.chain_base_link, msg->header.frame_id, ros::Time(0), transform_tf);
00418 frame.M = KDL::Rotation::Quaternion(transform_tf.getRotation().x(), transform_tf.getRotation().y(), transform_tf.getRotation().z(), transform_tf.getRotation().w());
00419 }
00420 catch (tf::TransformException& ex)
00421 {
00422 ROS_ERROR("CobTwistController::twistStampedCallback: \n%s", ex.what());
00423 return;
00424 }
00425
00426 tf::twistMsgToKDL(msg->twist, twist);
00427 twist_transformed = frame*twist;
00428 solveTwist(twist_transformed);
00429 }
00430
00432 void CobTwistController::twistCallback(const geometry_msgs::Twist::ConstPtr& msg)
00433 {
00434 KDL::Twist twist;
00435 tf::twistMsgToKDL(*msg, twist);
00436 solveTwist(twist);
00437 }
00438
00440 void CobTwistController::solveTwist(KDL::Twist twist)
00441 {
00442 ros::Time start, end;
00443 start = ros::Time::now();
00444
00445 visualizeTwist(twist);
00446
00447 KDL::JntArray q_dot_ik(chain_.getNrOfJoints());
00448
00449 if (twist_controller_params_.kinematic_extension == BASE_COMPENSATION)
00450 {
00451 twist = twist - twist_odometry_cb_;
00452 }
00453
00454 int ret_ik = p_inv_diff_kin_solver_->CartToJnt(this->joint_states_,
00455 twist,
00456 q_dot_ik);
00457
00458 if (0 != ret_ik)
00459 {
00460 ROS_ERROR("No Vel-IK found!");
00461 }
00462 else
00463 {
00464 this->controller_interface_->processResult(q_dot_ik, this->joint_states_.current_q_);
00465 }
00466
00467 end = ros::Time::now();
00468
00469 }
00470
00471 void CobTwistController::visualizeTwist(KDL::Twist twist)
00472 {
00473 std::string tracking_frame = twist_controller_params_.chain_tip_link;
00474 if (twist_controller_params_.kinematic_extension == LOOKAT)
00475 {
00476 tracking_frame = "lookat_focus_frame";
00477 }
00478
00479 tf::StampedTransform transform_tf;
00480 try
00481 {
00482 tf_listener_.lookupTransform(twist_controller_params_.chain_base_link, tracking_frame, ros::Time(0), transform_tf);
00483 }
00484 catch (tf::TransformException& ex)
00485 {
00486 ROS_ERROR("CobTwistController::visualizeTwist: \n%s", ex.what());
00487 return;
00488 }
00489
00490 visualization_msgs::Marker marker_vel;
00491 marker_vel.header.frame_id = twist_controller_params_.chain_base_link;
00492 marker_vel.header.stamp = ros::Time::now();
00493 marker_vel.ns = "twist_vel";
00494 marker_vel.id = 0;
00495 marker_vel.type = visualization_msgs::Marker::ARROW;
00496 marker_vel.action = visualization_msgs::Marker::ADD;
00497 marker_vel.lifetime = ros::Duration(0.1);
00498 marker_vel.pose.orientation.w = 1.0;
00499
00500 marker_vel.scale.x = 0.02;
00501 marker_vel.scale.y = 0.02;
00502 marker_vel.scale.z = 0.02;
00503
00504 marker_vel.color.r = 1.0f;
00505 marker_vel.color.g = 1.0f;
00506 marker_vel.color.b = 0.0f;
00507 marker_vel.color.a = 1.0;
00508
00509 marker_vel.points.resize(2);
00510 marker_vel.points[0].x = transform_tf.getOrigin().x();
00511 marker_vel.points[0].y = transform_tf.getOrigin().y();
00512 marker_vel.points[0].z = transform_tf.getOrigin().z();
00513 marker_vel.points[1].x = transform_tf.getOrigin().x() + 5.0 * twist.vel.x();
00514 marker_vel.points[1].y = transform_tf.getOrigin().y() + 5.0 * twist.vel.y();
00515 marker_vel.points[1].z = transform_tf.getOrigin().z() + 5.0 * twist.vel.z();
00516
00517 visualization_msgs::Marker marker_rot;
00518 marker_rot.header.frame_id = twist_controller_params_.chain_base_link;
00519 marker_rot.header.stamp = ros::Time::now();
00520 marker_rot.ns = "twist_rot";
00521 marker_rot.id = 0;
00522 marker_rot.type = visualization_msgs::Marker::CYLINDER;
00523 marker_rot.action = visualization_msgs::Marker::ADD;
00524 marker_rot.lifetime = ros::Duration(0.1);
00525 marker_rot.pose.position.x = transform_tf.getOrigin().x();
00526 marker_rot.pose.position.y = transform_tf.getOrigin().y();
00527 marker_rot.pose.position.z = transform_tf.getOrigin().z();
00528
00529 tf::Quaternion rot;
00530 rot.setRPY(twist.rot.x(), twist.rot.y(), twist.rot.z());
00531
00533 tf::Vector3 z_axis = tf::Vector3(0, 0, 1);
00534 tf::Vector3 t_axis = rot.getAxis();
00535 tf::Quaternion temp(0, 0, 0, 1);
00536 if (z_axis != t_axis && z_axis != -t_axis)
00537 {
00538 tf::Vector3 cross = z_axis.cross(t_axis);
00539 temp = tf::Quaternion(cross.x(), cross.y(), cross.z(), (std::sqrt(z_axis.length2() * t_axis.length2()) + z_axis.dot(t_axis)));
00540 temp = temp.normalized();
00541 }
00542 tf::quaternionTFToMsg(temp, marker_rot.pose.orientation);
00543
00544 marker_rot.scale.x = rot.getAngle();
00545 marker_rot.scale.y = rot.getAngle();
00546 marker_rot.scale.z = 0.002;
00547
00548 marker_rot.color.r = 1.0f;
00549 marker_rot.color.g = 1.0f;
00550 marker_rot.color.b = 0.0f;
00551 marker_rot.color.a = 1.0;
00552
00553 visualization_msgs::MarkerArray markers;
00554 markers.markers.push_back(marker_vel);
00555 markers.markers.push_back(marker_rot);
00556
00557 twist_direction_pub_.publish(markers);
00558 }
00559
00560 void CobTwistController::jointstateCallback(const sensor_msgs::JointState::ConstPtr& msg)
00561 {
00562 KDL::JntArray q_temp = this->joint_states_.current_q_;
00563 KDL::JntArray q_dot_temp = this->joint_states_.current_q_dot_;
00564 int count = 0;
00565
00566 for (uint16_t j = 0; j < twist_controller_params_.dof; j++)
00567 {
00568 for (uint16_t i = 0; i < msg->name.size(); i++)
00569 {
00570 if (strcmp(msg->name[i].c_str(), twist_controller_params_.joints[j].c_str()) == 0)
00571 {
00572 q_temp(j) = msg->position[i];
00573 q_dot_temp(j) = msg->velocity[i];
00574 count++;
00575 break;
00576 }
00577 }
00578 }
00579
00580 if (count == twist_controller_params_.joints.size())
00581 {
00582 this->joint_states_.last_q_ = joint_states_.current_q_;
00583 this->joint_states_.last_q_dot_ = joint_states_.current_q_dot_;
00584 this->joint_states_.current_q_ = q_temp;
00585 this->joint_states_.current_q_dot_ = q_dot_temp;
00586 }
00587 }
00588
00589 void CobTwistController::odometryCallback(const nav_msgs::Odometry::ConstPtr& msg)
00590 {
00591 KDL::Twist twist_odometry_bl, tangential_twist_bl, twist_odometry_transformed_cb;
00592 KDL::Frame cb_frame_bl;
00593 tf::StampedTransform cb_transform_bl, bl_transform_ct;
00594
00595 try
00596 {
00597 tf_listener_.waitForTransform(twist_controller_params_.chain_base_link, "base_link", ros::Time(0), ros::Duration(0.5));
00598 tf_listener_.lookupTransform(twist_controller_params_.chain_base_link, "base_link", ros::Time(0), cb_transform_bl);
00599
00600 tf_listener_.waitForTransform("base_link", twist_controller_params_.chain_tip_link, ros::Time(0), ros::Duration(0.5));
00601 tf_listener_.lookupTransform("base_link", twist_controller_params_.chain_tip_link, ros::Time(0), bl_transform_ct);
00602
00603 cb_frame_bl.p = KDL::Vector(cb_transform_bl.getOrigin().x(), cb_transform_bl.getOrigin().y(), cb_transform_bl.getOrigin().z());
00604 cb_frame_bl.M = KDL::Rotation::Quaternion(cb_transform_bl.getRotation().x(), cb_transform_bl.getRotation().y(), cb_transform_bl.getRotation().z(), cb_transform_bl.getRotation().w());
00605 }
00606 catch (tf::TransformException& ex)
00607 {
00608 ROS_ERROR("CobTwistController::odometryCallback: \n%s", ex.what());
00609 return;
00610 }
00611
00612 try
00613 {
00614
00615 Eigen::Vector3d r(bl_transform_ct.getOrigin().x(), bl_transform_ct.getOrigin().y(), bl_transform_ct.getOrigin().z());
00616 Eigen::Vector3d w(0, 0, msg->twist.twist.angular.z);
00617 Eigen::Vector3d res = w.cross(r);
00618 tangential_twist_bl.vel = KDL::Vector(res(0), res(1), res(2));
00619 tangential_twist_bl.rot = KDL::Vector(0, 0, 0);
00620 }
00621 catch(...)
00622 {
00623 ROS_ERROR("Error occurred while calculating tangential twist for angular base movements.");
00624 return;
00625 }
00626
00627 tf::twistMsgToKDL(msg->twist.twist, twist_odometry_bl);
00628
00629
00630 twist_odometry_transformed_cb = cb_frame_bl * (twist_odometry_bl + tangential_twist_bl);
00631
00632 twist_odometry_cb_ = twist_odometry_transformed_cb;
00633 }