diff --git a/controller_manager/CMakeLists.txt b/controller_manager/CMakeLists.txt
index a80c97b2f..d44f110f6 100644
--- a/controller_manager/CMakeLists.txt
+++ b/controller_manager/CMakeLists.txt
@@ -26,6 +26,17 @@ if(catkin_EXPORTED_TARGETS)
add_dependencies(${PROJECT_NAME} ${catkin_EXPORTED_TARGETS})
endif()
+if(CATKIN_ENABLE_TESTING)
+
+ find_package(rostest REQUIRED)
+ add_rostest_gtest(controller_manager_hwi_switch_test
+ test/hwi_switch_test.test
+ test/hwi_switch_test.cpp
+ )
+ target_link_libraries(controller_manager_hwi_switch_test ${PROJECT_NAME} ${catkin_LIBRARIES})
+
+endif()
+
# Install
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION})
diff --git a/controller_manager/package.xml b/controller_manager/package.xml
index 0fe09f374..c7dee40b5 100644
--- a/controller_manager/package.xml
+++ b/controller_manager/package.xml
@@ -11,6 +11,7 @@
https://github.com/ros-controls/ros_control
Wim Meeussen
+ Mathias Lüdtke
catkin
diff --git a/controller_manager/src/controller_manager.cpp b/controller_manager/src/controller_manager.cpp
index dcdb8c0c0..20439c064 100644
--- a/controller_manager/src/controller_manager.cpp
+++ b/controller_manager/src/controller_manager.cpp
@@ -408,7 +408,8 @@ bool ControllerManager::switchController(const std::vector& start_c
ROS_DEBUG("Start request vector has size %i", (int)start_request_.size());
// Do the resource management checking
- std::list info_list;
+ std::list info_list, start_list, stop_list;
+
std::vector &controllers = controllers_lists_[current_controllers_list_];
for (size_t i = 0; i < controllers.size(); ++i)
{
@@ -422,13 +423,44 @@ bool ControllerManager::switchController(const std::vector& start_c
in_start_list = in_start_list || (start_request_[j] == controllers[i].c.get());
bool add_to_list = controllers[i].c->isRunning();
+ hardware_interface::ControllerInfo &info = controllers[i].info;
+
+ if(!add_to_list && in_stop_list){ // check for double stop
+ if(strictness == controller_manager_msgs::SwitchController::Request::STRICT){
+ ROS_ERROR_STREAM("Could not stop controller '" << info.name << "' since it is not running");
+ stop_request_.clear();
+ start_request_.clear();
+ return false;
+ } else {
+ in_stop_list = false;
+ }
+ }
+
+ if(add_to_list && !in_stop_list && in_start_list){ // check for doubled start
+ if(strictness == controller_manager_msgs::SwitchController::Request::STRICT){
+ ROS_ERROR_STREAM("Controller '" << info.name << "' is already running");
+ stop_request_.clear();
+ start_request_.clear();
+ return false;
+ } else {
+ in_start_list = false;
+ }
+ }
+
+ if(add_to_list && in_stop_list && !in_start_list){ // running and real stop
+ stop_list.push_back(info);
+ }
+ else if(!in_stop_list && in_start_list){ // start, but no restart
+ start_list.push_back(info);
+ }
+
if (in_stop_list)
add_to_list = false;
if (in_start_list)
add_to_list = true;
if (add_to_list)
- info_list.push_back(controllers[i].info);
+ info_list.push_back(info);
}
bool in_conflict = robot_hw_->checkForConflict(info_list);
@@ -440,6 +472,16 @@ bool ControllerManager::switchController(const std::vector& start_c
return false;
}
+ if (!robot_hw_->canSwitch(start_list, stop_list))
+ {
+ ROS_ERROR("Could not switch controllers. The hardware interface combination for the requested controllers is unfeasible.");
+ stop_request_.clear();
+ start_request_.clear();
+ return false;
+ }
+
+ robot_hw_->doSwitch(start_list, stop_list);
+
// start the atomic controller switching
switch_strictness_ = strictness;
please_switch_ = true;
diff --git a/controller_manager/test/hwi_switch_test.cpp b/controller_manager/test/hwi_switch_test.cpp
new file mode 100644
index 000000000..e1b71e9a1
--- /dev/null
+++ b/controller_manager/test/hwi_switch_test.cpp
@@ -0,0 +1,452 @@
+///////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2015, Fraunhofer IPA
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of Fraunhofer IPA nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//////////////////////////////////////////////////////////////////////////////
+
+/// \author Mathias Lüdtke
+
+#include
+
+#include