rov_sf_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 import rospy
17 import numpy as np
18 from uuv_control_interfaces import DPControllerBase
19 
20 
21 class ROV_SFController(DPControllerBase):
22  """
23  Singularity-free tracking controller
24 
25  Reference
26  ---------
27 
28  [1] O.-E. Fjellstad and T. I. Fossen, Singularity-free tracking of unmanned
29  underwater vehicles in 6 DOF, Proceedings of 1994 33rd IEEE Conference
30  on Decision and Control
31  [2] G. Antonelli, "Underwater Robots," Springer Tracts in Advanced Robotics,
32  2003
33  """
34 
35  _LABEL = 'Singularity-free tracking controller'
36 
37  def __init__(self):
38  DPControllerBase.__init__(self, True)
39  self._tau = np.zeros(6)
40  self._logger.info('Initializing: ' + self._LABEL)
41 
42  self._Kd = np.zeros(shape=(6, 6))
43 
44  if rospy.has_param('~Kd'):
45  coefs = rospy.get_param('~Kd')
46  if len(coefs) == 6:
47  self._Kd = np.diag(coefs)
48  else:
49  raise rospy.ROSException('Kd coefficients: 6 coefficients '
50  'needed')
51 
52  self._logger.info('Kd=\n' + str(self._Kd))
53 
54  # Build delta matrix
55  self._delta = np.zeros(shape=(6, 6))
56 
57  l = rospy.get_param('~lambda', [0.0])
58 
59  if len(l) == 1:
60  self._delta[0:3, 0:3] = l[0] * np.eye(3)
61  elif len(l) == 3:
62  self._delta[0:3, 0:3] = np.diag(l)
63  else:
64  raise rospy.ROSException(
65  'lambda: either a scalar or a 3 element vector must be provided')
66 
67  c = rospy.get_param('~c', [0.0])
68 
69  if len(c) == 1:
70  self._delta[3:6, 3:6] = c[0] * np.eye(3)
71  elif len(c) == 3:
72  self._delta[3:6, 3:6] = np.diag(c)
73  else:
74  raise rospy.ROSException(
75  'c: either a scalar or a 3 element vector must be provided')
76 
77  self._logger.info('delta=\n' + str(self._delta))
78 
79  self._prev_t = None
80  self._prev_vel_r = np.zeros(6)
81 
82  self._is_init = True
83  self._logger.info(self._LABEL + ' ready')
84 
85  def update_controller(self):
86  if not self._is_init:
87  return False
88 
89  t = rospy.Time.now().to_sec()
90 
91  # Compute the generalized pose error vector using the quaternion
92  # orientation error
93  error = np.hstack((self._errors['pos'], self.error_orientation_quat))
94 
95  # Compute the virtual velocity signal
96  vel_r = self._reference['vel'] + np.dot(self._delta, error)
97 
98  if self._prev_t is None:
99  self._prev_t = t
100  self._prev_vel_r = vel_r
101  return False
102 
103  dt = t - self._prev_t
104 
105  if dt <= 0:
106  return False
107 
108  # Compute virtual velocity error
109  vel = self._vehicle_model.to_SNAME(self._vehicle_model.vel)
110  # s = vel - self._vehicle_model.to_SNAME(vel_r)
111  s = self._errors['vel'] + np.dot(self._delta, error)
112 
113  # Compute numerical derivative for virtual velocity signal
114  d_vel_r = (vel_r - self._prev_vel_r) / dt
115 
116  sname_vel_r = self._vehicle_model.to_SNAME(vel_r)
117  sname_d_vel_r = self._vehicle_model.to_SNAME(d_vel_r)
118  self._vehicle_model._update_damping(vel)
119  self._vehicle_model._update_coriolis(vel)
120  self._vehicle_model._update_restoring(use_sname=True)
121 
122  self._tau = np.dot(self._vehicle_model.Mtotal, sname_d_vel_r) + \
123  np.dot(self._vehicle_model.Ctotal, sname_vel_r) + \
124  np.dot(self._vehicle_model.Dtotal, sname_vel_r) + \
125  self._vehicle_model.restoring_forces
126 
127  # Update PID control action
128  self.publish_control_wrench(
129  self._vehicle_model.from_SNAME(self._tau) + np.dot(self._Kd, s))
130 
131  self._prev_t = t
132  self._prev_vel_r = vel_r
133  return True
134 
135 
136 if __name__ == '__main__':
137  rospy.init_node('rov_sf_controller')
138 
139  try:
141  rospy.spin()
142  except rospy.ROSInterruptException:
143  print('caught exception')
144  print('exiting')


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