NimbRo ROS Soccer Package
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
headcontrol.h
1 // Motion control for the robot head
2 // Author: Philipp Allgeuer <pallgeuer@ais.uni-bonn.de>
3 
4 // Ensure header is only included once
5 #ifndef HEADCONTROL_H
6 #define HEADCONTROL_H
7 
8 // Includes
9 #include <robotcontrol/model/robotmodel.h>
10 #include <robotcontrol/motionmodule.h>
11 #include <head_control/LookAtTarget.h>
12 #include <head_control/HeadControlStatus.h>
13 #include <config_server/parameter.h>
14 #include <rc_utils/math_spline.h>
15 #include <visualization_msgs/Marker.h>
16 #include <plot_msgs/plot_manager.h>
17 #include <sensor_msgs/Joy.h>
18 #include <std_srvs/Empty.h>
19 
20 // Head control namespace
21 namespace headcontrol
22 {
23  //
24  // BoundarySegment struct
25  //
26  struct BoundarySegment
27  {
28  // Constructor
29  BoundarySegment() { a = b = d = 0.0; c = 1.0; tStart = 0.0; tEnd = 1.0; useX = true; }
30  BoundarySegment(double a, double b, double c, double d = 0.0, double tStart = 0.0, double tEnd = 1.0, bool useX = true) : a(a), b(b), c(c), d(d), tStart(tStart), tEnd(tEnd), useX(useX) {}
31 
32  // Validity functions
33  bool invalid() const { return (a == 0.0 && b == 0.0 && d == 0.0); }
34  static bool isInvalid(const BoundarySegment& B) { return B.invalid(); }
35 
36  // Shift function
37  void shiftBy(double margin);
38 
39  // Serialisation
40  static std::string serialiseArray(const std::vector<BoundarySegment>& array);
41  static bool deserialiseArray(const std::string& str, std::vector<BoundarySegment>& array);
42 
43  // Data members (function is a*x + b*y + c + d*x^2 >= 0)
44  double a; // Coeff of x
45  double b; // Coeff of y
46  double c; // Coeff of 1
47  double d; // Coeff of x^2
48  double tStart; // Start of parameterised range
49  double tEnd; // End of parameterised range
50  bool useX; // Flag whether the parameter is x or y (d is ignored if useX is false)
51 
52  // Constants
53  static const double minC = 0.01;
54  };
55 
56  //
57  // HeadLimiter class
58  //
59  class HeadLimiter
60  {
61  public:
62  // Constructor
63  HeadLimiter() {}
64 
65  // Virtual functions
66  virtual bool applyLimit(double& yaw, double& pitch) const { return false; } // This function should update yaw/pitch if necessary to be the closest possible that is in the allowable position space
67  };
68 
69  //
70  // SimpleLimiter class
71  //
72  class SimpleLimiter : public HeadLimiter
73  {
74  public:
75  // Constants
76  static const double minYawCmd = -1.57;
77  static const double maxYawCmd = 1.57;
78  static const double minPitchCmd = -0.5;
79  static const double maxPitchCmd = 0.5;
80 
81  // Constructor
82  SimpleLimiter() {}
83 
84  // Overrides
85  virtual bool applyLimit(double& yaw, double& pitch) const;
86  };
87 
88  //
89  // BoundaryLimiter class
90  //
91  class BoundaryLimiter : public HeadLimiter
92  {
93  public:
94  // Constructor
95  BoundaryLimiter() : m_params(NULL) {}
96  BoundaryLimiter(const std::vector<BoundarySegment>* params) : m_params(params) {}
97 
98  // Reference to boundary parameters
99  void setParams(const std::vector<BoundarySegment>* params) { m_params = params; }
100  const std::vector<BoundarySegment>* getParams() const { return m_params; }
101 
102  // Overrides
103  virtual bool applyLimit(double& yaw, double& pitch) const;
104 
105  private:
106  // Internal variables
107  const std::vector<BoundarySegment>* m_params;
108  };
109 
110  //
111  // HeadControl class
112  //
113  class HeadControl : public robotcontrol::MotionModule
114  {
115  public:
116  // Constructor
117  HeadControl();
118  virtual ~HeadControl();
119 
120  // Motion module overrides
121  virtual bool init(robotcontrol::RobotModel* model);
122  virtual bool isTriggered();
123  virtual void step();
124 
125  private:
126  // Return whether head control should be enabled
127  bool active() const { return m_headControlEnabled() && m_haveTarget && (m_model->state() != m_state_kicking) && (m_model->state() != m_state_standingUp); }
128 
129  // Reset target function
130  void resetTarget();
131 
132  // ROS topic handlers
133  void handleLookAtTarget(const head_control::LookAtTargetConstPtr& msg);
134 
135  // Node handle
136  ros::NodeHandle m_nh;
137 
138  // Publishers and subscribers
139  ros::Subscriber m_sub_lookAtTarget;
140  ros::Publisher m_pub_headControlStatus;
141 
142  // Head control status updates
143  void updateHeadControlStatus();
144  head_control::HeadControlStatus m_msgStatus;
145  bool m_lastActive;
146 
147  // Pointer to robot model
148  robotcontrol::RobotModel* m_model;
149 
150  // Robot joints
151  robotcontrol::Joint::Ptr m_headYawJoint;
152  robotcontrol::Joint::Ptr m_headPitchJoint;
153 
154  // Robotcontrol states
155  robotcontrol::RobotModel::State m_state_kicking;
156  robotcontrol::RobotModel::State m_state_standingUp;
157 
158  // Config server parameters
159  config_server::Parameter<bool> m_headControlEnabled;
160  config_server::Parameter<bool> m_yawRelax;
161  config_server::Parameter<float> m_yawMaxVel;
162  config_server::Parameter<float> m_yawMaxAcc;
163  config_server::Parameter<float> m_yawDefaultEffort;
164  config_server::Parameter<bool> m_pitchRelax;
165  config_server::Parameter<float> m_pitchMaxVel;
166  config_server::Parameter<float> m_pitchMaxAcc;
167  config_server::Parameter<float> m_pitchDefaultEffort;
168 
169  // Yaw tracking state
170  double m_yawTarget;
171  double m_yawCurX;
172  double m_yawCurV;
173  double m_yawCurEffort;
174  double m_yawEffortTarget;
175  rc_utils::TrapVelSpline m_yawSpline;
176  rc_utils::LinearSpline m_yawEffortSpline;
177 
178  // Pitch tracking state
179  double m_pitchTarget;
180  double m_pitchCurX;
181  double m_pitchCurV;
182  double m_pitchCurEffort;
183  double m_pitchEffortTarget;
184  rc_utils::TrapVelSpline m_pitchSpline;
185  rc_utils::LinearSpline m_pitchEffortSpline;
186 
187  // Joystick
188  config_server::Parameter<bool> m_enableJoystick;
189  ros::Subscriber m_sub_joystickData;
190  void handleJoystickData(const sensor_msgs::JoyConstPtr& msg);
191  bool m_joystickButton9Pressed;
192  bool m_joystickSaysEnabled;
193 
194  // Miscellaneous
195  bool m_haveTarget;
196  BoundaryLimiter m_posLimiter;
197 
198  // Typedefs
199  typedef std::pair<double, double> Point;
200 
201  // Calibration initialisation
202  void initCalibration();
203 
204  // Data recording
205  bool m_recording;
206  void recordPoint();
207  std::vector<Point> m_recordedData;
208 
209  // Calibration process
210  bool m_calibrating;
211  void subscribeClickedPoint() { m_sub_clickedPoint = m_nh.subscribe("/clicked_point", 1, &HeadControl::handleClickedPoint, this); }
212  void unsubscribeClickedPoint() { m_sub_clickedPoint.shutdown(); }
213  void handleClickedPoint(const geometry_msgs::PointStampedConstPtr& msg);
214  void handleCalibParamString();
215  BoundarySegment fitLine(const Point& p1, const Point& p2);
216  BoundarySegment fitParabola(const Point& p1, const Point& p2, const Point& p3);
217  ros::Subscriber m_sub_clickedPoint;
218  std::vector<Point> m_calibData;
219  std::vector<BoundarySegment> m_calibParams;
220  std::vector<BoundarySegment> m_curCalibParams;
221  config_server::Parameter<float> m_calibSafetyMargin;
222  config_server::Parameter<std::string> m_calibParamString;
223 
224  // Calibration services
225  ros::ServiceServer m_srv_startRecording;
226  ros::ServiceServer m_srv_stopRecording;
227  ros::ServiceServer m_srv_startCalibration;
228  ros::ServiceServer m_srv_stopCalibration;
229  ros::ServiceServer m_srv_showHeadLimits;
230  bool startRecording(std_srvs::EmptyRequest&, std_srvs::EmptyResponse&) { return startRecording(); }
231  bool stopRecording(std_srvs::EmptyRequest&, std_srvs::EmptyResponse&) { return stopRecording(); }
232  bool startCalibration(std_srvs::EmptyRequest&, std_srvs::EmptyResponse&) { return startCalibration(); }
233  bool stopCalibration(std_srvs::EmptyRequest&, std_srvs::EmptyResponse&) { return stopCalibration(); }
234  bool showHeadLimits(std_srvs::EmptyRequest&, std_srvs::EmptyResponse&) { return showHeadLimits(); }
235  bool startRecording();
236  bool stopRecording();
237  bool startCalibration();
238  bool stopCalibration();
239  bool showHeadLimits();
240  void calcCalibParams(bool shrink);
241  void plotCalibParams();
242 
243  // Calibration visualisation
244  void updatePlotCalibData();
245  config_server::Parameter<bool> m_plotCalibData;
246  visualization_msgs::Marker m_dataMarker;
247  visualization_msgs::Marker m_calibMarker;
248  ros::Publisher m_pub_dataMarker;
249  ros::Publisher m_pub_calibMarker;
250 
251  // Test functions
252  void testLimiter();
253 
254  // Plot manager
255  config_server::Parameter<bool> m_plotData;
256  plot_msgs::PlotManagerFS m_PM;
257  void configurePlotManager();
258  void callbackPlotData();
259  enum PMIDS
260  {
261  PM_ENABLED,
262  PM_HAVETARGET,
263  PM_TARGETYAW,
264  PM_TARGETYAWEFFORT,
265  PM_TARGETPITCH,
266  PM_TARGETPITCHEFFORT,
267  PM_TIMETOTARGET,
268  PM_CURYAWX,
269  PM_CURYAWV,
270  PM_CURYAWEFFORT,
271  PM_CURPITCHX,
272  PM_CURPITCHV,
273  PM_CURPITCHEFFORT,
274  PM_COUNT
275  };
276  };
277 }
278 
279 #endif
280 // EOF