00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00027
00029
00030 #include <gtest/gtest.h>
00031
00032 #include <map>
00033 #include <set>
00034 #include <string>
00035 #include <algorithm>
00036 #include <iterator>
00037
00038 #include <controller_manager/controller_manager.h>
00039 #include <hardware_interface/robot_hw.h>
00040 #include <hardware_interface/joint_command_interface.h>
00041
00042 namespace hardware_interface {
00043 bool operator<(hardware_interface::ControllerInfo const& i1, hardware_interface::ControllerInfo const& i2)
00044 {
00045 return i1.name < i2.name;
00046 }
00047 }
00048 template<typename T> T intersect(const T& v1, const T &v2)
00049 {
00050
00051 std::vector<typename T::value_type> sorted1(v1.begin(), v1.end()), sorted2(v2.begin(), v2.end());
00052 T res;
00053
00054 std::sort(sorted1.begin(), sorted1.end());
00055 std::sort(sorted2.begin(), sorted2.end());
00056
00057 std::set_intersection(sorted1.begin(), sorted1.end(), sorted2.begin(), sorted2.end(), std::back_inserter(res));
00058 return res;
00059 }
00060
00061 class SwitchBot : public hardware_interface::RobotHW
00062 {
00063 hardware_interface::JointStateInterface jsi_;
00064 hardware_interface::PositionJointInterface pji_;
00065 hardware_interface::VelocityJointInterface vji_;
00066 hardware_interface::EffortJointInterface eji_;
00067
00068 class Joint
00069 {
00070 double dummy_;
00071 std::set<std::string> interfaces_;
00072 std::string current_;
00073 hardware_interface::JointStateHandle jsh_;
00074 public:
00075 Joint(const std::string &n, hardware_interface::JointStateInterface &iface): jsh_(n, &dummy_, &dummy_, &dummy_)
00076 {
00077 iface.registerHandle(jsh_);
00078 }
00079
00080 template<typename Interface> void registerHandle(Interface &iface, bool can_switch)
00081 {
00082 if(can_switch) interfaces_.insert(hardware_interface::internal::demangledTypeName<Interface>() );
00083 iface.registerHandle(typename Interface::ResourceHandleType(jsh_, &dummy_));
00084 }
00085 bool canSwitch(const std::string &n) const
00086 {
00087 if(interfaces_.find(n) == interfaces_.end()) return false;
00088 return n >= current_;
00089 }
00090 void doSwitch(const std::string &n)
00091 {
00092 current_ = n;
00093 }
00094 };
00095
00096 typedef boost::shared_ptr<Joint> JointSharedPtr;
00097
00098 std::map<std::string, JointSharedPtr> joints_;
00099
00100 JointSharedPtr makeJoint(const std::string & name)
00101 {
00102 JointSharedPtr j(new Joint(name, jsi_));
00103 joints_.insert(std::make_pair(name, j));
00104 return j;
00105 }
00106
00107 std::vector<std::string> started_;
00108 std::vector<std::string> stopped_;
00109 public:
00110 SwitchBot()
00111 {
00112 JointSharedPtr j;
00113
00114 j = makeJoint("j_pv");
00115
00116 j->registerHandle(pji_, true);
00117 j->registerHandle(vji_, true);
00118 j->registerHandle(eji_, false);
00119
00120 j = makeJoint("j_pe");
00121 j->registerHandle(pji_, true);
00122 j->registerHandle(vji_, false);
00123 j->registerHandle(eji_, true);
00124
00125 j = makeJoint("j_ve");
00126 j->registerHandle(pji_, false);
00127 j->registerHandle(vji_, true);
00128 j->registerHandle(eji_, true);
00129
00130 registerInterface(&pji_);
00131 registerInterface(&vji_);
00132 registerInterface(&eji_);
00133
00134 }
00135
00136 virtual bool canSwitch(const std::list<hardware_interface::ControllerInfo> &start_list, const std::list<hardware_interface::ControllerInfo> &stop_list) const
00137 {
00138
00139 if(!RobotHW::canSwitch(start_list, stop_list))
00140 {
00141 ROS_ERROR("Something is wrong with RobotHW");
00142 return false;
00143 }
00144
00145 if(!intersect(start_list, stop_list).empty())
00146 {
00147 ROS_ERROR_STREAM("start_list and stop_list intersect");
00148 return false;
00149 }
00150
00151 bool j_pe_e = false;
00152 bool j_ve_v = false;
00153
00154 for(std::list<hardware_interface::ControllerInfo>::const_iterator it = start_list.begin(); it != start_list.end(); ++it)
00155 {
00156 for (std::set<std::string>::const_iterator res_it = it->resources.begin(); res_it != it->resources.end(); ++res_it)
00157 {
00158
00159
00160 if(it->hardware_interface == "hardware_interface::EffortJointInterface" && *res_it == "j_pe") j_pe_e = true;
00161 else if(it->hardware_interface == "hardware_interface::VelocityJointInterface" && *res_it == "j_ve") j_ve_v = true;
00162
00163
00164 try
00165 {
00166 if(!joints_.at(*res_it)->canSwitch(it->hardware_interface))
00167 {
00168 ROS_ERROR_STREAM("Cannot switch " << *res_it << " to " << it->hardware_interface);
00169 return false;
00170 }
00171 }
00172 catch(...)
00173 {
00174 ROS_FATAL("This should never happen!");
00175 return false;
00176 }
00177 }
00178 }
00179 return !(j_pe_e && j_ve_v);
00180 }
00181 virtual void doSwitch(const std::list<hardware_interface::ControllerInfo> &start_list, const std::list<hardware_interface::ControllerInfo> &stop_list)
00182 {
00183 RobotHW::doSwitch(start_list, stop_list);
00184
00185 std::map<std::string, std::string> switches;
00186 for(std::list<hardware_interface::ControllerInfo>::const_iterator it = stop_list.begin(); it != stop_list.end(); ++it)
00187 {
00188 started_.erase(std::remove(started_.begin(), started_.end(), it->name), started_.end());
00189 stopped_.push_back(it->name);
00190 for (std::set<std::string>::const_iterator res_it = it->resources.begin(); res_it != it->resources.end(); ++res_it)
00191 {
00192 switches[*res_it] = "";
00193 }
00194 }
00195 for(std::list<hardware_interface::ControllerInfo>::const_iterator it = start_list.begin(); it != start_list.end(); ++it)
00196 {
00197
00198 stopped_.erase(std::remove(stopped_.begin(), stopped_.end(), it->name), stopped_.end());
00199 started_.push_back(it->name);
00200 for (std::set<std::string>::const_iterator res_it = it->resources.begin(); res_it != it->resources.end(); ++res_it)
00201 {
00202 switches[*res_it] = it->hardware_interface;
00203 }
00204 }
00205 for(std::map<std::string, std::string>::iterator it = switches.begin(); it != switches.end(); ++it)
00206 {
00207 joints_[it->first]->doSwitch(it->second);
00208 }
00209 }
00210 bool checkUnqiue() const
00211 {
00212 return intersect(started_, stopped_).empty();
00213 }
00214 bool checkNotRunning() const
00215 {
00216 return started_.empty();
00217 }
00218 };
00219
00220
00221 class DummyControllerLoader: public controller_manager::ControllerLoaderInterface
00222 {
00223 class DummyController : public controller_interface::ControllerBase
00224 {
00225 const std::string type_name;
00226 public:
00227 DummyController(const std::string &name) : type_name(name) {}
00228 virtual void update(const ros::Time& , const ros::Duration& ) {}
00229 virtual bool initRequest(hardware_interface::RobotHW* ,
00230 ros::NodeHandle& ,
00231 ros::NodeHandle &controller_nh,
00232 std::set<std::string>& claimed_resources)
00233 {
00234 std::vector<std::string> joints;
00235 if(!controller_nh.getParam("joints", joints))
00236 {
00237 ROS_ERROR("Could not parse joint names");
00238 return false;
00239 }
00240 claimed_resources.insert(joints.begin(), joints.end());
00241 state_ = INITIALIZED;
00242 return true;
00243 }
00244 virtual std::string getHardwareInterfaceType() const
00245 {
00246 return type_name;
00247 }
00248 };
00249
00250 std::map<std::string, std::string> classes;
00251 void add(const std::string type)
00252 {
00253 classes.insert(std::make_pair("Dummy" + type + "Controller", "hardware_interface::" + type));
00254 }
00255 public:
00256 DummyControllerLoader() : ControllerLoaderInterface("controller_interface::ControllerBase")
00257 {
00258 add("EffortJointInterface");
00259 add("PositionJointInterface");
00260 add("VelocityJointInterface");
00261 }
00262 virtual controller_interface::ControllerBaseSharedPtr createInstance(const std::string& lookup_name)
00263 {
00264 return controller_interface::ControllerBaseSharedPtr(new DummyController(classes.at(lookup_name)));
00265 }
00266 virtual std::vector<std::string> getDeclaredClasses()
00267 {
00268 std::vector<std::string> v;
00269 for(std::map<std::string, std::string>::iterator it = classes.begin(); it != classes.end(); ++it)
00270 {
00271 v.push_back(it->first);
00272 }
00273 return v;
00274 }
00275 virtual void reload() {}
00276 };
00277
00278 void update(controller_manager::ControllerManager &cm, const ros::TimerEvent& e)
00279 {
00280 cm.update(e.current_real, e.current_real - e.last_real);
00281 }
00282
00283 class GuardROS
00284 {
00285 public:
00286 ~GuardROS()
00287 {
00288 ros::shutdown();
00289 ros::waitForShutdown();
00290 }
00291 };
00292
00293 TEST(SwitchInterfacesTest, SwitchInterfaces)
00294 {
00295 GuardROS guard;
00296
00297 SwitchBot bot;
00298 ros::NodeHandle nh;
00299
00300 controller_manager::ControllerManager cm(&bot);
00301
00302 cm.registerControllerLoader(boost::make_shared<DummyControllerLoader>());
00303
00304 ros::Timer timer = nh.createTimer(ros::Duration(0.01), boost::bind(update, boost::ref(cm), _1));
00305
00306 ASSERT_TRUE(cm.loadController("group_pos"));
00307 ASSERT_TRUE(cm.loadController("another_group_pos"));
00308 ASSERT_TRUE(cm.loadController("group_vel"));
00309 ASSERT_TRUE(cm.loadController("group_eff"));
00310 ASSERT_TRUE(cm.loadController("single_pos"));
00311 ASSERT_TRUE(cm.loadController("single_eff"));
00312 ASSERT_TRUE(cm.loadController("invalid_group_pos"));
00313 ASSERT_FALSE(cm.loadController("totally_random_name"));
00314
00315 {
00316 std::vector<std::string> start, stop;
00317 start.push_back("invalid_group_pos");
00318 ASSERT_FALSE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00319 }
00320 {
00321 std::vector<std::string> start, stop;
00322 start.push_back("group_pos");
00323 start.push_back("group_vel");
00324 ASSERT_FALSE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00325 }
00326 {
00327 std::vector<std::string> start, stop;
00328 start.push_back("group_pos");
00329 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00330 ASSERT_TRUE(cm.switchController(stop, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00331 }
00332 {
00333 std::vector<std::string> start, stop, next_start;
00334 start.push_back("group_pos");
00335 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00336
00337 next_start.push_back("group_pos");
00338 ASSERT_TRUE(cm.switchController(next_start, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00339
00340 ASSERT_TRUE(cm.switchController(stop, next_start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00341 }
00342 {
00343 std::vector<std::string> start, stop, next_start;
00344 start.push_back("group_pos");
00345 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00346
00347 next_start.push_back("another_group_pos");
00348 ASSERT_TRUE(cm.switchController(next_start, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00349
00350 ASSERT_TRUE(cm.switchController(stop, next_start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00351 }
00352 {
00353 std::vector<std::string> start, stop;
00354 start.push_back("group_vel");
00355 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00356 ASSERT_TRUE(cm.switchController(stop, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00357 }
00358 {
00359 std::vector<std::string> start, stop;
00360 start.push_back("group_eff");
00361 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00362 ASSERT_TRUE(cm.switchController(stop, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00363 }
00364
00365 {
00366 std::vector<std::string> start, stop, next_start;
00367 start.push_back("group_eff");
00368 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00369
00370 next_start.push_back("group_vel");
00371 ASSERT_TRUE(cm.switchController(next_start, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00372
00373 ASSERT_FALSE(cm.switchController(start, next_start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00374
00375 ASSERT_TRUE(cm.switchController(stop, next_start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00376 }
00377
00378 {
00379 std::vector<std::string> start, stop;
00380 start.push_back("single_pos");
00381 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00382 ASSERT_TRUE(cm.switchController(stop, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00383 }
00384 {
00385 std::vector<std::string> start, stop;
00386 start.push_back("single_pos");
00387 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00388 ASSERT_TRUE(cm.switchController(stop, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00389 }
00390 {
00391 std::vector<std::string> start, stop;
00392 start.push_back("single_pos");
00393 start.push_back("group_eff");
00394 ASSERT_FALSE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00395 }
00396 {
00397 std::vector<std::string> start, stop;
00398 start.push_back("single_eff");
00399 start.push_back("group_vel");
00400 ASSERT_FALSE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00401 }
00402 {
00403 std::vector<std::string> start, stop;
00404 start.push_back("single_pos");
00405 start.push_back("group_vel");
00406 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00407 ASSERT_TRUE(cm.switchController(stop, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00408 }
00409 {
00410 std::vector<std::string> start, stop;
00411 start.push_back("single_pos");
00412 start.push_back("group_vel");
00413 start.push_back("totally_random_name");
00414 ASSERT_FALSE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00415 ASSERT_FALSE(cm.switchController(stop, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00416
00417 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::BEST_EFFORT));
00418 ASSERT_TRUE(cm.switchController(stop, start, controller_manager_msgs::SwitchControllerRequest::BEST_EFFORT));
00419 }
00420 {
00421 std::vector<std::string> start, stop;
00422 start.push_back("single_pos");
00423 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00424
00425 ASSERT_TRUE(cm.switchController(start, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00426 ASSERT_TRUE(bot.checkUnqiue());
00427
00428 ASSERT_TRUE(cm.switchController(stop, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00429 }
00430 {
00431 std::vector<std::string> start, stop;
00432 stop.push_back("single_pos");
00433 ASSERT_FALSE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00434 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::BEST_EFFORT));
00435 }
00436 {
00437 std::vector<std::string> start, stop;
00438 start.push_back("single_pos");
00439 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00440 ASSERT_FALSE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::STRICT));
00441 ASSERT_TRUE(cm.switchController(start, stop, controller_manager_msgs::SwitchControllerRequest::BEST_EFFORT));
00442 ASSERT_TRUE(cm.switchController(stop, start, controller_manager_msgs::SwitchControllerRequest::STRICT));
00443 }
00444 ASSERT_TRUE(bot.checkNotRunning());
00445 }
00446
00447 int main(int argc, char **argv)
00448 {
00449 testing::InitGoogleTest(&argc, argv);
00450 ros::init(argc, argv, "controller_manager_switch_test");
00451
00452 ros::AsyncSpinner spinner(1);
00453 spinner.start();
00454 int ret = RUN_ALL_TESTS();
00455 return ret;
00456 }