joystick_manual_control.h
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2015, University of Colorado, Boulder
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the Univ of CO, Boulder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Dave Coleman <dave@dav.ee>
36  Desc: Inherit from this file to enable joystick mode switching of your robot
37 */
38 
39 #ifndef ROS_CONTROL_BOILERPLATE__JOYSTICK_MANUAL_CONTROL
40 #define ROS_CONTROL_BOILERPLATE__JOYSTICK_MANUAL_CONTROL
41 
42 // ROS
43 #include <ros/ros.h>
44 #include <sensor_msgs/Joy.h>
45 
46 // ros_control
47 #include <controller_manager_msgs/SwitchController.h>
48 #include <controller_manager_msgs/LoadController.h>
49 
51 {
53 {
54 public:
61  JoystickManualControl(const std::string& parent_name, const std::string& service_namespace)
62  : parent_name_(parent_name), using_trajectory_controller_(true)
63  {
64  switch_service_ = service_namespace + "/controller_manager/switch_controller";
65  load_service_ = service_namespace + "/controller_manager/load_controller";
66 
67  // Switch modes of controllers
68  switch_controlers_client_ = nh_.serviceClient<controller_manager_msgs::SwitchController>(switch_service_);
69  load_controlers_client_ = nh_.serviceClient<controller_manager_msgs::LoadController>(load_service_);
70 
71  // Subscribe to joystick control
72  std::size_t queue_size = 1;
73  remote_joy_ = nh_.subscribe("/joy", queue_size, &JoystickManualControl::joyCallback, this);
74 
75  ROS_INFO_STREAM_NAMED(parent_name_, "JoystickManualControl Ready.");
76  }
77 
82  virtual void joyCallback(const sensor_msgs::Joy::ConstPtr& msg) = 0;
83 
88  {
89  // Ensure services are up
90  ROS_INFO_STREAM_NAMED(parent_name_, "Waiting for serivces...");
92  ROS_ERROR_STREAM_NAMED(parent_name_, "Unable to find service " << switch_service_);
94  ROS_ERROR_STREAM_NAMED(parent_name_, "Unable to find service " << load_service_);
95 
96  for (std::size_t i = 0; i < manual_controllers_.size(); ++i)
97  {
98  ROS_INFO_STREAM_NAMED(parent_name_, "Loading controller " << manual_controllers_[i]);
99  controller_manager_msgs::LoadController service;
100  service.request.name = manual_controllers_[i];
101  std::size_t counter = 0;
102  while (!load_controlers_client_.call(service) && ros::ok())
103  {
104  if (counter > 100)
106  "Failed to load controller '" << manual_controllers_[i] << "', trying again");
107  ros::spinOnce();
108  ros::Duration(0.1).sleep();
109  counter++;
110  }
111  }
112 
113  return true;
114  }
115 
117  {
118  // Stop all controllers, soft E-Stop
119  controller_manager_msgs::SwitchController service;
120  service.request.strictness = service.request.STRICT;
121 
122  ROS_WARN_STREAM_NAMED(parent_name_, "Switching to MANUAL control");
123  for (std::size_t i = 0; i < manual_controllers_.size(); ++i)
124  {
125  service.request.start_controllers.push_back(manual_controllers_[i]);
126  }
127  for (std::size_t i = 0; i < trajectory_controllers_.size(); ++i)
128  {
129  service.request.stop_controllers.push_back(trajectory_controllers_[i]);
130  }
131 
132  // Attempt stop
133  if (!switch_controlers_client_.call(service))
134  {
135  ROS_ERROR_STREAM_NAMED(parent_name_, "Failed to switch controllers");
136  return;
137  }
138  }
139 
141  {
142  // Stop all controllers, soft E-Stop
143  controller_manager_msgs::SwitchController service;
144  service.request.strictness = service.request.STRICT;
145 
146  ROS_INFO_STREAM_NAMED(parent_name_, "Switching to TRAJECTORY control");
147  for (std::size_t i = 0; i < manual_controllers_.size(); ++i)
148  {
149  service.request.stop_controllers.push_back(manual_controllers_[i]);
150  }
151  for (std::size_t i = 0; i < trajectory_controllers_.size(); ++i)
152  {
153  service.request.start_controllers.push_back(trajectory_controllers_[i]);
154  }
155 
156  // Attempt stop
157  if (!switch_controlers_client_.call(service))
158  {
159  ROS_ERROR_STREAM_NAMED(parent_name_, "Failed to switch controllers");
160  return;
161  }
162  }
163 
164 protected:
165  // A shared node handle
167 
168  // Name of parent class, used for logging messages
169  const std::string parent_name_;
170  std::string switch_service_;
171  std::string load_service_;
172 
173  // Subscribe to joystick commands
175 
176  // Ability to switch controllers
179 
180  // Switching controller mode
182 
183  // Controller lists
184  std::vector<std::string> manual_controllers_;
185  std::vector<std::string> trajectory_controllers_;
186 
187 }; // end class
188 
189 } // namespace ros_control_boilerplate
190 
191 #endif
ServiceClient serviceClient(const std::string &service_name, bool persistent=false, const M_string &header_values=M_string())
#define ROS_ERROR_STREAM_NAMED(name, args)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
bool call(MReq &req, MRes &res)
virtual void joyCallback(const sensor_msgs::Joy::ConstPtr &msg)=0
Response to joystick control Button mapping is customized by each class that inherits from this...
#define ROS_INFO_STREAM_NAMED(name, args)
JoystickManualControl(const std::string &parent_name, const std::string &service_namespace)
Constructor.
#define ROS_WARN_STREAM_THROTTLE_NAMED(period, name, args)
ROSCPP_DECL bool ok()
bool sleep() const
ROSCPP_DECL void spinOnce()
ROSCPP_DECL bool waitForService(const std::string &service_name, int32_t timeout)
#define ROS_WARN_STREAM_NAMED(name, args)
bool loadManualControllers()
Load a secondary manual controller.


ros_control_boilerplate
Author(s): Dave Coleman
autogenerated on Mon Feb 28 2022 23:27:26