ros_control
ros_control copied to clipboard
Calling switch_controller service from python requires controller being loaded
When switching controllers from the cmdline via rosservice call /controller_manager/switch_controller ...
it works out of the box. However doing the same from python code always failed silently (response was ok=True
, but controller wasn't started as confirmed via rqt controller_manager plugin). Experimenting a little bit, I noticed that I need to load the controller in advance when switching programmatically. However calling the service from cmdline and from python should be the same, shouldn't it?
This works:
#!/usr/bin/env python3
import rospy
from controller_manager_msgs.srv import SwitchController, LoadController
def call(ns, cls, **kwargs):
rospy.wait_for_service(ns)
service = rospy.ServiceProxy(ns, cls)
response = service(**kwargs)
print(response.ok)
if not response.ok:
print(response)
try:
# When calling the switch_controller service here, I need to ensure that the controller is loaded.
# When calling the service via cmdline (rosservice call /controller_manager/switch_controller ...) it works without loading!?
call("/controller_manager/load_controller", LoadController,
name="position_joint_trajectory_controller")
call("/controller_manager/switch_controller", SwitchController,
start_controllers=["position_joint_trajectory_controller"],
stop_controllers=["effort_joint_trajectory_controller"],
strictness=1, start_asap=False, timeout=0.0)
except rospy.ServiceException as e:
print("Service call failed: %s" % e)
I am planning to do this recently, will try this code. Thanks.
A small question: is it possible to write python code controlling rqt to switch controllers?
Is it possible to write python code controlling rqt to switch controllers
I don't think so. However, if you switch controllers, rqt's controller_manager plugin should reflect the new state of the controllers.