rov_mb_sm_controller.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # Copyright (c) 2016-2019 The UUV Simulator Authors.
3 # All rights reserved.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 from __future__ import print_function
17 import rospy
18 import numpy as np
19 from uuv_control_interfaces import DPControllerBase
20 from uuv_control_msgs.srv import *
21 from uuv_control_interfaces.vehicle import cross_product_operator
22 
23 class ROV_MB_SMController(DPControllerBase):
24  _LABEL = 'Model-based Sliding Mode Controller'
25 
26  def __init__(self):
27  DPControllerBase.__init__(self, True)
28  self._logger.info('Initializing: ' + self._LABEL)
29 
30  # Lambda - Slope of the Sliding Surface
31  self._lambda = np.zeros(6)
32  # Rho Constant - Vector of positive terms for assuring sliding surface reaching condition
33  self._rho_constant = np.zeros(6)
34  # k - PD gain (P term = k * lambda , D term = k)
35  self._k = np.zeros(6)
36  # c - slope of arctan (the greater, the more similar with the sign function)
37  self._c = np.zeros(6)
38  # Adapt slope - Adaptation gain for the estimation of uncertainties
39  # and disturbances upper boundaries
40  # adapt_slope = [proportional to surface distance, prop. to square
41  # of pose errors, prop. to square of velocity errors]
42  self._adapt_slope = np.zeros(3)
43  # Rho_0 - rho_adapt treshold for drift prevention
44  self._rho_0 = np.zeros(6)
45  # Drift prevent - Drift prevention slope
46  self._drift_prevent = 0
47 
48  if rospy.has_param('~lambda'):
49  coefs = rospy.get_param('~lambda')
50  if len(coefs) == 6:
51  self._lambda = np.array(coefs)
52  else:
53  raise rospy.ROSException('lambda coefficients: 6 coefficients '
54  'needed')
55  print('lambda=', self._lambda)
56 
57  if rospy.has_param('~rho_constant'):
58  coefs = rospy.get_param('~rho_constant')
59  if len(coefs) == 6:
60  self._rho_constant = np.array(coefs)
61  else:
62  raise rospy.ROSException('rho_constant coefficients: 6 coefficients '
63  'needed')
64  print('rho_constant=', self._rho_constant)
65 
66  if rospy.has_param('~k'):
67  coefs = rospy.get_param('~k')
68  if len(coefs) == 6:
69  self._k = np.array(coefs)
70  else:
71  raise rospy.ROSException('k coefficients: 6 coefficients '
72  'needed')
73  print('k=', self._k)
74 
75  if rospy.has_param('~c'):
76  coefs = rospy.get_param('~c')
77  if len(coefs) == 6:
78  self._c = np.array(coefs)
79  else:
80  raise rospy.ROSException('c coefficients: 6 coefficients '
81  'needed')
82  print('c=', self._c)
83 
84  if rospy.has_param('~adapt_slope'):
85  coefs = rospy.get_param('~adapt_slope')
86  if len(coefs) == 3:
87  self._adapt_slope = np.array(coefs)
88  else:
89  raise rospy.ROSException('adapt_slope coefficients: 6 coefficients '
90  'needed')
91  print('adapt_slope=', self._adapt_slope)
92 
93  if rospy.has_param('~rho_0'):
94  coefs = rospy.get_param('~rho_0')
95  if len(coefs) == 6:
96  self._rho_0 = np.array(coefs)
97  else:
98  raise rospy.ROSException('rho_0 coefficients: 6 coefficients '
99  'needed')
100  print('rho_0=', self._rho_0)
101 
102  if rospy.has_param('~drift_prevent'):
103  scalar = rospy.get_param('~drift_prevent')
104  if not isinstance(scalar, list):
105  self._drift_prevent = scalar
106  else:
107  raise rospy.ROSException('drift_prevent needs to be a scalar value')
108 
109  print('drift_prevent=', self._drift_prevent)
110 
111  # Enable(1) / disable(0) integral term in the sliding surface
112  if rospy.has_param('~enable_integral_term'):
113  self._sliding_int = rospy.get_param('~enable_integral_term')
114  else:
115  self._sliding_int = 0
116 
117  # Enable(1) / disable(0) adaptive uncertainty upper boundaries for
118  # robust control
119  if rospy.has_param('~adaptive_bounds'):
120  self._adaptive_bounds = rospy.get_param('~adaptive_bounds')
121  else:
122  self._adaptive_bounds = 1
123 
124  # Enable(1) / disable(0) constant uncertainty upper boundaries for
125  # robust control
126  if rospy.has_param('~constant_bound'):
127  self._constant_bound = rospy.get_param('~constant_bound')
128  else:
129  self._constant_bound = 1
130 
131  # Enable(1) / disable(0) equivalent control term
132  if rospy.has_param('~ctrl_eq'):
133  self._ctrl_eq = rospy.get_param('~ctrl_eq')
134  else:
135  self._ctrl_eq = 1
136 
137  # Enable(1) / disable(0) linear control term
138  if rospy.has_param('~ctrl_lin'):
139  self._ctrl_lin = rospy.get_param('~ctrl_lin')
140  else:
141  self._ctrl_lin = 1
142 
143  # Enable(1) / disable(0) robust control term
144  if rospy.has_param('~ctrl_robust'):
145  self._ctrl_robust = rospy.get_param('~ctrl_robust')
146  else:
147  self._ctrl_robust = 1
148  # Integrator component
149  self._int = np.zeros(6)
150  # Error for the vehicle pose
151  self._error_pose = np.zeros(6)
152  # Sliding Surface
153  self._s_b = np.zeros(6)
154  # Time derivative of the rotation matrix
155  self._rotBtoI_dot = np.zeros(shape=(3, 3), dtype=float)
156  # Linear acceleration estimation
157  self._accel_linear_estimate_b = np.zeros(3)
158  # Angular acceleration estimation
159  self._accel_angular_estimate_b = np.zeros(3)
160  # Acceleration estimation
161  self._accel_estimate_b = np.zeros(6)
162  # adaptive term of uncertainties upper bound estimation
163  self._rho_adapt = np.zeros(6)
164  # Upper bound for model uncertainties and disturbances
165  self._rho_total = np.zeros(6)
166  # Equivalent control
167  self._f_eq = np.zeros(6)
168  # Linear term of controller
169  self._f_lin = np.zeros(6)
170  # Robust control
171  self._f_robust = np.zeros(6)
172  # Total control
173  self._tau = np.zeros(6)
174 
175  self._services['set_mb_sm_controller_params'] = rospy.Service(
176  'set_mb_sm_controller_params',
177  SetMBSMControllerParams,
179 
180  self._services['get_mb_sm_controller_params'] = rospy.Service(
181  'get_mb_sm_controller_params',
182  GetMBSMControllerParams,
184  self._is_init = True
185  self._logger.info(self._LABEL + ' ready')
186 
187  def _reset_controller(self):
188  super(ROV_MB_SMController, self)._reset_controller()
189  self._sliding_int = 0
190  self._adaptive_bounds = 0
191  self._constant_bound = 0
192  self._ctrl_eq = 0
193  self._ctrl_lin = 0
194  self._ctrl_robust = 0
195  self._prev_t = 0
196  self._int = np.zeros(6)
197  self._error_pose = np.zeros(6)
198  self._s_b = np.zeros(6)
199  self._rotBtoI_dot = np.zeros(shape=(3, 3), dtype=float)
200  self._accel_linear_estimate_b = np.zeros(3)
201  self._accel_angular_estimate_b = np.zeros(3)
202  self._accel_estimate_b = np.zeros(6)
203  self._rho_adapt = np.zeros(6)
204  self._rho_total = np.zeros(6)
205  self._f_eq = np.zeros(6)
206  self._f_lin = np.zeros(6)
207  self._f_robust = np.zeros(6)
208  self._tau = np.zeros(6)
209 
211  return SetMBSMControllerParamsResponse(True)
212 
214  return GetMBSMControllerParamsResponse(
215  self._lambda.tolist(),
216  self._rho_constant.tolist(),
217  self._k.tolist(),
218  self._c.tolist(),
219  self._adapt_slope.tolist(),
220  self._rho_0.tolist(),
221  self._drift_prevent)
222 
223  def update_controller(self):
224  if not self._is_init:
225  return False
226  t = rospy.Time.now().to_sec()
227 
228  dt = t - self._prev_t
229  if self._prev_t < 0.0:
230  dt = 0.0
231 
232  # Update integrator
233  self._int += 0.5 * (self.error_pose_euler - self._error_pose) * self._dt
234  # Store current pose error
235  self._error_pose = self.error_pose_euler
236 
237  # Get trajectory errors (reference - actual)
238  e_p_linear_b = self._errors['pos']
239  e_v_linear_b = self._errors['vel'][0:3]
240 
241  e_p_angular_b = self.error_orientation_rpy
242  e_v_angular_b = self._errors['vel'][3:6]
243 
244  e_p_b = np.hstack((e_p_linear_b, e_p_angular_b))
245  e_v_b = np.hstack((e_v_linear_b, e_v_angular_b))
246 
247  # Compute sliding surface s wrt body frame
248  self._s_b = -e_v_b - np.multiply(self._lambda, e_p_b) \
249  - self._sliding_int * np.multiply(np.square(self._lambda)/4, self._int)
250 
251  # Acceleration estimate
252  self._rotBtoI_dot = np.dot(cross_product_operator(self._vehicle_model._vel[3:6]), self._vehicle_model.rotBtoI)
253  self._accel_linear_estimate_b = np.dot(
254  self._vehicle_model.rotItoB, (self._reference['acc'][0:3] - \
255  np.dot(self._rotBtoI_dot, self._vehicle_model._vel[0:3]))) + \
256  np.multiply(self._lambda[0:3], e_v_linear_b) + \
257  self._sliding_int * np.multiply(np.square(self._lambda[0:3]) / 4, e_p_linear_b)
258  self._accel_angular_estimate_b = np.dot(self._vehicle_model.rotItoB, (self._reference['acc'][3:6] -
259  np.dot(self._rotBtoI_dot, self._vehicle_model._vel[3:6]))) + \
260  np.multiply(self._lambda[3:6], e_v_angular_b) + \
261  self._sliding_int * np.multiply(np.square(self._lambda[3:6]) / 4,
262  e_p_angular_b)
264 
265  # Equivalent control
266  acc = self._vehicle_model.to_SNAME(self._accel_estimate_b)
267  self._f_eq = self._vehicle_model.compute_force(acc, use_sname=False)
268 
269  # Linear control
270  self._f_lin = - np.multiply(self._k, self._s_b)
271 
272  # Uncertainties / disturbances upper boundaries for robust control
273  self._rho_total = self._adaptive_bounds * self._rho_adapt + self._constant_bound * self._rho_constant
274 
275  # Adaptation law
276  self._rho_adapt = self._rho_adapt + \
277  (self._adapt_slope[0] * np.abs(self._s_b) +
278  (self._adapt_slope[1] * np.abs(self._s_b) * np.abs(e_p_b) * np.abs(e_p_b)) +
279  (self._adapt_slope[2] * np.abs(self._s_b) * np.abs(e_v_b) * np.abs(e_v_b)) +
280  self._drift_prevent * (self._rho_0 - self._rho_adapt)) * dt
281 
282  # Robust control
283  self._f_robust = - np.multiply(self._rho_total, (2 / np.pi) * np.arctan(np.multiply(self._c, self._s_b)))
284 
285  # Compute required forces and torques wrt body frame
286  self._tau = self._ctrl_eq * self._f_eq + self._ctrl_lin * self._f_lin + self._ctrl_robust * self._f_robust
287 
288  self.publish_control_wrench(self._tau)
289 
290  self._prev_t = t
291 
292 if __name__ == '__main__':
293  print('Starting Model-based Sliding Mode Controller')
294  rospy.init_node('rov_mb_sm_controller')
295 
296  try:
298  rospy.spin()
299  except rospy.ROSInterruptException:
300  print('caught exception')
301  print('exiting')


uuv_trajectory_control
Author(s):
autogenerated on Thu Jun 18 2020 03:28:42