15 from rospy
import get_namespace
17 from copy
import deepcopy
22 from .trajectory_point
import TrajectoryPoint
23 from uuv_waypoints
import Waypoint, WaypointSet
25 quaternion_conjugate, quaternion_about_axis
27 from .path_generator
import PathGenerator
31 """Class that generates a trajectory from the interpolated path generated 32 from a set of waypoints. It uses the information given for the waypoint's 33 maximum forward speed to estimate the velocity between waypoint and 34 parametrize the interpolated curve. 35 The velocity and acceleration profiles are the generated through finite 36 discretization. These profiles are not optimized, this class is a 37 simple solution for quick trajectory generation for waypoint navigation. 41 * `full_dof` (*type:* `bool`, *default:* `False`): `True` to generate 6 DoF 43 * `use_finite_diff` (*type:* `bool`, *default:* `True`): Use finite differentiation 44 if `True`, otherwise use the motion regression algorithm 45 * `interpolation_method` (*type:* `str`, *default:* `cubic`): Name of the interpolation 46 method, options are `cubic`, `dubins`, `lipb` or `linear` 47 * `stamped_pose_only` (*type:* `bool`, *default:* `False`): Generate only position 48 and quaternion vectors, velocities and accelerations are set to zero 50 def __init__(self, full_dof=False, use_finite_diff=True,
51 interpolation_method=
'cubic',
52 stamped_pose_only=
False):
53 """Class constructor.""" 54 self.
_logger = logging.getLogger(
'wp_trajectory_generator')
55 out_hdlr = logging.StreamHandler(sys.stdout)
56 out_hdlr.setFormatter(logging.Formatter(
57 get_namespace().replace(
'/',
'').upper() +
' -- %(asctime)s | %(levelname)s | %(module)s | %(message)s'))
58 out_hdlr.setLevel(logging.INFO)
59 self._logger.addHandler(out_hdlr)
60 self._logger.setLevel(logging.INFO)
63 self._logger.info(
'Waypoint interpolators available:')
64 for gen
in PathGenerator.get_all_generators():
65 self._logger.info(
'\t - ' + gen.get_label())
109 while self._logger.handlers:
110 self._logger.handlers.pop()
114 """`bool`: Flag set to true if the interpolation has started.""" 119 """Return the closest waypoint to the current position on the path.""" 124 """`int`: Index of the closest waypoint to the current position on the 131 """`str`: Name of the interpolation method""" 136 """List of `str`: List of all interpolation method""" 137 return [gen.get_label()
for gen
in PathGenerator.get_all_generators()]
141 """`bool`: Use finite differentiation for computation of 146 @use_finite_diff.setter
148 assert type(flag) == bool
153 """`bool`: Flag to enable computation of stamped poses""" 156 @stamped_pose_only.setter
164 return self.interpolator.get_visual_markers()
169 self._logger.info(
'Interpolation method set: ' + str(method))
172 self._logger.info(
'Invalid interpolation method, keeping the current method <%s>' % self.
_interp_method)
177 self._logger.error(
'Invalid interpolation method: ' + str(method))
182 """Return true if the trajectory is generated for all 6 degrees of 188 """Return maximum trajectory time.""" 189 return self.interpolator.max_time
192 """Set a new maximum trajectory time.""" 194 self.interpolator.duration = t
195 self.interpolator.s_step = self.
_t_step / self.interpolator.duration
196 self._logger.info(
'New duration, max. relative time=%.2f s' % self.interpolator.duration)
199 self._logger.info(
'Invalid max. time, time=%.2f s' % t)
203 """Return true if the trajectory has finished.""" 207 """Reset all class attributes to allow a new trajectory to be 219 """Initialize the waypoint set.""" 221 self.interpolator.reset()
222 return self.interpolator.init_waypoints(waypoint_set, init_rot)
225 """Add waypoint to the existing waypoint set. If no waypoint set has 226 been initialized, create new waypoint set structure and add the given 228 return self.interpolator.add_waypoint(waypoint, add_to_beginning)
231 """Return waypoint set.""" 232 return self.interpolator.waypoints
235 """Update the time stamp.""" 239 if self.interpolator.start_time
is None:
240 self.interpolator.start_time = t
244 return (
True if self.
_dt > 0
else False)
247 """Return pose samples from the interpolated path.""" 248 assert step > 0,
'Step size must be positive' 249 return self.interpolator.get_samples(0.0, step)
252 """Set a custom starting time to the interpolated trajectory.""" 253 assert t >= 0,
'Starting time must be positive' 254 self.interpolator.start_time = t
255 self._logger.info(
'Setting new starting time, t=%.2f s' % t)
259 Computation of the velocity and acceleration for the target time t 260 using a sequence of points with time stamps for one dimension. This 261 is an implementation of the algorithm presented by [1]. 265 [1] Sittel, Florian, Joerg Mueller, and Wolfram Burgard. Computing 266 velocities and accelerations from a pose time sequence in 267 three-dimensional space. Technical Report 272, University of 268 Freiburg, Department of Computer Science, 2013. 282 st2x += pnt[0] * ti**2
289 A = n * (st3 * st3 - st2 * st4) + \
290 st * (st * st4 - st2 * st3) + \
291 st2 * (st2 * st2 - st * st3)
296 v = (1.0 / A) * (sx * (st * st4 - st2 * st3) +
297 stx * (st2 * st2 - n * st4) +
298 st2x * (n * st3 - st * st2))
300 a = (2.0 / A) * (sx * (st2 * st2 - st * st3) +
301 stx * (n * st3 - st * st2) +
302 st2x * (st * st - n * st2))
307 Compute translational and rotational velocities and accelerations in 308 the inertial frame at the target time t. 312 [1] Sittel, Florian, Joerg Mueller, and Wolfram Burgard. Computing 313 velocities and accelerations from a pose time sequence in 314 three-dimensional space. Technical Report 272, University of 315 Freiburg, Department of Computer Science, 2013. 318 lin_vel = np.zeros(3)
319 lin_acc = np.zeros(3)
326 [(pnt[
'pos'][i], pnt[
't'])
for pnt
in pnts], t)
332 [(pnt[
'rot'][i], pnt[
't'])
for pnt
in pnts], t)
337 ang_vel = 2 * quaternion_multiply(q_d, quaternion_conjugate(qt))
338 ang_acc = 2 * quaternion_multiply(q_dd, quaternion_conjugate(qt))
340 return np.hstack((lin_vel, ang_vel[0:3])), np.hstack((lin_acc, ang_acc[0:3]))
343 """Return trajectory sample for the current parameter s.""" 344 cur_s = (t - self.interpolator.start_time) / (self.interpolator.max_time - self.interpolator.start_time)
345 last_s = cur_s - self.interpolator.s_step
348 pnt = self.interpolator.generate_pnt(
350 cur_s * (self.interpolator.max_time - self.interpolator.start_time) + self.interpolator.start_time,
360 pnt.acc = (pnt.vel - last_vel) / self.
_t_step 366 elif ti > self.interpolator.max_time - self.interpolator.start_time:
369 si = (ti - self.interpolator.start_time) / self.interpolator.max_time
370 pnts.append(dict(pos=self.interpolator.generate_pos(si),
371 rot=self.interpolator.generate_quat(si),
378 pnt.vel = np.zeros(6)
379 pnt.acc = np.zeros(6)
381 pnt.vel = np.zeros(6)
382 pnt.acc = np.zeros(6)
388 cur_s = (self.
_cur_s if s
is None else s)
389 last_s = cur_s - self.interpolator.s_step
391 if last_s < 0
or cur_s > 1:
394 q_cur = self.interpolator.generate_quat(cur_s)
395 q_last = self.interpolator.generate_quat(last_s)
397 cur_pos = self.interpolator.generate_pos(cur_s)
398 last_pos = self.interpolator.generate_pos(last_s)
404 q_diff = quaternion_multiply(q_cur, quaternion_inverse(q_last))
406 ang_vel = 2 * q_diff[0:3] / self.
_t_step 408 vel = [(cur_pos[0] - last_pos[0]) / self.
_t_step,
409 (cur_pos[1] - last_pos[1]) / self.
_t_step,
410 (cur_pos[2] - last_pos[2]) / self.
_t_step,
417 t = max(t, self.interpolator.start_time)
418 t = min(t, self.interpolator.max_time)
426 if not self.interpolator.init_interpolator():
427 self._logger.error(
'Error initializing the waypoint interpolator')
429 if self.interpolator.start_time
is None:
431 self.interpolator.s_step = self.
_t_step / (self.interpolator.max_time - self.interpolator.start_time)
437 self._logger.info(
'Waypoint interpolator initialized! Start time: %.2f s' % self.interpolator.start_time)
439 if self.interpolator.is_finished(t)
or not self.interpolator.has_started(t):
440 if self.interpolator.is_finished(t):
445 self._this_pnt.vel = np.zeros(6)
446 self._this_pnt.acc = np.zeros(6)
453 self.
_cur_s = (t - self.interpolator.start_time) / (self.interpolator.max_time - self.interpolator.start_time)
def interpolator_tags(self)
def generate_pnt(self, t, pos, rot)
def add_waypoint(self, waypoint, add_to_beginning=False)
def __init__(self, full_dof=False, use_finite_diff=True, interpolation_method='cubic', stamped_pose_only=False)
def set_start_time(self, t)
def _motion_regression_6d(self, pnts, qt, t)
def init_waypoints(self, waypoint_set, init_rot=(0, 0, 0, 1))
def set_interpolator_parameters(self, method, params)
def set_interpolation_method(self, method)
def interpolate(self, t, args)
def get_interpolation_method(self)
def stamped_pose_only(self)
def get_samples(self, step=0.005)
def use_finite_diff(self)
def _generate_vel(self, s=None)
def _motion_regression_1d(self, pnts, t)
def get_visual_markers(self)
def generate_reference(self, t, args)
def closest_waypoint(self)
def set_duration(self, t)
def closest_waypoint_idx(self)