cob_twist_controller.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *   http://www.apache.org/licenses/LICENSE-2.0
00009 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
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     // JointNames
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     // Chain
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     // links of the chain to be considered for collision avoidance
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     // Currently not supported yet
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         // ROS_ERROR("Parameter 'limits_acc' not set or dimensions do not match! Not limiting acceleration!");
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     // Configure Lookat Extenstion (Offset and Axis) --- not dynamic-reconfigurable
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     // Configure Controller Interface
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;  // in [m]
00267     cp_ca.thresholds.critical = config.critical_threshold_ca;  // in [m]
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         //damping method has changed - setting back to proper default values
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     // ROS_INFO_STREAM("solveTwist took " << (end-start).toSec() << " seconds");
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         // Calculate tangential twist for angular base movements v = w x r
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);  // Base Twist
00628 
00629     // transform into chain_base
00630     twist_odometry_transformed_cb = cb_frame_bl * (twist_odometry_bl + tangential_twist_bl);
00631 
00632     twist_odometry_cb_ = twist_odometry_transformed_cb;
00633 }


cob_twist_controller
Author(s): Felix Messmer , Marco Bezzon , Christoph Mark , Francisco Moreno
autogenerated on Thu Jun 6 2019 21:19:26