20 from copy
import deepcopy
21 from os.path
import isfile
22 from threading
import Lock, Event
24 from std_msgs.msg
import Bool, Float64
25 from geometry_msgs.msg
import Twist
27 from uuv_control_msgs.msg
import Trajectory, TrajectoryPoint, WaypointSet
28 from visualization_msgs.msg
import MarkerArray
29 from geometry_msgs.msg
import Point
31 import uuv_trajectory_generator
34 quaternion_inverse, quaternion_matrix, euler_from_quaternion, quaternion_from_euler
36 from ._log
import get_logger
40 """Local planner for the dynamic positioning controllers 41 to interpolate trajectories and generate trajectories from 42 interpolated waypoint paths. 46 * `full_dof` (*type:* `bool`, *default:* `False`): If `True`, 47 the reference trajectory reference will be computed for 6 DoF, 48 otherwise, 4 DoF `(x, y, z, yaw)`. 49 * `stamped_pose_only` (*type:* `bool`, *default:* `False`): If 50 `True`, only stamped poses will be generated as a reference, with 51 velocity and acceleration reference being set to zero. 52 * `thrusters_only` (*type:* `bool`, *default:* `True`): If `False`, 53 the idle mode will be used to keep the vehicle moving. 57 * `max_forward_speed` (*type:* `float`, *default:* `1.0`): Maximum 58 allowed forward speed. 59 * `idle_radius` (*type:* `float`, *default:* `10.0`): Radius of the circle 60 path generated when an AUV is in idle mode. 61 * `inertial_frame_id` (*type:* `str`): Name of the inertial frame used, 62 options are `world` or `world_ned`. 63 * `timeout_idle_mode` (*type:* `float`): Timeout at the start or after 64 a trajectory is finished where the AUV is set to start idle mode path. 65 * `look_ahead_delay` (*type:* `float`): Look ahead delay in seconds. This 66 parameters will offset the interpolation of the trajectory in the given 67 amount of seconds to compute the look-ahead target for AUVs. 71 The parameters for the path interpolators must also be provided when 72 starting a node that includes the local planner, since the interpolators 73 are initialized by the local planner. 77 * `trajectory` (*type:* `uuv_control_msgs.Trajectory`): Generated trajectory or 79 * `waypoints` (*type:* `uuv_control_msgs.WaypointSet`): Set of waypoints provided 80 as input for the interpolator 81 * `station_keeping_on` (*type:* `std_msgs.Bool`): Status of the station keeping mode 82 * `automatic_on` (*type:* `std_msgs.Bool`): Status of automatic model. If `False` 83 the vehicle can receive control inputs from a teleop node. 84 * `trajectory_tracking_on` (*type:* `std_msgs.Bool`): Sets the output flag to `True` 85 when trajectory tracking is ongoing 86 * `interpolator_visual_markers` (*type:* `visualization_msgs.MarkerArray`): Helper 87 visual markers from the interpolator class. 88 * `time_to_target` (*type:* `std_msgs.Float64`): Estimated time to target in seconds. 92 * `hold_vehicle` (*type:* `uuv_control_msgs.Hold`) 93 * `start_waypoint_list` (*type:* `uuv_control_msgs.InitWaypointSet`) 94 * `start_circular_trajectory` (*type:* `uuv_control_msgs.InitCircularTrajectory`) 95 * `start_helical_trajectory` (*type:* `uuv_control_msgs.InitHelicalTrajectory`) 96 * `init_waypoints_from_file` (*type:* `uuv_control_msgs.InitWaypointsFromFile`) 97 * `go_to` (*type:* `uuv_control_msgs.GoTo`) 98 * `go_to_incremental` (*type:* `uuv_control_msgs.GoToIncremental`) 101 def __init__(self, full_dof=False, stamped_pose_only=False, thrusters_only=True):
107 full_dof=full_dof, stamped_pose_only=stamped_pose_only)
120 self._logger.info(
'Idle circle radius [m] = %.2f' % self.
_idle_radius)
128 if rospy.has_param(
'~inertial_frame_id'):
143 tf_trans_ned_to_enu = tf_buffer.lookup_transform(
144 'world',
'world_ned', rospy.Time(),
148 [tf_trans_ned_to_enu.transform.rotation.x,
149 tf_trans_ned_to_enu.transform.rotation.y,
150 tf_trans_ned_to_enu.transform.rotation.z,
151 tf_trans_ned_to_enu.transform.rotation.w])
152 except Exception
as ex:
153 self._logger.warning(
154 'Error while requesting ENU to NED transform' 155 ', message={}'.format(ex))
156 self.
q_ned_to_enu = quaternion_from_euler(2 * np.pi, 0, np.pi)
162 self._logger.info(
'Transform world_ned (NED) to world (ENU)=\n' +
166 self._logger.info(
'Max. forward speed = ' +
169 for method
in self._traj_interpolator.get_interpolator_tags():
170 if rospy.has_param(
'~' + method):
171 self._logger.info(
'Parameters for interpolation method <%s> found' % method)
172 params = rospy.get_param(
'~' + method)
173 self._logger.info(
'\t' + str(params))
175 self._traj_interpolator.set_interpolator_parameters(method, params)
177 self._logger.info(
'No parameters for interpolation method <%s> found' % method)
189 self.init_odom_event.clear()
237 self.
_max_time_pub = rospy.Publisher(
'time_to_target', Float64, queue_size=1)
257 self.
_services[
'hold_vehicle'] = rospy.Service(
259 self.
_services[
'start_waypoint_list'] = rospy.Service(
261 self.
_services[
'start_circular_trajectory'] = rospy.Service(
262 'start_circular_trajectory', InitCircularTrajectory,
264 self.
_services[
'start_helical_trajectory'] = rospy.Service(
265 'start_helical_trajectory', InitHelicalTrajectory,
267 self.
_services[
'init_waypoints_from_file'] = rospy.Service(
268 'init_waypoints_from_file', InitWaypointsFromFile,
270 self.
_services[
'go_to'] = rospy.Service(
'go_to', GoTo, self.
go_to)
271 self.
_services[
'go_to_incremental'] = rospy.Service(
275 """Remove logging message handlers""" 276 while self._logger.handlers:
277 self._logger.handlers.pop()
280 """Transform the position vector between `world` and `world_ned`. 284 * `vec` (*type:* `numpy.array`): Position vector 285 * `target` (*type:* `str`): Target frame 286 * `source` (*type:* `str`): Source frame 290 `numpy.array`: Transformed vector 294 if target ==
'world':
296 if target ==
'world_ned':
297 return np.dot(self.transform_ned_to_enu.T, vec)
300 """Transform position vector of a waypoint between 301 `world` and `world_ned` frames. 305 * `waypoint` (*type:* `uuv_waypoints.Waypoint`): Input waypoint 309 `uuv_waypoints.Waypoint`: Transformed waypoint 311 output = deepcopy(waypoint)
314 output.inertial_frame_id)
320 """Apply transformation between `world` and 'world_ned` frames 321 to waypoints in a waypoint set. 325 * `waypoint_set` (*type:* `uuv_waypoins.WaypointSet`): Set of waypoints 329 `uuv_waypoins.WaypointSet`: Set of transformed waypoints 331 output = uuv_waypoints.WaypointSet(
333 for i
in range(waypoint_set.num_waypoints):
335 output.add_waypoint(wp)
339 """Filter out waypoints that are positioned above 340 sea surface, namely `z > 0` if the inertial frame is 341 `world`, or `z < 0` if the inertial frame is `world_ned`. 345 * `waypoint_set` (*type:* `uuv_waypoins.WaypointSet`): Set of waypoints 349 `uuv_waypoins.WaypointSet`: Filtered set of waypoints 351 wp_set = uuv_waypoints.WaypointSet(
353 for i
in range(waypoint_set.num_waypoints):
354 wp = waypoint_set.get_waypoint(i)
359 wp_set.add_waypoint(wp)
363 """Publish messages for the waypoints, trajectory and 370 markers = self._traj_interpolator.get_visual_markers()
371 if markers
is not None:
372 self._interp_visual_markers.publish(markers)
374 self._interp_visual_markers.publish(MarkerArray())
376 self._automatic_control_pub.publish(Bool(self.
_is_automatic))
381 """Update the trajectory message.""" 383 if self._traj_interpolator.is_using_waypoints():
384 wps = self._traj_interpolator.get_waypoints()
389 msg = self._traj_interpolator.get_trajectory_as_message()
393 self._logger.info(
'Updating the trajectory information')
396 self._logger.error(
'Error generating trajectory message')
399 """Callback to the twist teleop subscriber.""" 419 vel = np.array([self._teleop_vel_ref.linear.x, self._teleop_vel_ref.linear.y, self._teleop_vel_ref.linear.z, self._teleop_vel_ref.angular.z])
426 """Compute pose and velocity reference using the 427 joystick linear and angular velocity input. 440 speed = np.sqrt(self._teleop_vel_ref.linear.x**2 + self._teleop_vel_ref.linear.y**2)
441 vel = np.array([self._teleop_vel_ref.linear.x, self._teleop_vel_ref.linear.y, self._teleop_vel_ref.linear.z])
447 vel = np.dot(self._vehicle_pose.rot_matrix, vel)
450 step = uuv_trajectory_generator.TrajectoryPoint()
451 step.pos = np.dot(self._vehicle_pose.rot_matrix, vel * self.
_dt)
452 step.rotq = quaternion_about_axis(self._teleop_vel_ref.angular.z * self.
_dt, [0, 0, 1])
455 ref_pnt = uuv_trajectory_generator.TrajectoryPoint()
456 ref_pnt.pos = self._vehicle_pose.pos + step.pos
463 ref_pnt.vel = [vel[0], vel[1], 0, 0, 0, self._teleop_vel_ref.angular.z]
465 ref_pnt.vel = [vel[0], vel[1], vel[2], 0, 0, self._teleop_vel_ref.angular.z]
467 ref_pnt.acc = np.zeros(6)
474 """Add the current vehicle position as waypoint 475 to allow a smooth approach to the given trajectory. 478 self._logger.error(
'Simulation not properly initialized yet, ignoring approach...')
480 if not self._traj_interpolator.is_using_waypoints():
481 self._logger.error(
'Not using the waypoint interpolation method')
487 init_wp = uuv_waypoints.Waypoint(
488 x=self._vehicle_pose.pos[0],
489 y=self._vehicle_pose.pos[1],
490 z=self._vehicle_pose.pos[2],
491 max_forward_speed=self._traj_interpolator.get_waypoints().get_waypoint(0).max_forward_speed,
492 heading_offset=self._traj_interpolator.get_waypoints().get_waypoint(0).heading_offset)
494 max_speed = self._traj_interpolator.get_waypoints().get_waypoint(0).max_forward_speed
495 init_wp = uuv_waypoints.Waypoint(
496 x=self._vehicle_pose.pos[0],
497 y=self._vehicle_pose.pos[1],
498 z=self._vehicle_pose.pos[2],
499 max_forward_speed=max_speed,
500 heading_offset=self._traj_interpolator.get_waypoints().get_waypoint(0).heading_offset)
501 first_wp = self._traj_interpolator.get_waypoints().get_waypoint(0)
503 dx = first_wp.x - init_wp.x
504 dy = first_wp.y - init_wp.y
505 dz = first_wp.z - init_wp.z
508 self._logger.info(
'Adding waypoints to approach the first position in the given waypoint set')
509 steps = int(np.floor(first_wp.dist(init_wp.pos)) / 10)
510 if steps > 0
and self._traj_interpolator.get_interp_method() !=
'dubins':
511 for i
in range(1, steps):
512 wp = uuv_waypoints.Waypoint(
513 x=first_wp.x - i * dx / steps,
514 y=first_wp.y - i * dy / steps,
515 z=first_wp.z - i * dz / steps,
516 max_forward_speed=self._traj_interpolator.get_waypoints().get_waypoint(0).max_forward_speed)
517 self._traj_interpolator.add_waypoint(wp, add_to_beginning=
True)
518 self._traj_interpolator.add_waypoint(init_wp, add_to_beginning=
True)
522 """Return `True`, if vehicle is holding its position.""" 526 """Return `True` if vehicle if following a trajectory in 532 """Set station keeping mode flag. 536 * `is_on` (*type:* `bool`, *default:* `True`): Station keeping flag 539 self._logger.info(
'STATION KEEPING MODE = ' + (
'ON' if is_on
else 'OFF'))
542 """Set automatic mode flag.""" 544 self._logger.info(
'AUTOMATIC MODE = ' + (
'ON' if is_on
else 'OFF'))
547 """Set trajectory tracking flag.""" 549 self._logger.info(
'TRAJECTORY TRACKING = ' + (
'ON' if is_on
else 'OFF'))
552 """Return if the trajectory interpolator has started generating 556 return self._traj_interpolator.has_started()
559 """Return `True` if the trajectory has finished.""" 560 return self._traj_interpolator.has_finished()
563 """Update the vehicle's pose information. 567 * `pos` (*type:* `numpy.array`): Position vector 568 * `quat` (*type:* `numpy.array`): Quaternion as `(qx, qy, qz, qw)` 571 self.
_vehicle_pose = uuv_trajectory_generator.TrajectoryPoint()
572 self._vehicle_pose.pos = pos
573 self._vehicle_pose.rotq = quat
574 self._vehicle_pose.t = rospy.get_time()
575 self.init_odom_event.set()
578 """Return the vehicle's rotation quaternion.""" 579 self.init_odom_event.wait()
580 return self._vehicle_pose.rotq
584 self._traj_interpolator.init_from_trajectory_message(msg)
589 """Start station keeping mode by setting the pose 590 set-point of the vehicle as the last pose before the 591 vehicle finished automatic mode. 595 self._this_ref_pnt.vel = np.zeros(6)
596 self._this_ref_pnt.acc = np.zeros(6)
602 """Service callback function to hold the vehicle's 606 self._logger.error(
'Current pose of the vehicle is invalid')
607 return HoldResponse(
False)
609 return HoldResponse(
True)
612 """Service callback function to follow a set of waypoints 616 * `request` (*type:* `uuv_control_msgs.InitWaypointSet`) 618 if len(request.waypoints) == 0:
619 self._logger.error(
'Waypoint list is empty')
620 return InitWaypointSetResponse(
False)
621 t = rospy.Time(request.start_time.data.secs, request.start_time.data.nsecs)
622 if t.to_sec() < rospy.get_time()
and not request.start_now:
623 self._logger.error(
'The trajectory starts in the past, correct the starting time!')
624 return InitWaypointSetResponse(
False)
626 self._logger.info(
'Start waypoint trajectory now!')
629 wp_set = uuv_waypoints.WaypointSet(
632 waypointset_msg = WaypointSet()
633 waypointset_msg.header.stamp = rospy.get_time()
635 if request.start_now:
636 waypointset_msg.start_time = rospy.get_time()
638 waypointset_msg.start_time = t.to_sec()
639 waypointset_msg.waypoints = request.waypoints
640 wp_set.from_message(waypointset_msg)
644 if self._traj_interpolator.set_waypoints(wp_set, self.
get_vehicle_rot()):
646 self._traj_interpolator.set_start_time((t.to_sec()
if not request.start_now
else rospy.get_time()))
653 self._logger.info(
'============================')
654 self._logger.info(
' WAYPOINT SET ')
655 self._logger.info(
'============================')
656 self._logger.info(
'Interpolator = ' + request.interpolator.data)
657 self._logger.info(
'# waypoints = %d' % self._traj_interpolator.get_waypoints().num_waypoints)
658 self._logger.info(
'Starting time = %.2f' % (t.to_sec()
if not request.start_now
else rospy.get_time()))
660 self._logger.info(
'============================')
662 return InitWaypointSetResponse(
True)
664 self._logger.error(
'Error occurred while parsing waypoints')
666 return InitWaypointSetResponse(
False)
669 """Service callback function to initialize a parametrized 674 * `request` (*type:* `uuv_control_msgs.InitCircularTrajectory`) 676 if request.max_forward_speed <= 0
or request.radius <= 0
or \
677 request.n_points <= 0:
678 self._logger.error(
'Invalid parameters to generate a circular trajectory')
679 return InitCircularTrajectoryResponse(
False)
680 t = rospy.Time(request.start_time.data.secs, request.start_time.data.nsecs)
681 if t.to_sec() < rospy.get_time()
and not request.start_now:
682 self._logger.error(
'The trajectory starts in the past, correct the starting time!')
683 return InitCircularTrajectoryResponse(
False)
685 wp_set = uuv_waypoints.WaypointSet(
687 success = wp_set.generate_circle(radius=request.radius,
688 center=request.center,
689 num_points=request.n_points,
690 max_forward_speed=request.max_forward_speed,
691 theta_offset=request.angle_offset,
692 heading_offset=request.heading_offset)
694 self._logger.error(
'Error generating circular trajectory from waypoint set')
695 return InitCircularTrajectoryResponse(
False)
698 self._logger.error(
'Waypoints violate workspace constraints, are you using world or world_ned as reference?')
699 return InitCircularTrajectoryResponse(
False)
704 self._traj_interpolator.set_interp_method(
'cubic')
707 self._traj_interpolator.set_start_time((t.to_sec()
if not request.start_now
else rospy.get_time()))
708 if request.duration > 0:
709 if self._traj_interpolator.set_duration(request.duration):
710 self._logger.info(
'Setting a maximum duration, duration=%.2f s' % request.duration)
712 self._logger.error(
'Setting maximum duration failed')
721 self._logger.info(
'============================')
722 self._logger.info(
'CIRCULAR TRAJECTORY GENERATED FROM WAYPOINT INTERPOLATION')
723 self._logger.info(
'============================')
724 self._logger.info(
'Radius [m] = %.2f' % request.radius)
725 self._logger.info(
'Center [m] = (%.2f, %.2f, %.2f)' % (request.center.x, request.center.y, request.center.z))
726 self._logger.info(
'# of points = %d' % request.n_points)
727 self._logger.info(
'Max. forward speed = %.2f' % request.max_forward_speed)
728 self._logger.info(
'Circle angle offset = %.2f' % request.angle_offset)
729 self._logger.info(
'Heading offset = %.2f' % request.heading_offset)
730 self._logger.info(
'# waypoints = %d' % self._traj_interpolator.get_waypoints().num_waypoints)
731 self._logger.info(
'Starting from = ' + str(self._traj_interpolator.get_waypoints().get_waypoint(0).pos))
732 self._logger.info(
'Starting time [s] = %.2f' % (t.to_sec()
if not request.start_now
else rospy.get_time()))
733 self._logger.info(
'============================')
735 return InitCircularTrajectoryResponse(
True)
736 except Exception
as e:
737 self._logger.error(
'Error while setting circular trajectory, msg={}'.format(e))
742 return InitCircularTrajectoryResponse(
False)
745 """Service callback function to initialize a parametrized helical 750 * `request` (*type:* `uuv_control_msgs.InitHelicalTrajectory`) 752 if request.radius <= 0
or request.n_points <= 0
or \
753 request.n_turns <= 0:
754 self._logger.error(
'Invalid parameters to generate a helical trajectory')
755 return InitHelicalTrajectoryResponse(
False)
756 t = rospy.Time(request.start_time.data.secs, request.start_time.data.nsecs)
757 if t.to_sec() < rospy.get_time()
and not request.start_now:
758 self._logger.error(
'The trajectory starts in the past, correct the starting time!')
759 return InitHelicalTrajectoryResponse(
False)
761 self._logger.info(
'Start helical trajectory now!')
765 success = wp_set.generate_helix(radius=request.radius,
766 center=request.center,
767 num_points=request.n_points,
768 max_forward_speed=request.max_forward_speed,
769 delta_z=request.delta_z,
770 num_turns=request.n_turns,
771 theta_offset=request.angle_offset,
772 heading_offset=request.heading_offset)
775 self._logger.error(
'Error generating circular trajectory from waypoint set')
776 return InitHelicalTrajectoryResponse(
False)
779 self._logger.error(
'Waypoints violate workspace constraints, are you using world or world_ned as reference?')
780 return InitHelicalTrajectoryResponse(
False)
784 self._traj_interpolator.set_interp_method(
'cubic')
785 if not self._traj_interpolator.set_waypoints(wp_set, self.
get_vehicle_rot()):
786 self._logger.error(
'Error setting the waypoints')
787 return InitHelicalTrajectoryResponse(
False)
790 self._traj_interpolator.set_start_time((t.to_sec()
if not request.start_now
else rospy.get_time()))
792 if request.duration > 0:
793 if self._traj_interpolator.set_duration(request.duration):
794 self._logger.info(
'Setting a maximum duration, duration=%.2f s' % request.duration)
796 self._logger.error(
'Setting maximum duration failed')
804 self._logger.info(
'============================')
805 self._logger.info(
'HELICAL TRAJECTORY GENERATED FROM WAYPOINT INTERPOLATION')
806 self._logger.info(
'============================')
807 self._logger.info(
'Radius [m] = %.2f' % request.radius)
808 self._logger.info(
'Center [m] = (%.2f, %.2f, %.2f)' % (request.center.x, request.center.y, request.center.z))
809 self._logger.info(
'# of points = %d' % request.n_points)
810 self._logger.info(
'Max. forward speed = %.2f' % request.max_forward_speed)
811 self._logger.info(
'Delta Z = %.2f' % request.delta_z)
812 self._logger.info(
'# of turns = %d' % request.n_turns)
813 self._logger.info(
'Helix angle offset = %.2f' % request.angle_offset)
814 self._logger.info(
'Heading offset = %.2f' % request.heading_offset)
815 self._logger.info(
'# waypoints = %d' % self._traj_interpolator.get_waypoints().num_waypoints)
816 self._logger.info(
'Starting from = ' + str(self._traj_interpolator.get_waypoints().get_waypoint(0).pos))
817 self._logger.info(
'Starting time [s] = %.2f' % (t.to_sec()
if not request.start_now
else rospy.get_time()))
818 self._logger.info(
'============================')
820 return InitHelicalTrajectoryResponse(
True)
821 except Exception
as e:
822 self._logger.error(
'Error while setting helical trajectory, msg={}'.format(e))
827 return InitHelicalTrajectoryResponse(
False)
830 """Service callback function to initialize the path interpolator 831 with a set of waypoints loaded from a YAML file. 835 * `request` (*type:* `uuv_control_msgs.InitWaypointsFromFile`) 837 if (len(request.filename.data) == 0
or 838 not isfile(request.filename.data)):
839 self._logger.error(
'Invalid waypoint file')
840 return InitWaypointsFromFileResponse(
False)
841 t = rospy.Time(request.start_time.data.secs, request.start_time.data.nsecs)
842 if t.to_sec() < rospy.get_time()
and not request.start_now:
843 self._logger.error(
'The trajectory starts in the past, correct the starting time!')
844 return InitWaypointsFromFileResponse(
False)
846 self._logger.info(
'Start waypoint trajectory now!')
849 self._traj_interpolator.set_interp_method(request.interpolator.data)
851 wp_set = uuv_waypoints.WaypointSet()
852 if not wp_set.read_from_file(request.filename.data):
853 self._logger.info(
'Error occurred while parsing waypoint file')
854 return InitWaypointsFromFileResponse(
False)
858 if self._traj_interpolator.set_waypoints(wp_set, self.
get_vehicle_rot()):
860 self._traj_interpolator.set_start_time((t.to_sec()
if not request.start_now
else rospy.get_time()))
868 self._logger.info(
'============================')
869 self._logger.info(
'IMPORT WAYPOINTS FROM FILE')
870 self._logger.info(
'============================')
871 self._logger.info(
'Filename = ' + request.filename.data)
872 self._logger.info(
'Interpolator = ' + request.interpolator.data)
873 self._logger.info(
'# waypoints = %d' % self._traj_interpolator.get_waypoints().num_waypoints)
874 self._logger.info(
'Starting time = %.2f' % (t.to_sec()
if not request.start_now
else rospy.get_time()))
876 self._logger.info(
'============================')
878 return InitWaypointsFromFileResponse(
True)
880 self._logger.error(
'Error occurred while parsing waypoint file')
882 return InitWaypointsFromFileResponse(
False)
885 """Service callback function to initialize to set one target 890 * `request` (*type:* `uuv_control_msgs.GoTo`) 893 self._logger.error(
'Current pose has not been initialized yet')
894 return GoToResponse(
False)
895 if request.waypoint.max_forward_speed <= 0.0:
896 self._logger.error(
'Max. forward speed must be greater than zero')
897 return GoToResponse(
False)
900 wp_set = uuv_waypoints.WaypointSet(
903 init_wp = uuv_waypoints.Waypoint(
904 x=self._vehicle_pose.pos[0],
905 y=self._vehicle_pose.pos[1],
906 z=self._vehicle_pose.pos[2],
907 max_forward_speed=request.waypoint.max_forward_speed,
909 use_fixed_heading=request.waypoint.use_fixed_heading,
911 wp_set.add_waypoint(init_wp)
912 wp_set.add_waypoint_from_msg(request.waypoint)
914 self._traj_interpolator.set_interp_method(request.interpolator)
915 if not self._traj_interpolator.set_waypoints(wp_set, self.
get_vehicle_rot()):
916 self._logger.error(
'Error while setting waypoints')
918 return GoToResponse(
False)
922 self._traj_interpolator.set_start_time(t)
930 self._logger.info(
'============================')
931 self._logger.info(
'GO TO')
932 self._logger.info(
'============================')
933 self._logger.info(
'Heading offset [rad] = %.2f' % request.waypoint.heading_offset)
934 self._logger.info(
'# waypoints = %d' % self._traj_interpolator.get_waypoints().num_waypoints)
935 self._logger.info(
'Starting from = ' + str(self._traj_interpolator.get_waypoints().get_waypoint(0).pos))
936 self._logger.info(
'Start time [s] = %.2f ' % t)
938 self._logger.info(
'============================')
940 return GoToResponse(
True)
943 """Service callback to set the command to the vehicle to move to a 944 relative position in the world. 948 * `request` (*type:* `uuv_control_msgs.GoToIncremental`) 951 self._logger.error(
'Current pose has not been initialized yet')
952 return GoToIncrementalResponse(
False)
953 if request.max_forward_speed <= 0:
954 self._logger.error(
'Max. forward speed must be positive')
955 return GoToIncrementalResponse(
False)
959 wp_set = uuv_waypoints.WaypointSet(
961 init_wp = uuv_waypoints.Waypoint(
962 x=self._vehicle_pose.pos[0],
963 y=self._vehicle_pose.pos[1],
964 z=self._vehicle_pose.pos[2],
965 max_forward_speed=request.max_forward_speed,
968 wp_set.add_waypoint(init_wp)
970 wp = uuv_waypoints.Waypoint(
971 x=self._vehicle_pose.pos[0] + request.step.x,
972 y=self._vehicle_pose.pos[1] + request.step.y,
973 z=self._vehicle_pose.pos[2] + request.step.z,
974 max_forward_speed=request.max_forward_speed,
976 wp_set.add_waypoint(wp)
978 self._traj_interpolator.set_interp_method(request.interpolator)
979 if not self._traj_interpolator.set_waypoints(wp_set, self.
get_vehicle_rot()):
980 self._logger.error(
'Error while setting waypoints')
982 return GoToIncrementalResponse(
False)
985 self._traj_interpolator.set_start_time(rospy.Time.now().to_sec())
993 self._logger.info(
'============================')
994 self._logger.info(
'GO TO INCREMENTAL')
995 self._logger.info(
'============================')
996 self._logger.info(str(wp_set))
997 self._logger.info(
'# waypoints = %d' % wp_set.num_waypoints)
999 self._logger.info(
'============================')
1000 self._lock.release()
1001 return GoToIncrementalResponse(
True)
1004 """Return a trajectory point computed by the interpolator for the 1005 timestamp `t`, in case the vehicle is on `automatic` mode. In case 1006 it is in station keeping, the pose is kept constant. 1010 * `t` (*type:* `float`): Timestamp 1014 `uuv_trajectory_generator.TrajectoryPoint`: Trajectory point 1016 pnt = self._traj_interpolator.generate_reference(t, self._vehicle_pose.pos, self.
get_vehicle_rot())
1023 """Generate a waypoint set starting from the current 1024 position of the vehicle in the shape of a circle to 1025 initialize an AUVs idle mode. 1029 * `n_points` (*type:* `int`): Number of waypoints 1030 * `radius` (*type:* `float`): Circle radius in meters 1034 `uuv_waypoints.WaypointSet`: Set of waypoints for idle mode 1039 [np.cos(pose.rot[2]), -np.sin(pose.rot[2]), 0],
1040 [np.sin(pose.rot[2]), np.cos(pose.rot[2]), 0],
1045 phi =
lambda u: 2 * np.pi * u + pose.rot[2] - np.pi / 2
1046 u =
lambda angle: (angle - pose.rot[2] + np.pi / 2) / (2 * np.pi)
1049 vec /= np.linalg.norm(vec)
1050 u_init = u(np.arctan2(vec[1], vec[0]))
1052 wp_set = uuv_waypoints.WaypointSet(
1055 for i
in np.linspace(u_init, u_init + 1, n_points):
1056 wp = uuv_waypoints.Waypoint(
1062 wp_set.add_waypoint(wp)
1066 """Function interface to the controller. Calls the interpolator to 1067 calculate the current trajectory sample or returns a fixed position 1068 based on the past odometry measurements for station keeping. 1072 * `t` (*type:* `float`): Timestamp 1076 `uuv_trajectory_generator.TrajectoryPoint`: Trajectory point 1079 self._lock.acquire()
1087 self._logger.info(
'Adding waypoints to approach the given waypoint trajectory')
1095 self._max_time_pub.publish(Float64(self._traj_interpolator.get_max_time() - rospy.get_time()))
1099 self._logger.info(rospy.get_namespace() +
' - Trajectory running')
1103 self._logger.info(rospy.get_namespace() +
' - Trajectory completed!')
1110 self._this_ref_pnt.vel = np.zeros(6)
1111 self._this_ref_pnt.acc = np.zeros(6)
1117 self._traj_interpolator.set_interp_method(
'lipb')
1124 yaw = self._this_ref_pnt.rot[2]
1125 self._this_ref_pnt.rot = [0, 0, yaw]
1130 self._max_time_pub.publish(Float64(0))
1133 self._logger.info(
'AUV STATION KEEPING')
1140 raise rospy.ROSException(
'Waypoints violate workspace constraints, are you using world or world_ned as reference?')
1144 self._traj_interpolator.set_interp_method(
'cubic')
1146 self._traj_interpolator.set_start_time(rospy.get_time())
1154 self._lock.release()
def set_station_keeping(self, is_on=True)
def get_vehicle_rot(self)
def get_idle_circle_path(self, n_points, radius=30)
_stamp_trajectory_received
def _transform_waypoint(self, waypoint)
def _update_trajectory_from_msg(self, msg)
def _calc_smooth_approach(self)
def _update_trajectory_info(self)
def _calc_teleop_reference(self)
def is_station_keeping_on(self)
def set_trajectory_running(self, is_on=True)
def start_circle(self, request)
def _apply_workspace_constraints(self, waypoint_set)
def init_waypoints_from_file(self, request)
def start_station_keeping(self)
def generate_reference(self, t)
def __init__(self, full_dof=False, stamped_pose_only=False, thrusters_only=True)
def update_vehicle_pose(self, pos, quat)
def _transform_position(self, vec, target, source)
def _update_teleop(self, msg)
def _transform_waypoint_set(self, waypoint_set)
def start_helix(self, request)
def is_automatic_on(self)
def start_waypoint_list(self, request)
def go_to_incremental(self, request)
def set_automatic_mode(self, is_on=True)
def hold_vehicle(self, request)
def _publish_trajectory_info(self, event)