YouBotOODLWrapper.cpp
Go to the documentation of this file.
00001 /******************************************************************************
00002  * Copyright (c) 2011
00003  * Locomotec
00004  *
00005  * Author:
00006  * Sebastian Blumenthal
00007  *
00008  *
00009  * This software is published under a dual-license: GNU Lesser General Public
00010  * License LGPL 2.1 and BSD license. The dual-license implies that users of this
00011  * code may choose which terms they prefer.
00012  *
00013  * Redistribution and use in source and binary forms, with or without
00014  * modification, are permitted provided that the following conditions are met:
00015  *
00016  * * Redistributions of source code must retain the above copyright
00017  * notice, this list of conditions and the following disclaimer.
00018  * * Redistributions in binary form must reproduce the above copyright
00019  * notice, this list of conditions and the following disclaimer in the
00020  * documentation and/or other materials provided with the distribution.
00021  * * Neither the name of Locomotec nor the names of its
00022  * contributors may be used to endorse or promote products derived from
00023  * this software without specific prior written permission.
00024  *
00025  * This program is free software: you can redistribute it and/or modify
00026  * it under the terms of the GNU Lesser General Public License LGPL as
00027  * published by the Free Software Foundation, either version 2.1 of the
00028  * License, or (at your option) any later version or the BSD license.
00029  *
00030  * This program is distributed in the hope that it will be useful,
00031  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00032  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00033  * GNU Lesser General Public License LGPL and the BSD license for more details.
00034  *
00035  * You should have received a copy of the GNU Lesser General Public
00036  * License LGPL and BSD license along with this program.
00037  *
00038  ******************************************************************************/
00039 
00040 #include "youbot_driver_ros_interface/YouBotOODLWrapper.h"
00041 #include "youbot_driver_ros_interface/joint_state_observer_oodl.h"
00042 
00043 #include <youbot_trajectory_action_server/joint_trajectory_action.h>
00044 #include <sstream>
00045 
00046 namespace youBot
00047 {
00048 
00049 YouBotOODLWrapper::YouBotOODLWrapper()
00050 {
00051 }
00052 
00053 YouBotOODLWrapper::YouBotOODLWrapper(ros::NodeHandle n) :
00054 node(n)
00055 {
00056 
00057     youBotConfiguration.hasBase = false;
00058     youBotConfiguration.hasArms = false;
00059     areBaseMotorsSwitchedOn = false;    
00060     areArmMotorsSwitchedOn = false;
00061 
00062     youBotChildFrameID = "base_link"; //holds true for both: base and arm
00063     armJointStateMessages.clear();
00064 
00065     n.param("youBotDriverCycleFrequencyInHz", youBotDriverCycleFrequencyInHz, 50.0);
00066     //n.param("trajectoryActionServerEnable", trajectoryActionServerEnable, false);
00067     //n.param("trajectoryVelocityGain", trajectoryVelocityGain, 0.0);
00068     //n.param("trajectoryPositionGain", trajectoryPositionGain, 5.0);
00069     gripperCycleCounter = 0;
00070     diagnosticNameArm = "platform_Arm";
00071     diagnosticNameBase = "platform_Base";
00072     dashboardMessagePublisher = n.advertise<pr2_msgs::PowerBoardState>("/dashboard/platform_state", 1);
00073     diagnosticArrayPublisher = n.advertise<diagnostic_msgs::DiagnosticArray>("/diagnostics", 1);
00074 }
00075 
00076 YouBotOODLWrapper::~YouBotOODLWrapper()
00077 {
00078     this->stop();
00079     dashboardMessagePublisher.shutdown();
00080     diagnosticArrayPublisher.shutdown();
00081 }
00082 
00083 void YouBotOODLWrapper::initializeBase(std::string baseName)
00084 {
00085 
00086     try
00087     {
00088         youBotConfiguration.baseConfiguration.youBotBase = new youbot::YouBotBase(baseName, youBotConfiguration.configurationFilePath);
00089         youBotConfiguration.baseConfiguration.youBotBase->doJointCommutation();
00090     }
00091     catch (std::exception& e)
00092     {
00093         std::string errorMessage = e.what();
00094         ROS_FATAL("%s", errorMessage.c_str());
00095         ROS_ERROR("Base \"%s\" could not be initialized.", baseName.c_str());
00096         youBotConfiguration.hasBase = false;
00097         return;
00098     }
00099 
00100     /* setup input/output communication */
00101     youBotConfiguration.baseConfiguration.baseCommandSubscriber = node.subscribe("cmd_vel", 1000, &YouBotOODLWrapper::baseCommandCallback, this);
00102     youBotConfiguration.baseConfiguration.baseOdometryPublisher = node.advertise<nav_msgs::Odometry > ("odom", 1);
00103     youBotConfiguration.baseConfiguration.baseJointStatePublisher = node.advertise<sensor_msgs::JointState > ("base/joint_states", 1);
00104 
00105     /* setup services*/
00106     youBotConfiguration.baseConfiguration.switchOffMotorsService = node.advertiseService("base/switchOffMotors", &YouBotOODLWrapper::switchOffBaseMotorsCallback, this);
00107     youBotConfiguration.baseConfiguration.switchONMotorsService = node.advertiseService("base/switchOnMotors", &YouBotOODLWrapper::switchOnBaseMotorsCallback, this);
00108 
00109     /* setup frame_ids */
00110     youBotOdometryFrameID = "odom";
00111     youBotOdometryChildFrameID = "base_footprint";
00112 
00113     ROS_INFO("Base is initialized.");
00114     youBotConfiguration.hasBase = true;
00115     areBaseMotorsSwitchedOn = true;
00116 }
00117 
00118 void YouBotOODLWrapper::initializeArm(std::string armName, bool enableStandardGripper)
00119 {
00120     int armIndex;
00121     youbot::JointName jointNameParameter;
00122     std::string jointName;
00123     stringstream topicName;
00124     stringstream serviceName;
00125 
00126     try
00127     {
00128         YouBotArmConfiguration tmpArmConfig;
00129         youBotConfiguration.youBotArmConfigurations.push_back(tmpArmConfig);
00130         armIndex = static_cast<int> (youBotConfiguration.youBotArmConfigurations.size()) - 1;
00131         youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm = new youbot::YouBotManipulator(armName, youBotConfiguration.configurationFilePath);
00132         youBotConfiguration.youBotArmConfigurations[armIndex].armID = armName;
00133         topicName.str("");
00134         topicName << "arm_" << (armIndex + 1) << "/";
00135         youBotConfiguration.youBotArmConfigurations[armIndex].commandTopicName = topicName.str(); // e.g. arm_1/
00136         youBotConfiguration.youBotArmConfigurations[armIndex].parentFrameIDName = "base_link";
00137         youBotConfiguration.armNameToArmIndexMapping.insert(make_pair(armName, static_cast<int> (youBotConfiguration.youBotArmConfigurations.size())));
00138 
00139         /* take joint names form configuration files */
00140         youBotConfiguration.youBotArmConfigurations[armIndex].jointNames.clear();
00141         for (int i = 0; i < youBotArmDoF; ++i)
00142         {
00143             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(i + 1).getConfigurationParameter(jointNameParameter);
00144             jointNameParameter.getParameter(jointName);
00145             youBotConfiguration.youBotArmConfigurations[armIndex].jointNames.push_back(jointName);
00146             ROS_INFO("Joint %i for arm %s has name: %s", i + 1, youBotConfiguration.youBotArmConfigurations[armIndex].armID.c_str(), youBotConfiguration.youBotArmConfigurations[armIndex].jointNames[i].c_str());
00147 
00148         }
00149 
00150 
00151         youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->doJointCommutation();
00152         youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->calibrateManipulator();
00153         if (enableStandardGripper)
00154         {
00155             youbot::GripperBarName barName;
00156             std::string gripperBarName;
00157 
00158             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmGripper().getGripperBar1().getConfigurationParameter(barName);
00159             barName.getParameter(gripperBarName);
00160             youBotConfiguration.youBotArmConfigurations[armIndex].gripperFingerNames[YouBotArmConfiguration::LEFT_FINGER_INDEX] = gripperBarName;
00161             ROS_INFO("Joint %i for gripper of arm %s has name: %s", 1, youBotConfiguration.youBotArmConfigurations[armIndex].armID.c_str(), gripperBarName.c_str());
00162 
00163             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmGripper().getGripperBar2().getConfigurationParameter(barName);
00164             barName.getParameter(gripperBarName);
00165             youBotConfiguration.youBotArmConfigurations[armIndex].gripperFingerNames[YouBotArmConfiguration::RIGHT_FINGER_INDEX] = gripperBarName;
00166             ROS_INFO("Joint %i for gripper of arm %s has name: %s", 2, youBotConfiguration.youBotArmConfigurations[armIndex].armID.c_str(), gripperBarName.c_str());
00167 
00168             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->calibrateGripper();
00169         }
00170     }
00171     catch (std::exception& e)
00172     {
00173         youBotConfiguration.youBotArmConfigurations.pop_back();
00174         std::string errorMessage = e.what();
00175         ROS_FATAL("%s", errorMessage.c_str());
00176         ROS_ERROR("Arm \"%s\" could not be initialized.", armName.c_str());
00177         ROS_INFO("System has %i initialized arm(s).", static_cast<int> (youBotConfiguration.youBotArmConfigurations.size()));
00178         return;
00179     }
00180 
00181 
00182     /* setup input/output communication */
00183     topicName.str("");
00184     topicName << youBotConfiguration.youBotArmConfigurations[armIndex].commandTopicName << "arm_controller/position_command"; // e.g. arm_1/arm_controller/positionCommand
00185     youBotConfiguration.youBotArmConfigurations[armIndex].armPositionCommandSubscriber = node.subscribe<brics_actuator::JointPositions > (topicName.str(), 1000, boost::bind(&YouBotOODLWrapper::armPositionsCommandCallback, this, _1, armIndex));
00186 
00187     topicName.str("");
00188     topicName << youBotConfiguration.youBotArmConfigurations[armIndex].commandTopicName << "arm_controller/velocity_command";
00189     youBotConfiguration.youBotArmConfigurations[armIndex].armVelocityCommandSubscriber = node.subscribe<brics_actuator::JointVelocities > (topicName.str(), 1000, boost::bind(&YouBotOODLWrapper::armVelocitiesCommandCallback, this, _1, armIndex));
00190 
00191     topicName.str("");
00192     topicName << youBotConfiguration.youBotArmConfigurations[armIndex].commandTopicName << "arm_controller/follow_joint_trajectory";
00193     // topicName.str("/arm_1/arm_controller/follow_joint_trajectory");
00194     youBotConfiguration.youBotArmConfigurations[armIndex].armJointTrajectoryAction = new actionlib::ActionServer<control_msgs::FollowJointTrajectoryAction > (
00195                     node, topicName.str(),
00196                     boost::bind(&YouBotOODLWrapper::armJointTrajectoryGoalCallback, this, _1, armIndex),
00197                     boost::bind(&YouBotOODLWrapper::armJointTrajectoryCancelCallback, this, _1, armIndex), false);
00198 
00199 
00200     topicName.str("");
00201     topicName << youBotConfiguration.youBotArmConfigurations[armIndex].commandTopicName << "joint_states";
00202     youBotConfiguration.youBotArmConfigurations[armIndex].armJointStatePublisher = node.advertise<sensor_msgs::JointState > (topicName.str(), 1); //TODO different names or one topic?
00203 
00204     if (enableStandardGripper)
00205     {
00206         topicName.str("");
00207         topicName << youBotConfiguration.youBotArmConfigurations[armIndex].commandTopicName << "gripper_controller/position_command";
00208         youBotConfiguration.youBotArmConfigurations[armIndex].gripperPositionCommandSubscriber = node.subscribe<brics_actuator::JointPositions > (topicName.str(), 1000, boost::bind(&YouBotOODLWrapper::gripperPositionsCommandCallback, this, _1, armIndex));
00209         youBotConfiguration.youBotArmConfigurations[armIndex].lastGripperCommand = 0.0; //This is true if the gripper is calibrated.
00210     }
00211 
00212 
00213 
00214     /* setup services*/
00215     serviceName.str("");
00216     serviceName << youBotConfiguration.youBotArmConfigurations[armIndex].commandTopicName << "switchOffMotors"; // e.g. "arm_1/switchOffMotors"
00217     youBotConfiguration.youBotArmConfigurations[armIndex].switchOffMotorsService = node.advertiseService<std_srvs::Empty::Request, std_srvs::Empty::Response > (serviceName.str(), boost::bind(&YouBotOODLWrapper::switchOffArmMotorsCallback, this, _1, _2, armIndex));
00218 
00219     serviceName.str("");
00220     serviceName << youBotConfiguration.youBotArmConfigurations[armIndex].commandTopicName << "switchOnMotors"; // e.g. "arm_1/switchOnMotors"
00221     youBotConfiguration.youBotArmConfigurations[armIndex].switchONMotorsService = node.advertiseService<std_srvs::Empty::Request, std_srvs::Empty::Response > (serviceName.str(), boost::bind(&YouBotOODLWrapper::switchOnArmMotorsCallback, this, _1, _2, armIndex));
00222 
00223     serviceName.str("");
00224     serviceName << youBotConfiguration.youBotArmConfigurations[armIndex].commandTopicName << "calibrate"; // e.g. "arm_1/calibrate"
00225     youBotConfiguration.youBotArmConfigurations[armIndex].calibrateService = node.advertiseService<std_srvs::Empty::Request, std_srvs::Empty::Response > (serviceName.str(), boost::bind(&YouBotOODLWrapper::calibrateArmCallback, this, _1, _2, armIndex));
00226 /*
00227     if (trajectoryActionServerEnable)
00228     {
00229         JointStateObserver* jointStateObserver = new JointStateObserverOODL(this, armIndex);
00230         topicName.str("");
00231         topicName << youBotConfiguration.youBotArmConfigurations[armIndex].commandTopicName << "action";
00232         youBotConfiguration.youBotArmConfigurations[armIndex].jointTrajectoryAction = new JointTrajectoryAction(jointStateObserver,
00233                                                                                                                 trajectoryPositionGain,
00234                                                                                                                 trajectoryVelocityGain,
00235                                                                                                                 youBotDriverCycleFrequencyInHz);
00236 
00237         serviceName.str("");
00238         serviceName << youBotConfiguration.youBotArmConfigurations[armIndex].commandTopicName << "arm_controller/joint_trajectory_action"; // e.g. "arm_1/switchOnMotors"
00239         
00240         youBotConfiguration.youBotArmConfigurations[armIndex].trajectoryActionServer = new Server(serviceName.str(),
00241                                                                                                   boost::bind(&YouBotOODLWrapper::executeActionServer, this, _1, armIndex),
00242                                                                                                   false);
00243         youBotConfiguration.youBotArmConfigurations[armIndex].trajectoryActionServer->start();
00244     }
00245 */
00246     /* initialize message vector for arm joint states */
00247     sensor_msgs::JointState dummyMessage;
00248     armJointStateMessages.push_back(dummyMessage);
00249 
00250     /* setup frame_ids */
00251     youBotArmFrameID = "arm"; //TODO find default topic name
00252     ROS_INFO("Arm \"%s\" is initialized.", armName.c_str());
00253     ROS_INFO("System has %i initialized arm(s).", static_cast<int> (youBotConfiguration.youBotArmConfigurations.size()));
00254     youBotConfiguration.hasArms = true;
00255     areArmMotorsSwitchedOn = true;
00256 
00257     // currently no action is running
00258     armHasActiveJointTrajectoryGoal = false;
00259 
00260     //tracejoint = 4;
00261     //myTrace = new youbot::DataTrace(youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(tracejoint), "Joint4TrajectoryTrace");
00262 
00263     // we can handle actionlib requests only after the complete initialization has been performed
00264     youBotConfiguration.youBotArmConfigurations[armIndex].armJointTrajectoryAction->start();
00265 }
00266 
00267 /*
00268 void YouBotOODLWrapper::executeActionServer(const control_msgs::FollowJointTrajectoryGoalConstPtr& goal, int armIndex)
00269 {
00270 
00271     JointTrajectoryAction* jointTrajectoryAction = youBotConfiguration.youBotArmConfigurations[armIndex].jointTrajectoryAction;
00272     if (jointTrajectoryAction != NULL)
00273     {
00274 
00275         jointTrajectoryAction->execute(goal, youBotConfiguration.youBotArmConfigurations[armIndex].trajectoryActionServer);
00276     }
00277 }
00278 */
00279 void YouBotOODLWrapper::stop()
00280 {
00281 
00282     if (youBotConfiguration.baseConfiguration.youBotBase)
00283     {
00284         delete youBotConfiguration.baseConfiguration.youBotBase;
00285         youBotConfiguration.baseConfiguration.youBotBase = 0;
00286     }
00287 
00288     youBotConfiguration.baseConfiguration.baseCommandSubscriber.shutdown();
00289     youBotConfiguration.baseConfiguration.baseJointStatePublisher.shutdown();
00290     youBotConfiguration.baseConfiguration.baseOdometryPublisher.shutdown();
00291     youBotConfiguration.baseConfiguration.switchONMotorsService.shutdown();
00292     youBotConfiguration.baseConfiguration.switchOffMotorsService.shutdown();
00293     // youBotConfiguration.baseConfiguration.odometryBroadcaster.
00294     youBotConfiguration.hasBase = false;
00295     areBaseMotorsSwitchedOn = false;
00296 
00297 
00298     for (int armIndex = 0; armIndex < static_cast<int> (youBotConfiguration.youBotArmConfigurations.size()); armIndex++) //delete each arm
00299     {
00300         if (youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm)
00301         {
00302             delete youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm;
00303             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm = 0;
00304         }
00305 
00306         youBotConfiguration.youBotArmConfigurations[armIndex].armJointStatePublisher.shutdown();
00307         youBotConfiguration.youBotArmConfigurations[armIndex].armPositionCommandSubscriber.shutdown();
00308         youBotConfiguration.youBotArmConfigurations[armIndex].armVelocityCommandSubscriber.shutdown();
00309         youBotConfiguration.youBotArmConfigurations[armIndex].calibrateService.shutdown();
00310         youBotConfiguration.youBotArmConfigurations[armIndex].gripperPositionCommandSubscriber.shutdown();
00311         youBotConfiguration.youBotArmConfigurations[armIndex].switchONMotorsService.shutdown();
00312         youBotConfiguration.youBotArmConfigurations[armIndex].switchOffMotorsService.shutdown();
00313     }
00314 
00315     youBotConfiguration.hasArms = false;
00316     areArmMotorsSwitchedOn = false;
00317     youBotConfiguration.youBotArmConfigurations.clear();
00318     armJointStateMessages.clear();
00319 
00320     youbot::EthercatMaster::destroy();
00321 }
00322 
00323 void YouBotOODLWrapper::baseCommandCallback(const geometry_msgs::Twist& youbotBaseCommand)
00324 {
00325 
00326     if (youBotConfiguration.hasBase)
00327     { // in case stop has been invoked
00328         quantity<si::velocity> longitudinalVelocity;
00329         quantity<si::velocity> transversalVelocity;
00330         quantity<si::angular_velocity> angularVelocity;
00331 
00332         /*
00333          * Frame in OODL:
00334          *
00335          *         FRONT
00336          *
00337          *         X
00338          *         ^
00339          *         |
00340          *         |
00341          *         |
00342          * Y <-----+
00343          *
00344          *        BACK
00345          *
00346          * Positive angular velocity means turning counterclockwise
00347          *
00348          */
00349 
00350         longitudinalVelocity = youbotBaseCommand.linear.x * meter_per_second;
00351         transversalVelocity = youbotBaseCommand.linear.y * meter_per_second;
00352         angularVelocity = youbotBaseCommand.angular.z * radian_per_second;
00353 
00354         try
00355         {
00356             youBotConfiguration.baseConfiguration.youBotBase->setBaseVelocity(longitudinalVelocity, transversalVelocity, angularVelocity);
00357         }
00358         catch (std::exception& e)
00359         {
00360             std::string errorMessage = e.what();
00361             ROS_WARN("Cannot set base velocities: %s", errorMessage.c_str());
00362         }
00363 
00364     }
00365     else
00366     {
00367         ROS_ERROR("No base initialized!");
00368     }
00369 }
00370 
00371 void YouBotOODLWrapper::armPositionsCommandCallback(const brics_actuator::JointPositionsConstPtr& youbotArmCommand, int armIndex)
00372 {
00373     ROS_DEBUG("Command for arm%i received", armIndex + 1);
00374     ROS_ASSERT(0 <= armIndex && armIndex < static_cast<int> (youBotConfiguration.youBotArmConfigurations.size()));
00375 
00376     if (youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm != 0) // in case stop has been invoked
00377     {
00378 
00379         ROS_DEBUG("Arm ID is: %s", youBotConfiguration.youBotArmConfigurations[armIndex].armID.c_str());
00380         if (youbotArmCommand->positions.size() < 1)
00381         {
00382             ROS_WARN("youBot driver received an invalid joint positions command.");
00383             return;
00384         }
00385 
00386         youbot::JointAngleSetpoint desiredAngle;
00387         string unit = boost::units::to_string(boost::units::si::radian);
00388 
00389         /* populate mapping between joint names and values  */
00390         std::map<string, double> jointNameToValueMapping;
00391         for (int i = 0; i < static_cast<int> (youbotArmCommand->positions.size()); ++i)
00392         {
00393             if (unit == youbotArmCommand->positions[i].unit)
00394             {
00395                 jointNameToValueMapping.insert(make_pair(youbotArmCommand->positions[i].joint_uri, youbotArmCommand->positions[i].value));
00396             }
00397             else
00398             {
00399                 ROS_WARN("Unit incompatibility. Are you sure you want to command %s instead of %s ?", youbotArmCommand->positions[i].unit.c_str(), unit.c_str());
00400             }
00401         }
00402 
00403         /* loop over all youBot arm joints and check if something is in the received message that requires action */
00404         ROS_ASSERT(youBotConfiguration.youBotArmConfigurations[armIndex].jointNames.size() == static_cast<unsigned int> (youBotArmDoF));
00405         youbot::EthercatMaster::getInstance().AutomaticSendOn(false); // ensure that all joint values will be send at the same time
00406         for (int i = 0; i < youBotArmDoF; ++i)
00407         {
00408 
00409             /* check what is in map */
00410             map<string, double>::const_iterator jointIterator = jointNameToValueMapping.find(youBotConfiguration.youBotArmConfigurations[armIndex].jointNames[i]);
00411             if (jointIterator != jointNameToValueMapping.end())
00412             {
00413 
00414                 /* set the desired joint value */
00415                 ROS_DEBUG("Trying to set joint %s to new position value %f", (youBotConfiguration.youBotArmConfigurations[armIndex].jointNames[i]).c_str(), jointIterator->second);
00416                 desiredAngle.angle = jointIterator->second * radian;
00417                 try
00418                 {
00419                     youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(i + 1).setData(desiredAngle); //youBot joints start with 1 not with 0 -> i + 1
00420                 }
00421                 catch (std::exception& e)
00422                 {
00423                     std::string errorMessage = e.what();
00424                     ROS_WARN("Cannot set arm joint %i: %s", i + 1, errorMessage.c_str());
00425                 }
00426             }
00427         }
00428         youbot::EthercatMaster::getInstance().AutomaticSendOn(true); // ensure that all joint values will be send at the same time
00429     }
00430     else
00431     {
00432         ROS_ERROR("Arm%i is not correctly initialized!", armIndex + 1);
00433     }
00434 
00435 }
00436 
00437 void YouBotOODLWrapper::armVelocitiesCommandCallback(const brics_actuator::JointVelocitiesConstPtr& youbotArmCommand, int armIndex)
00438 {
00439     ROS_DEBUG("Command for arm%i received", armIndex + 1);
00440     ROS_ASSERT(0 <= armIndex && armIndex < static_cast<int> (youBotConfiguration.youBotArmConfigurations.size()));
00441 
00442     if (youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm != 0)
00443     { // in case stop has been invoked
00444 
00445 
00446         if (youbotArmCommand->velocities.size() < 1)
00447         {
00448             ROS_WARN("youBot driver received an invalid joint velocities command.");
00449             return;
00450         }
00451 
00452         youbot::JointVelocitySetpoint desiredAngularVelocity;
00453         string unit = boost::units::to_string(boost::units::si::radian_per_second);
00454 
00455         /* populate mapping between joint names and values  */
00456         std::map<string, double> jointNameToValueMapping;
00457         for (int i = 0; i < static_cast<int> (youbotArmCommand->velocities.size()); ++i)
00458         {
00459             if (unit == youbotArmCommand->velocities[i].unit)
00460             {
00461                 jointNameToValueMapping.insert(make_pair(youbotArmCommand->velocities[i].joint_uri, youbotArmCommand->velocities[i].value));
00462             }
00463             else
00464             {
00465                 ROS_WARN("Unit incompatibility. Are you sure you want to command %s instead of %s ?", youbotArmCommand->velocities[i].unit.c_str(), unit.c_str());
00466             }
00467 
00468         }
00469 
00470         /* loop over all youBot arm joints and check if something is in the received message that requires action */
00471         ROS_ASSERT(youBotConfiguration.youBotArmConfigurations[armIndex].jointNames.size() == static_cast<unsigned int> (youBotArmDoF));
00472         youbot::EthercatMaster::getInstance().AutomaticSendOn(false); // ensure that all joint values will be send at the same time
00473         for (int i = 0; i < youBotArmDoF; ++i)
00474         {
00475 
00476             /* check what is in map */
00477             map<string, double>::const_iterator jointIterator = jointNameToValueMapping.find(youBotConfiguration.youBotArmConfigurations[armIndex].jointNames[i]);
00478             if (jointIterator != jointNameToValueMapping.end())
00479             {
00480 
00481                 /* set the desired joint value */
00482                 ROS_DEBUG("Trying to set joint %s to new velocity value %f", (youBotConfiguration.youBotArmConfigurations[armIndex].jointNames[i]).c_str(), jointIterator->second);
00483                 desiredAngularVelocity.angularVelocity = jointIterator->second * radian_per_second;
00484                 try
00485                 {
00486                     youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(i + 1).setData(desiredAngularVelocity); //youBot joints start with 1 not with 0 -> i + 1
00487 
00488                 }
00489                 catch (std::exception& e)
00490                 {
00491                     std::string errorMessage = e.what();
00492                     ROS_WARN("Cannot set arm joint %i: %s", i + 1, errorMessage.c_str());
00493                 }
00494             }
00495         }
00496         youbot::EthercatMaster::getInstance().AutomaticSendOn(true); // ensure that all joint values will be send at the same time
00497     }
00498     else
00499     {
00500         ROS_ERROR("Arm%i is not correctly initialized!", armIndex + 1);
00501     }
00502 }
00503 
00504 
00505 void YouBotOODLWrapper::armJointTrajectoryGoalCallback(actionlib::ActionServer<control_msgs::FollowJointTrajectoryAction>::GoalHandle youbotArmGoal, unsigned int armIndex) {
00506     ROS_INFO("Goal for arm%i received", armIndex + 1);
00507     ROS_ASSERT(armIndex < youBotConfiguration.youBotArmConfigurations.size());
00508 
00509     if (youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm == 0) {
00510         ROS_ERROR("Arm%i is not correctly initialized!", armIndex + 1);
00511         youbotArmGoal.setRejected();
00512         return;
00513     }
00514 
00515 
00516     trajectory_msgs::JointTrajectory trajectory = youbotArmGoal.getGoal()->trajectory;
00517 
00518     // validate that the correct number of joints is provided in the goal
00519     if (trajectory.joint_names.size() != static_cast<unsigned int> (youBotArmDoF)) {
00520         ROS_ERROR("Trajectory is malformed! Goal has %i joint names, but only %i joints are supported", static_cast<int> (trajectory.joint_names.size()), youBotArmDoF);
00521         youbotArmGoal.setRejected();
00522         return;
00523     }
00524 
00525     // compare the joint names of the youBot configuration and joint names provided with the trajectory
00526     for (unsigned int i = 0; i < youBotConfiguration.youBotArmConfigurations[armIndex].jointNames.size(); i++) {
00527         bool jointNameFound = false;
00528         for (unsigned int j = 0; j < trajectory.joint_names.size(); j++) {
00529             if (youBotConfiguration.youBotArmConfigurations[armIndex].jointNames[i] == trajectory.joint_names[j]) {
00530                 jointNameFound = true;
00531                 break;
00532             }
00533         }
00534 
00535         if (!jointNameFound) {
00536             ROS_ERROR("Trajectory is malformed! Joint %s is missing in the goal", youBotConfiguration.youBotArmConfigurations[armIndex].jointNames[i].c_str());
00537             youbotArmGoal.setRejected();
00538             return;
00539         }
00540     }
00541 
00542   std::vector<youbot::JointTrajectory> jointTrajectories(youBotArmDoF);
00543   
00544     // convert from the ROS trajectory representation to the controller's representation
00545     std::vector<std::vector< quantity<plane_angle> > > positions(youBotArmDoF);
00546     std::vector<std::vector< quantity<angular_velocity> > > velocities(youBotArmDoF);
00547     std::vector<std::vector< quantity<angular_acceleration> > > accelerations(youBotArmDoF);
00548     youbot::TrajectorySegment segment;
00549     for (unsigned int i = 0; i < trajectory.points.size(); i++) {
00550         trajectory_msgs::JointTrajectoryPoint point = trajectory.points[i];
00551         // validate the trajectory point
00552         if ((point.positions.size() != static_cast<unsigned int> (youBotArmDoF)
00553                         || point.velocities.size() != static_cast<unsigned int> (youBotArmDoF)
00554                         || point.accelerations.size() != static_cast<unsigned int> (youBotArmDoF))) {
00555             ROS_ERROR("A trajectory point is malformed! %i positions, velocities and accelerations must be provided", youBotArmDoF);
00556             youbotArmGoal.setRejected();
00557             return;
00558         }
00559     
00560         for (int j = 0; j < youBotArmDoF; j++) {
00561             segment.positions = point.positions[j]*radian;
00562             segment.velocities = point.velocities[j]*radian_per_second;
00563             segment.accelerations = point.accelerations[j] * radian_per_second/second;
00564             segment.time_from_start = boost::posix_time::microsec(point.time_from_start.toNSec()/1000);
00565             jointTrajectories[j].segments.push_back(segment);
00566         }
00567     }
00568     for (int j = 0; j < youBotArmDoF; j++) {
00569         jointTrajectories[j].start_time = boost::posix_time::microsec_clock::local_time(); //TODO is this correct to set the trajectory start time to now
00570     }
00571 
00572   
00573   
00574 
00575     // cancel the old goal
00576   /*
00577     if (armHasActiveJointTrajectoryGoal) {
00578         armActiveJointTrajectoryGoal.setCanceled();
00579         armHasActiveJointTrajectoryGoal = false;
00580         for (int i = 0; i < youBotArmDoF; ++i) {
00581             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(i + 1).cancelTrajectory();
00582         }
00583     }
00584   */
00585 
00586     // replace the old goal with the new one
00587     youbotArmGoal.setAccepted();
00588     armActiveJointTrajectoryGoal = youbotArmGoal;
00589     armHasActiveJointTrajectoryGoal = true;
00590 
00591   
00592  // myTrace->startTrace();
00593 
00594     // send the trajectory to the controller
00595     for (int i = 0; i < youBotArmDoF; ++i) {
00596         try {
00597             // youBot joints start with 1 not with 0 -> i + 1
00598             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(i + 1).trajectoryController.setTrajectory(jointTrajectories[i]);
00599       ROS_INFO("set trajectories %d", i);
00600         } catch (std::exception& e) {
00601             std::string errorMessage = e.what();
00602             ROS_WARN("Cannot set trajectory for joint %i: %s", i + 1, errorMessage.c_str());
00603         }
00604     }
00605     ROS_INFO("set all trajectories");
00606 }
00607 
00608 void YouBotOODLWrapper::armJointTrajectoryCancelCallback(actionlib::ActionServer<control_msgs::FollowJointTrajectoryAction>::GoalHandle youbotArmGoal, unsigned int armIndex) {
00609     ROS_DEBUG("Goal for arm%i received", armIndex + 1);
00610     ROS_ASSERT(armIndex < youBotConfiguration.youBotArmConfigurations.size());
00611 
00612     // stop the controller
00613     for (int i = 0; i < youBotArmDoF; ++i) {
00614         try {
00615             // youBot joints start with 1 not with 0 -> i + 1
00616       //TODO cancel trajectory
00617             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(i + 1).trajectoryController.cancelCurrentTrajectory();
00618             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(i + 1).stopJoint();
00619         } catch (std::exception& e) {
00620             std::string errorMessage = e.what();
00621             ROS_WARN("Cannot stop joint %i: %s", i + 1, errorMessage.c_str());
00622         }
00623     }
00624 
00625     if (armActiveJointTrajectoryGoal == youbotArmGoal) {
00626         // Marks the current goal as canceled.
00627         youbotArmGoal.setCanceled();
00628         armHasActiveJointTrajectoryGoal = false;
00629     }
00630 }
00631 
00632 void YouBotOODLWrapper::gripperPositionsCommandCallback(const brics_actuator::JointPositionsConstPtr& youbotGripperCommand, int armIndex)
00633 {
00634     ROS_DEBUG("Command for gripper%i received", armIndex + 1);
00635     ROS_ASSERT(0 <= armIndex && armIndex < static_cast<int>(youBotConfiguration.youBotArmConfigurations.size()));
00636 
00637     if (youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm != 0) { // in case stop has been invoked
00638 
00639         if (youbotGripperCommand->positions.size() < 1){
00640             ROS_WARN("youBot driver received an invalid gripper positions command.");
00641             return;
00642         }
00643 
00644         map<string, double>::const_iterator gripperIterator;
00645         youbot::GripperBarPositionSetPoint leftGripperFingerPosition;
00646         youbot::GripperBarPositionSetPoint rightGripperFingerPosition;
00647         string unit = boost::units::to_string(boost::units::si::meter);
00648 
00649         /* populate mapping between joint names and values */
00650         std::map<string, double> jointNameToValueMapping;
00651         for (int i = 0; i < static_cast<int>(youbotGripperCommand->positions.size()); ++i) {
00652             if (unit == youbotGripperCommand->positions[i].unit) {
00653                 jointNameToValueMapping.insert(make_pair(youbotGripperCommand->positions[i].joint_uri, youbotGripperCommand->positions[i].value));
00654             } else {
00655                 ROS_WARN("Unit incompatibility. Are you sure you want to command %s instead of %s ?", youbotGripperCommand->positions[i].unit.c_str(), unit.c_str());
00656             }
00657         }
00658 
00659         youbot::EthercatMaster::getInstance().AutomaticSendOn(false); // ensure that all joint values will be send at the same time
00660 
00661         /* check if something is in the received message that requires action for the left finger gripper */
00662         gripperIterator = jointNameToValueMapping.find(youBotConfiguration.youBotArmConfigurations[armIndex].gripperFingerNames[YouBotArmConfiguration::LEFT_FINGER_INDEX]);
00663         if (gripperIterator != jointNameToValueMapping.end()) {
00664             ROS_DEBUG("Trying to set the left gripper finger to new value %f", gripperIterator->second);
00665 
00666             leftGripperFingerPosition.barPosition = gripperIterator->second * meter;
00667             try {
00668                 youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmGripper().getGripperBar1().setData(leftGripperFingerPosition);
00669             } catch (std::exception& e) {
00670                 std::string errorMessage = e.what();
00671                 ROS_WARN("Cannot set the left gripper finger: %s", errorMessage.c_str());
00672             }
00673         }
00674 
00675         /* check if something is in the received message that requires action for the right finger gripper */
00676         gripperIterator = jointNameToValueMapping.find(youBotConfiguration.youBotArmConfigurations[armIndex].gripperFingerNames[YouBotArmConfiguration::RIGHT_FINGER_INDEX]);
00677         if (gripperIterator != jointNameToValueMapping.end()) {
00678             ROS_DEBUG("Trying to set the right gripper to new value %f", gripperIterator->second);
00679 
00680             rightGripperFingerPosition.barPosition = gripperIterator->second * meter;
00681             try {
00682                 youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmGripper().getGripperBar2().setData(rightGripperFingerPosition);
00683             } catch (std::exception& e) {
00684                 std::string errorMessage = e.what();
00685                 ROS_WARN("Cannot set the right gripper finger: %s", errorMessage.c_str());
00686             }
00687         }
00688 
00689         youbot::EthercatMaster::getInstance().AutomaticSendOn(true); // ensure that all joint values will be send at the same time
00690     } else {
00691         ROS_ERROR("Arm%i is not correctly initialized!", armIndex + 1);
00692     }
00693 }
00694 
00695 void YouBotOODLWrapper::computeOODLSensorReadings()
00696 {
00697 
00698     try{
00699     currentTime = ros::Time::now();
00700     youbot::JointSensedAngle currentAngle;
00701     youbot::JointSensedVelocity currentVelocity;
00702     youbot::JointSensedTorque currentTorque;
00703 
00704     youbot::EthercatMaster::getInstance().AutomaticReceiveOn(false); // ensure that all joint values will be received at the same time
00705 
00706     if (youBotConfiguration.hasBase == true)
00707     {
00708         double x = 0.0;
00709         double y = 0.0;
00710         double theta = 0.0;
00711 
00712         double vx = 0.0;
00713         double vy = 0.0;
00714         double vtheta = 0.0;
00715 
00716         quantity<si::length> longitudinalPosition;
00717         quantity<si::length> transversalPosition;
00718         quantity<plane_angle> orientation;
00719 
00720         quantity<si::velocity> longitudinalVelocity;
00721         quantity<si::velocity> transversalVelocity;
00722         quantity<si::angular_velocity> angularVelocity;
00723 
00724         youBotConfiguration.baseConfiguration.youBotBase->getBasePosition(longitudinalPosition, transversalPosition, orientation);
00725         x = longitudinalPosition.value();
00726         y = transversalPosition.value();
00727         theta = orientation.value();
00728 
00729         youBotConfiguration.baseConfiguration.youBotBase->getBaseVelocity(longitudinalVelocity, transversalVelocity, angularVelocity);
00730         vx = longitudinalVelocity.value();
00731         vy = transversalVelocity.value();
00732         vtheta = angularVelocity.value();
00733         //ROS_DEBUG("Perceived odometric values (x,y,tetha, vx,vy,vtetha): %f, %f, %f \t %f, %f, %f", x, y, theta, vx, vy, vtheta);
00734 
00735 
00736         /* Setup odometry tf frame */
00737         odometryQuaternion = tf::createQuaternionMsgFromYaw(theta);
00738 
00739         odometryTransform.header.stamp = currentTime;
00740         odometryTransform.header.frame_id = youBotOdometryFrameID;
00741         odometryTransform.child_frame_id = youBotOdometryChildFrameID;
00742 
00743         odometryTransform.transform.translation.x = x;
00744         odometryTransform.transform.translation.y = y;
00745         odometryTransform.transform.translation.z = 0.0;
00746         odometryTransform.transform.rotation = odometryQuaternion;
00747 
00748         /* Setup odometry Message */
00749         odometryMessage.header.stamp = currentTime;
00750         odometryMessage.header.frame_id = youBotOdometryFrameID;
00751 
00752         odometryMessage.pose.pose.position.x = x;
00753         odometryMessage.pose.pose.position.y = y;
00754         odometryMessage.pose.pose.position.z = 0.0;
00755         odometryMessage.pose.pose.orientation = odometryQuaternion;
00756 
00757         odometryMessage.child_frame_id = youBotOdometryChildFrameID;
00758         //        odometryMessage.child_frame_id = youBotOdometryFrameID;
00759         odometryMessage.twist.twist.linear.x = vx;
00760         odometryMessage.twist.twist.linear.y = vy;
00761         odometryMessage.twist.twist.angular.z = vtheta;
00762 
00763         /* Set up joint state message for the wheels */
00764         baseJointStateMessage.header.stamp = currentTime;
00765         baseJointStateMessage.name.resize(youBotNumberOfWheels * 2); // *2 because of virtual wheel joints in the URDF description
00766         baseJointStateMessage.position.resize(youBotNumberOfWheels * 2);
00767         baseJointStateMessage.velocity.resize(youBotNumberOfWheels * 2);
00768 
00769         ROS_ASSERT((youBotConfiguration.baseConfiguration.wheelNames.size() == static_cast<unsigned int> (youBotNumberOfWheels)));
00770         for (int i = 0; i < youBotNumberOfWheels; ++i)
00771         {
00772             youBotConfiguration.baseConfiguration.youBotBase->getBaseJoint(i + 1).getData(currentAngle); //youBot joints start with 1 not with 0 -> i + 1
00773             youBotConfiguration.baseConfiguration.youBotBase->getBaseJoint(i + 1).getData(currentVelocity);
00774 
00775             baseJointStateMessage.name[i] = youBotConfiguration.baseConfiguration.wheelNames[i];
00776             baseJointStateMessage.position[i] = currentAngle.angle.value();
00777             baseJointStateMessage.velocity[i] = currentVelocity.angularVelocity.value();
00778         }
00779 
00780         /*
00781          * Here we add values for "virtual" rotation joints in URDF - robot_state_publisher can't
00782          * handle non-aggregated jointState messages well ...
00783          */
00784         baseJointStateMessage.name[4] = "caster_joint_fl";
00785         baseJointStateMessage.position[4] = 0.0;
00786 
00787         baseJointStateMessage.name[5] = "caster_joint_fr";
00788         baseJointStateMessage.position[5] = 0.0;
00789 
00790         baseJointStateMessage.name[6] = "caster_joint_bl";
00791         baseJointStateMessage.position[6] = 0.0;
00792 
00793         baseJointStateMessage.name[7] = "caster_joint_br";
00794         baseJointStateMessage.position[7] = 0.0;
00795 
00796         /*
00797          * Yet another hack to make the published values compatible with the URDF description.
00798          * We actually flipp the directions of the wheel on the right side such that the standard ROS controllers
00799          * (e.g. for PR2) can be used for the youBot
00800          */
00801         baseJointStateMessage.position[0] = -baseJointStateMessage.position[0];
00802         baseJointStateMessage.position[2] = -baseJointStateMessage.position[2];
00803 
00804     }
00805 
00806     if (youBotConfiguration.hasArms == true)
00807     {
00808 
00809         for (int armIndex = 0; armIndex < static_cast<int> (youBotConfiguration.youBotArmConfigurations.size()); armIndex++)
00810         {
00811             ROS_ASSERT(youBotConfiguration.youBotArmConfigurations.size() == armJointStateMessages.size());
00812 
00813             /* fill joint state message */
00814             armJointStateMessages[armIndex].header.stamp = currentTime;
00815             armJointStateMessages[armIndex].name.resize(youBotArmDoF + youBotNumberOfFingers);
00816             armJointStateMessages[armIndex].position.resize(youBotArmDoF + youBotNumberOfFingers);
00817             armJointStateMessages[armIndex].velocity.resize(youBotArmDoF + youBotNumberOfFingers);
00818             armJointStateMessages[armIndex].effort.resize(youBotArmDoF + youBotNumberOfFingers);
00819 
00820             if (youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm == 0)
00821             {
00822                 ROS_ERROR("Arm%i is not correctly initialized! Cannot publish data.", armIndex + 1);
00823                 continue;
00824             }
00825 
00826             ROS_ASSERT(youBotConfiguration.youBotArmConfigurations[armIndex].jointNames.size() == static_cast<unsigned int> (youBotArmDoF));
00827             for (int i = 0; i < youBotArmDoF; ++i)
00828             {
00829                 youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(i + 1).getData(currentAngle); //youBot joints start with 1 not with 0 -> i + 1 //FIXME might segfault if only 1eout of 2 arms are initialized.
00830                 youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(i + 1).getData(currentVelocity);
00831                 youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(i + 1).getData(currentTorque);
00832 
00833                 armJointStateMessages[armIndex].name[i] = youBotConfiguration.youBotArmConfigurations[armIndex].jointNames[i]; //TODO no unique names for URDF yet
00834                 armJointStateMessages[armIndex].position[i] = currentAngle.angle.value();
00835                 armJointStateMessages[armIndex].velocity[i] = currentVelocity.angularVelocity.value();
00836                 armJointStateMessages[armIndex].effort[i] = currentTorque.torque.value();
00837             }
00838 
00839             // check if trajectory controller is finished
00840             bool areTrajectoryControllersDone = true;
00841             for (int i = 0; i < youBotArmDoF; ++i) {
00842                 if (youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(i + 1).trajectoryController.isTrajectoryControllerActive()) {
00843                     areTrajectoryControllersDone = false;
00844                     break;
00845                 }
00846             }
00847             if (areTrajectoryControllersDone && armHasActiveJointTrajectoryGoal) {
00848                 armHasActiveJointTrajectoryGoal = false;
00849                 control_msgs::FollowJointTrajectoryResult trajectoryResult;
00850                 trajectoryResult.error_code = trajectoryResult.SUCCESSFUL;
00851                 armActiveJointTrajectoryGoal.setSucceeded(trajectoryResult, "trajectory successful");
00852                 // ROS_INFO("trajectory successful");
00853                 // myTrace->stopTrace();
00854                 // myTrace->plotTrace();
00855                         }
00856 
00857             /*
00858              * NOTE: gripper slide rails are always symmetric, but the fingers can be screwed in different
00859              * positions! The published values account for the distance between the gripper slide rails, not the fingers
00860              * themselves. Of course if the finger are screwed to the most inner position (i.e. the can close completely),
00861              * than it is correct.
00862              */
00863             try 
00864             {
00865                 youbot::YouBotGripperBar& gripperBar1 = youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmGripper().getGripperBar1();
00866                 youbot::YouBotGripperBar& gripperBar2 = youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmGripper().getGripperBar2();
00867 
00868                 if  (gripperCycleCounter == 0) { //workaround: avoid congestion of mailbox message by querying only every ith iteration
00869                     gripperCycleCounter = youBotDriverCycleFrequencyInHz/5; //approx. 5Hz here
00870                     gripperBar1.getData(gripperBar1Position);
00871                     gripperBar2.getData(gripperBar2Position);
00872                 }
00873                 gripperCycleCounter--;
00874 
00875                 armJointStateMessages[armIndex].name[youBotArmDoF + 0] = youBotConfiguration.youBotArmConfigurations[armIndex].gripperFingerNames[YouBotArmConfiguration::LEFT_FINGER_INDEX];
00876                 double leftGipperFingerPosition = gripperBar1Position.barPosition.value();
00877                 armJointStateMessages[armIndex].position[youBotArmDoF + 0] = leftGipperFingerPosition;
00878 
00879                 double rightGipperFingerPosition = gripperBar2Position.barPosition.value();
00880                 armJointStateMessages[armIndex].name[youBotArmDoF + 1] = youBotConfiguration.youBotArmConfigurations[armIndex].gripperFingerNames[YouBotArmConfiguration::RIGHT_FINGER_INDEX];
00881                 armJointStateMessages[armIndex].position[youBotArmDoF + 1] = rightGipperFingerPosition;
00882             }
00883             catch (std::exception& e)
00884             {
00885                 std::string errorMessage = e.what();
00886                 ROS_WARN("Cannot read gripper values: %s", errorMessage.c_str());
00887             }
00888 /*
00889             if (trajectoryActionServerEnable)
00890             {
00891                 // updating joint states in trajectory action 
00892                 youBotConfiguration.youBotArmConfigurations[armIndex].jointTrajectoryAction->jointStateCallback(armJointStateMessages[armIndex]);
00893             }
00894 */
00895         }
00896     }
00897 
00898     youbot::EthercatMaster::getInstance().AutomaticReceiveOn(true); // ensure that all joint values will be received at the same time
00899     }catch (youbot::EtherCATConnectionException& e)
00900     {
00901         ROS_WARN("%s", e.what());
00902         youBotConfiguration.hasBase = false;
00903         youBotConfiguration.hasArms = false;
00904     }
00905     catch (std::exception& e)
00906     {
00907         ROS_WARN_ONCE("%s", e.what());
00908     }
00909 
00910 }
00911 
00912 void YouBotOODLWrapper::publishOODLSensorReadings()
00913 {
00914       
00915     if (youBotConfiguration.hasBase)
00916     {
00917         youBotConfiguration.baseConfiguration.odometryBroadcaster.sendTransform(odometryTransform);
00918         youBotConfiguration.baseConfiguration.baseOdometryPublisher.publish(odometryMessage);
00919         youBotConfiguration.baseConfiguration.baseJointStatePublisher.publish(baseJointStateMessage);
00920     }
00921 
00922     if (youBotConfiguration.hasArms)
00923     {
00924         for (int armIndex = 0; armIndex < static_cast<int> (youBotConfiguration.youBotArmConfigurations.size()); armIndex++)
00925         {
00926             youBotConfiguration.youBotArmConfigurations[armIndex].armJointStatePublisher.publish(armJointStateMessages[armIndex]);
00927         }
00928     }
00929 
00930 
00931 }
00932 
00933 bool YouBotOODLWrapper::switchOffBaseMotorsCallback(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response) {
00934         ROS_INFO("Switch off the base motors");
00935         if (youBotConfiguration.hasBase) { // in case stop has been invoked
00936 
00937         youbot::JointCurrentSetpoint currentStopMovement;
00938         currentStopMovement.current = 0.0 * ampere;
00939                 try {
00940       youbot::EthercatMaster::getInstance().AutomaticSendOn(false); // ensure that all joint values will be send at the same time
00941                         youBotConfiguration.baseConfiguration.youBotBase->getBaseJoint(1).setData(currentStopMovement);
00942                         youBotConfiguration.baseConfiguration.youBotBase->getBaseJoint(2).setData(currentStopMovement);
00943                         youBotConfiguration.baseConfiguration.youBotBase->getBaseJoint(3).setData(currentStopMovement);
00944                         youBotConfiguration.baseConfiguration.youBotBase->getBaseJoint(4).setData(currentStopMovement);
00945       youbot::EthercatMaster::getInstance().AutomaticSendOn(true); // ensure that all joint values will be send at the same time
00946                 } catch (std::exception& e) {
00947                         std::string errorMessage = e.what();
00948                         ROS_WARN("Cannot switch off the base motors: %s", errorMessage.c_str());
00949                         return false;
00950                 }
00951         } else {
00952                 ROS_ERROR("No base initialized!");
00953                 return false;
00954         }
00955         areBaseMotorsSwitchedOn = false;
00956         return true;
00957 }
00958 
00959 bool YouBotOODLWrapper::switchOnBaseMotorsCallback(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response)
00960 {
00961     ROS_INFO("Switch on the base motors");
00962     if (youBotConfiguration.hasBase)
00963     { // in case stop has been invoked
00964         quantity<si::velocity> longitudinalVelocity;
00965         quantity<si::velocity> transversalVelocity;
00966         quantity<si::angular_velocity> angularVelocity;
00967 
00968         longitudinalVelocity = 0.0 * meter_per_second;
00969         transversalVelocity = 0.0 * meter_per_second;
00970         angularVelocity = 0.0 * radian_per_second;
00971 
00972         try
00973         {
00974             youBotConfiguration.baseConfiguration.youBotBase->setBaseVelocity(longitudinalVelocity, transversalVelocity, angularVelocity);
00975         }
00976         catch (std::exception& e)
00977         {
00978             std::string errorMessage = e.what();
00979             ROS_WARN("Cannot set base velocities: %s", errorMessage.c_str());
00980             return false;
00981         }
00982     }
00983     else
00984     {
00985         ROS_ERROR("No base initialized!");
00986         return false;
00987     }
00988     areBaseMotorsSwitchedOn = true;
00989     return true;
00990 }
00991 
00992 bool YouBotOODLWrapper::switchOffArmMotorsCallback(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response, int armIndex) {
00993     ROS_INFO("Switch off the arm%i motors", armIndex+1);
00994     ROS_ASSERT(0 <= armIndex && armIndex < static_cast<int>(youBotConfiguration.youBotArmConfigurations.size()));
00995 
00996     if (youBotConfiguration.hasArms && youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm != 0) { // in case stop has been invoked
00997 
00998         youbot::JointCurrentSetpoint currentStopMovement;
00999         currentStopMovement.current = 0.0 * ampere;
01000         try{
01001             youbot::EthercatMaster::getInstance().AutomaticSendOn(false); // ensure that all joint values will be send at the same time
01002             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(1).setData(currentStopMovement);
01003             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(2).setData(currentStopMovement);
01004             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(3).setData(currentStopMovement);
01005             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(4).setData(currentStopMovement);
01006             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getArmJoint(5).setData(currentStopMovement);
01007             youbot::EthercatMaster::getInstance().AutomaticSendOn(true); // ensure that all joint values will be send at the same time
01008         } catch (std::exception& e) {
01009             std::string errorMessage = e.what();
01010             ROS_WARN("Cannot switch off the arm motors: %s", errorMessage.c_str());
01011             return false;
01012         }
01013     } else {
01014         ROS_ERROR("Arm%i not initialized!", armIndex+1);
01015         return false;
01016     }
01017     areArmMotorsSwitchedOn = false;
01018     return true;
01019 }
01020 
01021 bool YouBotOODLWrapper::switchOnArmMotorsCallback(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response, int armIndex)
01022 {
01023     ROS_INFO("Switch on the arm%i motors", armIndex + 1);
01024     ROS_ASSERT(0 <= armIndex && armIndex < static_cast<int> (youBotConfiguration.youBotArmConfigurations.size()));
01025 
01026     if (youBotConfiguration.hasArms && youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm != 0)
01027     {   
01028       try
01029         {
01030             std::vector<youbot::JointSensedAngle> sensedJointAngleVector;
01031             std::vector<youbot::JointAngleSetpoint> desiredJointAngleVector;
01032             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->getJointData(sensedJointAngleVector);
01033             youbot::JointAngleSetpoint desiredJointAngle;
01034             for(unsigned int i = 0; i < sensedJointAngleVector.size(); i++){
01035               desiredJointAngle = sensedJointAngleVector[i].angle;
01036               desiredJointAngleVector.push_back(desiredJointAngle);
01037             }        
01038             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->setJointData(desiredJointAngleVector);
01039         }
01040         catch (std::exception& e)
01041         {
01042             std::string errorMessage = e.what();
01043             ROS_WARN("Cannot switch on the arm motors: %s", errorMessage.c_str());
01044             return false;
01045         }
01046     }
01047     else
01048     {
01049         ROS_ERROR("Arm%i not initialized!", armIndex + 1);
01050         return false;
01051     }
01052     areArmMotorsSwitchedOn = true;
01053     return true;
01054 }
01055 
01056 bool YouBotOODLWrapper::calibrateArmCallback(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response, int armIndex)
01057 {
01058     ROS_INFO("Calibrate the arm%i", armIndex + 1);
01059     ROS_ASSERT(0 <= armIndex && armIndex < static_cast<int> (youBotConfiguration.youBotArmConfigurations.size()));
01060 
01061     if (youBotConfiguration.hasArms && youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm != 0)
01062     {
01063 
01064         try
01065         {
01066             youBotConfiguration.youBotArmConfigurations[armIndex].youBotArm->calibrateManipulator(true);
01067         }
01068         catch (std::exception& e)
01069         {
01070             std::string errorMessage = e.what();
01071             ROS_WARN("Cannot calibrate the arm: %s", errorMessage.c_str());
01072             return false;
01073         }
01074     }
01075     else
01076     {
01077         ROS_ERROR("Arm%i not initialized!", armIndex + 1);
01078         return false;
01079     }
01080     return true;
01081 }
01082 
01083 bool YouBotOODLWrapper::reconnectCallback(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response)
01084 {
01085 
01086     this->stop();
01087 
01088     /* configuration */
01089     bool youBotHasBase;
01090     bool youBotHasArms;
01091     node.param("youBotHasBase", youBotHasBase, false);
01092     node.param("youBotHasArms", youBotHasArms, false);
01093     std::vector<std::string> armNames;
01094 
01095     // Retrieve all defined arm names from the launch file params
01096     int i = 1;
01097     std::stringstream armNameParam;
01098     armNameParam << "youBotArmName" << i; // youBotArmName1 is first checked param... then youBotArmName2, etc.
01099     while (node.hasParam(armNameParam.str())) {
01100         std::string armName;
01101         node.getParam(armNameParam.str(), armName);
01102         armNames.push_back(armName);
01103         armNameParam.str("");
01104         armNameParam << "youBotArmName" <<  (++i);
01105     }
01106 
01107     ROS_ASSERT((youBotHasBase == true) || (youBotHasArms == true)); // At least one should be true, otherwise nothing to be started.
01108     if (youBotHasBase == true)
01109     {
01110         this->initializeBase(this->youBotConfiguration.baseConfiguration.baseID);
01111     }
01112 
01113     if (youBotHasArms == true)
01114     {
01115         std::vector<std::string>::iterator armNameIter;
01116         for (armNameIter = armNames.begin(); armNameIter != armNames.end(); ++armNameIter) {
01117             this->initializeArm(*armNameIter);
01118         }
01119     }
01120     return true;
01121 }
01122 
01123 void YouBotOODLWrapper::publishArmAndBaseDiagnostics(double publish_rate_in_secs) {
01124     // only publish every X seconds
01125     if ((ros::Time::now() - lastDiagnosticPublishTime).toSec() < publish_rate_in_secs)
01126         return;
01127 
01128     lastDiagnosticPublishTime = ros::Time::now();
01129 
01130     platformStateMessage.header.stamp = ros::Time::now();
01131     diagnosticArrayMessage.header.stamp = ros::Time::now();
01132     diagnosticArrayMessage.status.clear();
01133 
01134     // diagnostics message
01135     // base status
01136     diagnosticStatusMessage.name = diagnosticNameBase;
01137     if (youBotConfiguration.hasBase) {
01138         diagnosticStatusMessage.message = "base is present";
01139         diagnosticStatusMessage.level = diagnostic_msgs::DiagnosticStatus::OK;
01140     } else {
01141         diagnosticStatusMessage.message = "base is not connected or switched off";
01142         diagnosticStatusMessage.level = diagnostic_msgs::DiagnosticStatus::ERROR;
01143     }
01144     diagnosticArrayMessage.status.push_back(diagnosticStatusMessage);
01145 
01146     // arm status
01147     diagnosticStatusMessage.name = diagnosticNameArm;
01148     if (youBotConfiguration.hasArms) {
01149         diagnosticStatusMessage.message = "arm is present";
01150         diagnosticStatusMessage.level = diagnostic_msgs::DiagnosticStatus::OK;
01151     } else {
01152         diagnosticStatusMessage.message = "arm is not connected or switched off";
01153         diagnosticStatusMessage.level = diagnostic_msgs::DiagnosticStatus::ERROR;
01154     }
01155     diagnosticArrayMessage.status.push_back(diagnosticStatusMessage);
01156 
01157 
01158     // EtherCAT status
01159     diagnosticStatusMessage.name = "platform_EtherCAT";
01160     if (youbot::EthercatMaster::getInstance().isEtherCATConnectionEstablished()) {
01161         diagnosticStatusMessage.message = "EtherCAT connnection is established";
01162         diagnosticStatusMessage.level = diagnostic_msgs::DiagnosticStatus::OK;
01163         platformStateMessage.run_stop = false;
01164     }
01165     else {
01166         diagnosticStatusMessage.message = "EtherCAT connnection lost";
01167         diagnosticStatusMessage.level = diagnostic_msgs::DiagnosticStatus::ERROR;
01168         platformStateMessage.run_stop = true;
01169     }
01170     diagnosticArrayMessage.status.push_back(diagnosticStatusMessage);        
01171 
01172 
01173     // dashboard message
01174     if (youBotConfiguration.hasBase && areBaseMotorsSwitchedOn)
01175         platformStateMessage.circuit_state[0] = pr2_msgs::PowerBoardState::STATE_ENABLED;
01176     else if (youBotConfiguration.hasBase && !areBaseMotorsSwitchedOn)
01177         platformStateMessage.circuit_state[0] = pr2_msgs::PowerBoardState::STATE_STANDBY;
01178     else
01179         platformStateMessage.circuit_state[0] = pr2_msgs::PowerBoardState::STATE_DISABLED;
01180 
01181     if (youBotConfiguration.hasArms && areArmMotorsSwitchedOn)
01182         platformStateMessage.circuit_state[1] = pr2_msgs::PowerBoardState::STATE_ENABLED;
01183     else if (youBotConfiguration.hasArms && !areArmMotorsSwitchedOn)
01184         platformStateMessage.circuit_state[1] = pr2_msgs::PowerBoardState::STATE_STANDBY;
01185     else
01186         platformStateMessage.circuit_state[1] = pr2_msgs::PowerBoardState::STATE_DISABLED;
01187 
01188 
01189     // publish established messages
01190     dashboardMessagePublisher.publish(platformStateMessage);
01191     diagnosticArrayPublisher.publish(diagnosticArrayMessage);
01192   }
01193 
01194 } // namespace youBot
01195 
01196 /* EOF */


youbot_driver_ros_interface
Author(s): Sebastian Blumenthal
autogenerated on Thu Jun 6 2019 20:43:35