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


youbot_oodl
Author(s): Sebastian Blumenthal
autogenerated on Fri Jul 26 2013 12:00:42