def new_goal(self):
        goal = self.moveto_as.accept_new_goal()
        self.desired_position = tools.position_from_posetwist(goal.posetwist)
        self.desired_orientation = tools.orientation_from_posetwist(
            goal.posetwist)
        #self.linear_tolerance = goal.linear_tolerance
        #self.angular_tolerance = goal.angular_tolerance

        rospy.loginfo('Desired position:' + str(self.desired_position))
        rospy.loginfo('Current position:' + str(self.current_position))
        rospy.loginfo('Desired orientation:' + str(self.desired_orientation))
        rospy.loginfo('Current orientation:' + str(self.current_orientation))
        rospy.loginfo('linear_tolerance:' + str(self.linear_tolerance))
        rospy.loginfo('angular_tolerance:' + str(self.angular_tolerance))
        # This controller doesn't handle desired twist
        #self.desired_twist = goal.posetwist.twist
        if (xyz_array(goal.posetwist.twist.linear).any()
                or xyz_array(goal.posetwist.twist.angular).any()):
            rospy.logwarn(
                'None zero are not handled by the tank steer trajectory generator. Setting twist to 0'
            )

        if np.linalg.norm(self.current_position -
                          self.desired_position) > self.orientation_radius:
            self.line = line(self.current_position, self.desired_position)
            self.redraw_line = True
        else:
            self.line = line(
                self.current_position,
                tools.normal_vector_from_rotvec(self.desired_orientation) +
                self.current_position)
            self.redraw_line = False
	def new_goal(self):
		goal = self.moveto_as.accept_new_goal()
		self.desired_position = tools.position_from_posetwist(goal.posetwist)
		self.desired_orientation = tools.orientation_from_posetwist(goal.posetwist)
		#self.linear_tolerance = goal.linear_tolerance
		#self.angular_tolerance = goal.angular_tolerance

		rospy.loginfo('Desired position:' + str(self.desired_position))
		rospy.loginfo('Current position:' + str(self.current_position))
		rospy.loginfo('Desired orientation:' + str(self.desired_orientation))
		rospy.loginfo('Current orientation:' + str(self.current_orientation))
		rospy.loginfo('linear_tolerance:' + str(self.linear_tolerance))
		rospy.loginfo('angular_tolerance:' + str(self.angular_tolerance))
		# This controller doesn't handle desired twist
		#self.desired_twist = goal.posetwist.twist
		if (xyz_array(goal.posetwist.twist.linear).any() or 
			xyz_array(goal.posetwist.twist.angular).any() ):
			rospy.logwarn('None zero are not handled by the tank steer trajectory generator. Setting twist to 0')
		
		if np.linalg.norm(self.current_position - self.desired_position) > self.orientation_radius:
			self.line = line(self.current_position, self.desired_position)
			self.redraw_line = True
		else:
			self.line = line(self.current_position, tools.normal_vector_from_rotvec(self.desired_orientation) + self.current_position)
			self.redraw_line = False
Exemple #3
0
    def update(self):
        # Check if in the orientation radius for the first time
        if self.redraw_line and self.distance_to_goal < self.orientation_radius:
            self.redraw_line = False
            rospy.loginfo('Redrawing trajectory line')
            self.line = line(
                self.desired_position,
                tools.normal_vector_from_rotvec(self.desired_orientation) +
                self.desired_position)

        # Output a posetwist (carrot)
        # Project current position onto trajectory line
        Bproj = self.line.proj_pt(self.current_position)
        parallel_distance = np.linalg.norm(self.desired_position - Bproj)

        # Move carrot along line
        tracking_step = self.get_tracking_distance()
        c_pos = Bproj + self.overshoot * self.line.hat * tracking_step

        # If bproj is in threashold just set the carrot to the final position
        if parallel_distance < self.orientation_radius:
            c_pos = self.desired_position

        # Fill up PoseTwist
        carrot = PoseTwist(
            pose=Pose(position=tools.vector3_from_xyz_array(c_pos),
                      orientation=tools.quaternion_from_rotvec(
                          [0, 0, self.line.angle])),
            twist=Twist(
                linear=Vector3(
                    tracking_step * self.tracking_to_speed_conv *
                    self.overshoot, 0,
                    0),  # Wrench Generator handles the sine of the velocity
                angular=Vector3()))
        return carrot
    def update(self, event):

        # Publish trajectory
        traj = self.get_carrot()
        #rospy.loginfo('Trajectory: ' + str(traj))
        if not self.killed:
            self.traj_pub.publish(traj)

        if self.redraw_line and self.distance_to_goal < self.orientation_radius:
            self.redraw_line = False
            rospy.loginfo('Redrawing trajectory line')
            self.line = line(
                self.current_position,
                tools.normal_vector_from_rotvec(self.desired_orientation) +
                self.current_position)

        rospy.loginfo('Angle to goal: ' +
                      str(self.angle_to_goal_orientation[2] * 180 / np.pi) +
                      '\t\t\tDistance to goal: ' + str(self.distance_to_goal))

        # Check if goal is reached
        if self.moveto_as.is_active():
            if self.distance_to_goal < self.linear_tolerance:
                if self.angle_to_goal_orientation[2] < self.angular_tolerance:
                    rospy.loginfo('succeded')
                    self.moveto_as.set_succeeded(None)
Exemple #5
0
    def update(self):
        # Check if in the orientation radius for the first time
        if self.redraw_line and self.distance_to_goal < self.orientation_radius:
            self.redraw_line = False
            rospy.loginfo('Redrawing trajectory line')
            self.line = line(self.desired_position, tools.normal_vector_from_rotvec(self.desired_orientation) + self.desired_position)

        # Output a posetwist (carrot)
        # Project current position onto trajectory line
        Bproj = self.line.proj_pt(self.current_position)
        parallel_distance = np.linalg.norm(self.desired_position - Bproj)

        # Move carrot along line
        tracking_step = self.get_tracking_distance()
        c_pos = Bproj + self.overshoot * self.line.hat * tracking_step

        # If bproj is in threashold just set the carrot to the final position
        if parallel_distance < self.orientation_radius:
            c_pos = self.desired_position      

        # Fill up PoseTwist
        carrot = PoseTwist(
                pose = Pose(
                    position = tools.vector3_from_xyz_array(c_pos),
                    orientation = tools.quaternion_from_rotvec([0, 0, self.line.angle])),

                twist = Twist(
                    linear = Vector3(tracking_step * self.tracking_to_speed_conv * self.overshoot, 0, 0),        # Wrench Generator handles the sine of the velocity
                    angular = Vector3())
                )
        return carrot
	def __init__(self, name):
		# Desired pose
		self.desired_position = self.current_position = np.zeros(3)
		self.desired_orientation = self.current_orientation = np.zeros(3)
		#self.desired_twist = self.current_twist = Twist()

		# Goal tolerances before seting succeded
		self.linear_tolerance = rospy.get_param('linear_tolerance', 0.5)
		self.angular_tolerance = rospy.get_param('angular_tolerance', np.pi / 10)
		self.orientation_radius = rospy.get_param('orientation_radius', 0.75)
		self.slow_down_radius = rospy.get_param('slow_down_radius', 5)

		# Speed parameters
		self.max_tracking_distance = rospy.get_param('max_tracking_distance', 5)
		self.min_tracking_distance = rospy.get_param('min_tracking_distance', 1)
		self.tracking_to_speed_conv = rospy.get_param('tracking_to_speed_conv', 1)
		self.tracking_slope = (self.max_tracking_distance - self.min_tracking_distance) / (self.slow_down_radius - self.orientation_radius)
		self.tracking_intercept = self.tracking_slope * self.orientation_radius + self.min_tracking_distance

		# Publishers
		self.traj_pub = rospy.Publisher('/trajectory', PoseTwistStamped, queue_size = 10)

		# Set desired twist to 0
		#self.desired_twist.linear.x = self.desired_twist.linear.y = self.desired_twist.linear.z = 0
		#self.desired_twist.angular.x = self.desired_twist.angular.y = self.desired_twist.angular.z = 0

		# Initilize a line
		self.line = line(np.zeros(3), np.ones(3))

		# Wait for current position and set as desired position
		rospy.loginfo('Waiting for /odom')
		self.odom_sub = rospy.Subscriber('/odom', Odometry, self.odom_cb, queue_size = 10)
		while not self.current_position.any():	# Will be 0 until an odom publishes (if its still 0 it will drift very very soon)
			pass

		# Initlize Trajectory generator with current position as goal
		# 	Set the line to be along our current orientation
		self.desired_position = self.current_position
		self.desired_orientation = self.current_orientation
		# 	Make a line along the orientation
		self.line = line(self.current_position, tools.normal_vector_from_rotvec(self.current_orientation) + self.current_position)
		self.redraw_line = False
		rospy.loginfo('Got current pose from /odom')

		# Kill handling
		self.killed = False
		self.kill_listener = KillListener(self.set_kill, self.clear_kill)
		self.kill_broadcaster = KillBroadcaster(id=name, description='Tank steer trajectory_generator shutdown')
		try:
			self.kill_broadcaster.clear()			# In case previously killed
		except rospy.service.ServiceException, e:
			rospy.logwarn(str(e))
    def start(self, current_pt):
        # Set current position and twist
        self.current_position = tools.position_from_posetwist(current_pt)
        # Zero the Z
        self.current_position[2] = 0
        self.current_orientation = tools.orientation_from_posetwist(current_pt)

        # Initlize Trajectory generator with current position as goal
        #   Set the line to be along our current orientation
        self.desired_position = self.current_position
        self.desired_orientation = self.current_orientation
        #   Make a line along the orientation
        self.line = line(self.current_position, tools.normal_vector_from_rotvec(self.current_orientation) + self.current_position)
    def feedback(self, pt):
        # Update current pt
        self.current_position = tools.position_from_posetwist(pt)
        # Zero the Z
        self.current_position[2] = 0
        self.current_orientation = tools.orientation_from_posetwist(pt)

        # Get distance to the goal
        if np.array_equal(self.current_position, self.desired_position):
            self.line = line(self.desired_position, tools.normal_vector_from_rotvec(self.desired_orientation) + self.desired_position)
        else:
            self.line = line(self.current_position, self.desired_position)

        self.distance_to_goal = np.linalg.norm(self.line.s)
Exemple #9
0
    def start(self, current_pt):
        # Set current position and twist
        self.current_position = tools.position_from_posetwist(current_pt)
        # Zero the Z
        self.current_position[2] = 0
        self.current_orientation = tools.orientation_from_posetwist(current_pt)

        # Initlize Trajectory generator with current position as goal
        #   Set the line to be along our current orientation
        self.desired_position = self.current_position
        self.desired_orientation = self.current_orientation
        #   Make a line along the orientation
        self.line = line(self.current_position, tools.normal_vector_from_rotvec(self.current_orientation) + self.current_position)
        self.redraw_line = False
Exemple #10
0
    def new_goal(self, goal):
        self.desired_position = tools.position_from_posetwist(goal)
        self.desired_orientation = tools.orientation_from_posetwist(goal)

        # Twist not supported
        if (xyz_array(goal.twist.linear).any() or 
            xyz_array(goal.twist.angular).any() ):
            rospy.logwarn('None zero twist are not handled by the azi point and shoot trajectory generator. Setting twist to 0')

        if np.linalg.norm(self.current_position - self.desired_position) > self.orientation_radius:
            #print 'Far out dude'
            self.line = line(self.current_position, self.desired_position)
        else:
            #print 'Pretty close'
            self.line = line(self.desired_position, tools.normal_vector_from_rotvec(self.desired_orientation) + self.desired_position)
    def feedback(self, pt):
        # Update current pt
        self.current_position = tools.position_from_posetwist(pt)
        # Zero the Z
        self.current_position[2] = 0
        self.current_orientation = tools.orientation_from_posetwist(pt)

        # Get distance to the goal
        if np.array_equal(self.current_position, self.desired_position):
            self.line = line(
                self.desired_position,
                tools.normal_vector_from_rotvec(self.desired_orientation) +
                self.desired_position)
        else:
            self.line = line(self.current_position, self.desired_position)

        self.distance_to_goal = np.linalg.norm(self.line.s)
	def update(self, event):
		
		# Publish trajectory
		traj = self.get_carrot()
		#rospy.loginfo('Trajectory: ' + str(traj))
		if not self.killed:
			self.traj_pub.publish(traj)

		if self.redraw_line and self.distance_to_goal < self.orientation_radius:
			self.redraw_line = False
			rospy.loginfo('Redrawing trajectory line')
			self.line = line(self.current_position, tools.normal_vector_from_rotvec(self.desired_orientation) + self.current_position)

		rospy.loginfo('Angle to goal: ' + str(self.angle_to_goal_orientation[2] * 180 / np.pi) + '\t\t\tDistance to goal: ' + str(self.distance_to_goal))

		# Check if goal is reached
		if self.moveto_as.is_active():
			if self.distance_to_goal < self.linear_tolerance:
				if self.angle_to_goal_orientation[2] < self.angular_tolerance:
					rospy.loginfo('succeded')
					self.moveto_as.set_succeeded(None)
    def new_goal(self, goal):
        self.desired_position = tools.position_from_posetwist(goal)
        self.desired_orientation = tools.orientation_from_posetwist(goal)

        # Twist not supported
        if (xyz_array(goal.twist.linear).any()
                or xyz_array(goal.twist.angular).any()):
            rospy.logwarn(
                'None zero twist are not handled by the azi point and shoot trajectory generator. Setting twist to 0'
            )

        if np.linalg.norm(self.current_position -
                          self.desired_position) > self.orientation_radius:
            #print 'Far out dude'
            self.line = line(self.current_position, self.desired_position)
        else:
            #print 'Pretty close'
            self.line = line(
                self.desired_position,
                tools.normal_vector_from_rotvec(self.desired_orientation) +
                self.desired_position)
Exemple #14
0
	def traj_cb(self, traj):
		# Timing
		now = rospy.get_rostime()
		dt = (now - self.last_time).to_sec()
		self.last_time = now

		# Get vectors related to the orientation of the trajectory
		o = tools.normal_vector_from_posetwist(traj.posetwist)
		#rospy.loginfo('o : ' + str(o))
		o_hat = o / np.linalg.norm(o)
		#rospy.loginfo('o hat: ' + str(o_hat))
		o_norm = np.cross([0, 0, -1], o_hat)
		#rospy.loginfo('o norm: ' + str(o_norm))

		# Overshoot = 1 if the boat is behind a line drawn perpendicular to the trajectory orientation
		#		and through the trajectories position, it is -1 if it is on the other side of the before mentioned line
		traj_position = tools.position_from_posetwist(traj.posetwist)
		boat_proj = line(traj_position, traj_position + o_hat).proj_pt(self.current_position)
		#rospy.loginfo('Boat_proj: ' + str(boat_proj))
		#rospy.loginfo('traj: ' + str(traj_position))
		#rospy.loginfo('traj - Boat_proj: ' + str(traj_position - boat_proj))
		boat_to_traj = traj_position - self.current_position
		boat_dist_to_traj = np.linalg.norm(boat_to_traj)
		boat_to_traj_hat = boat_to_traj / boat_dist_to_traj
		boat_to_traj_norm = np.cross([0,0,-1], boat_to_traj_hat)
		overshoot = np.dot(boat_to_traj_hat, o_hat)
		overshoot = overshoot / abs(overshoot)
		rospy.loginfo('overshoot: ' + str(overshoot))
		if math.isnan(overshoot):
			return

		# Method 2:
		#
		##		P error = - angle(between boat and trajectory)
		#
		#enu_angle_to_traj = np.arccos(boat_to_traj_hat, np.array([1, 0, 0])))
		#enu_angle_to_traj = math.copysign(enu_angle_to_traj, np.dot(boat_to_traj_norm, self.current_position))
		#boat_angle_to_traj = (self.current_orientation[2] - enu_angle_to_traj) % (np.pi)


		boat_orientation_vec = tools.normal_vector_from_rotvec(self.current_orientation)

		#angle_error = 0
		#torque_dir = 1
		if boat_dist_to_traj > self.orientation_radius:
			rospy.loginfo('Location: Outside orientation radius')
			# Is the angle to trajectory positive or negative ( dot product of two unit vectors is negative when the 
				# angle between them is greater than 90, by doting the orientation of the boat with a vector that is 90 degrees
				# to the trajectory and pointed to the right  we get positive numbers if we are pointed to the right and negative 
				# if we are on the left side)
			torque_dir = math.copysign(1, np.dot(boat_to_traj_norm, boat_orientation_vec))
								# angle between path to traj and boat orientation 			  		
			angle_error = np.arccos(np.dot(boat_orientation_vec, boat_to_traj_hat))
		else:
			rospy.loginfo('Location: Inside orientation radius')
			# Same as above but now we are orienting to the desired final orientation instead of towards the trajectory
			torque_dir = math.copysign(1, np.dot(o_norm, boat_orientation_vec))
								# Angle between traj_orientation and boat orientation
			angle_error = np.arccos(np.dot(boat_orientation_vec, o_hat))

		#rospy.loginfo('enu_angle_to_traj:\t' + str(enu_angle_to_traj * 180 / np.pi))
		#rospy.loginfo('Boat orientation:\t' + str(self.current_orientation[2] * 180 / np.pi))
		#rospy.loginfo('Boat angle to traj\t' + str((boat_angle_to_traj) * 180 / np.pi ))
		

		torque = angle_error * torque_dir * self.p
		force = traj.posetwist.twist.linear.x
		if boat_dist_to_traj < self.orientation_radius and overshoot == -1:
			rospy.loginfo('Status: Overshoot in orientation radius')
			force = force * -1
		elif abs(angle_error) > np.pi / 2:
			rospy.loginfo('Status: angle error > 90')
			force = 0
		else:
			rospy.loginfo('Status: Normal')

		rospy.loginfo('Angle error: ' + str(angle_error * torque_dir * 180 / np.pi))

		rospy.loginfo('torque: ' + str(torque))
		rospy.loginfo('Force: ' + str(force))

		""" Method 1:
		#
		##		P error = - perpendicular_velocity * p_gain * overshoot
		#
		# Velocity error = velocity perpendicular to trajectory orientation
		velocity_error = self.current_velocity - (np.dot(self.current_velocity, o_hat) * o_hat)
		v_dir = np.dot(velocity_error, o_norm)
		velocity_error = math.copysign(np.linalg.norm(velocity_error), v_dir)
		rospy.loginfo('V_perp = ' + str(velocity_error))
		velocity_error = -1 * velocity_error * self.p * overshoot
		rospy.loginfo('P error = ' + str(velocity_error))

		#
		##		I error = - position * i_gain * overshoot * ???
		#
		# Positional error
		#				boat_position		parralel portion of boat position
		pos_error = self.current_position - boat_proj
		p_dir = np.dot(pos_error, o_norm)
		pos_error = math.copysign(np.linalg.norm(pos_error), p_dir)
		rospy.loginfo('Perp_position = ' + str(pos_error))
		pos_error = -1 * pos_error * self.i * overshoot
		rospy.loginfo('I error = ' + str(pos_error))

		#
		##		D error
		#
		# Acceleration error
		acceleration_error = self.d * (velocity_error - self.last_perp_velocity) / dt
		self.last_perp_velocity = velocity_error

		torque = velocity_error + pos_error + acceleration_error


		# Reverse force if overshoot
		force = traj.posetwist.twist.linear.x * overshoot
		rospy.loginfo('torque: ' + str(torque))
		"""

		# Output a wrench!
		if not self.killed:
			self.wrench_pub.publish(
				WrenchStamped(
					header = Header(
						frame_id = '/base_link',
						stamp = now),
					wrench = Wrench(
						force = Vector3(force, 0, 0),
						torque = Vector3(0, 0, torque))))
		else:
			# Publish zero wrench
			self.wrench_pub.publish(WrenchStamped())
    def __init__(self, name):
        # Desired pose
        self.desired_position = self.current_position = np.zeros(3)
        self.desired_orientation = self.current_orientation = np.zeros(3)
        #self.desired_twist = self.current_twist = Twist()

        # Goal tolerances before seting succeded
        self.linear_tolerance = rospy.get_param('linear_tolerance', 0.5)
        self.angular_tolerance = rospy.get_param('angular_tolerance',
                                                 np.pi / 10)
        self.orientation_radius = rospy.get_param('orientation_radius', 0.75)
        self.slow_down_radius = rospy.get_param('slow_down_radius', 5)

        # Speed parameters
        self.max_tracking_distance = rospy.get_param('max_tracking_distance',
                                                     5)
        self.min_tracking_distance = rospy.get_param('min_tracking_distance',
                                                     1)
        self.tracking_to_speed_conv = rospy.get_param('tracking_to_speed_conv',
                                                      1)
        self.tracking_slope = (
            self.max_tracking_distance - self.min_tracking_distance) / (
                self.slow_down_radius - self.orientation_radius)
        self.tracking_intercept = self.tracking_slope * self.orientation_radius + self.min_tracking_distance

        # Publishers
        self.traj_pub = rospy.Publisher('/trajectory',
                                        PoseTwistStamped,
                                        queue_size=10)

        # Set desired twist to 0
        #self.desired_twist.linear.x = self.desired_twist.linear.y = self.desired_twist.linear.z = 0
        #self.desired_twist.angular.x = self.desired_twist.angular.y = self.desired_twist.angular.z = 0

        # Initilize a line
        self.line = line(np.zeros(3), np.ones(3))

        # Wait for current position and set as desired position
        rospy.loginfo('Waiting for /odom')
        self.odom_sub = rospy.Subscriber('/odom',
                                         Odometry,
                                         self.odom_cb,
                                         queue_size=10)
        while not self.current_position.any(
        ):  # Will be 0 until an odom publishes (if its still 0 it will drift very very soon)
            pass

        # Initlize Trajectory generator with current position as goal
        # 	Set the line to be along our current orientation
        self.desired_position = self.current_position
        self.desired_orientation = self.current_orientation
        # 	Make a line along the orientation
        self.line = line(
            self.current_position,
            tools.normal_vector_from_rotvec(self.current_orientation) +
            self.current_position)
        self.redraw_line = False
        rospy.loginfo('Got current pose from /odom')

        # Kill handling
        self.killed = False
        self.kill_listener = KillListener(self.set_kill, self.clear_kill)
        self.kill_broadcaster = KillBroadcaster(
            id=name, description='Tank steer trajectory_generator shutdown')
        try:
            self.kill_broadcaster.clear()  # In case previously killed
        except rospy.service.ServiceException, e:
            rospy.logwarn(str(e))
    def traj_cb(self, traj):
        # Timing
        now = rospy.get_rostime()
        dt = (now - self.last_time).to_sec()
        self.last_time = now

        # Get vectors related to the orientation of the trajectory
        o = tools.normal_vector_from_posetwist(traj.posetwist)
        #rospy.loginfo('o : ' + str(o))
        o_hat = o / np.linalg.norm(o)
        #rospy.loginfo('o hat: ' + str(o_hat))
        o_norm = np.cross([0, 0, -1], o_hat)
        #rospy.loginfo('o norm: ' + str(o_norm))

        # Overshoot = 1 if the boat is behind a line drawn perpendicular to the trajectory orientation
        #		and through the trajectories position, it is -1 if it is on the other side of the before mentioned line
        traj_position = tools.position_from_posetwist(traj.posetwist)
        boat_proj = line(traj_position,
                         traj_position + o_hat).proj_pt(self.current_position)
        #rospy.loginfo('Boat_proj: ' + str(boat_proj))
        #rospy.loginfo('traj: ' + str(traj_position))
        #rospy.loginfo('traj - Boat_proj: ' + str(traj_position - boat_proj))
        boat_to_traj = traj_position - self.current_position
        boat_dist_to_traj = np.linalg.norm(boat_to_traj)
        boat_to_traj_hat = boat_to_traj / boat_dist_to_traj
        boat_to_traj_norm = np.cross([0, 0, -1], boat_to_traj_hat)
        overshoot = np.dot(boat_to_traj_hat, o_hat)
        overshoot = overshoot / abs(overshoot)
        rospy.loginfo('overshoot: ' + str(overshoot))
        if math.isnan(overshoot):
            return

        # Method 2:
        #
        ##		P error = - angle(between boat and trajectory)
        #
        #enu_angle_to_traj = np.arccos(boat_to_traj_hat, np.array([1, 0, 0])))
        #enu_angle_to_traj = math.copysign(enu_angle_to_traj, np.dot(boat_to_traj_norm, self.current_position))
        #boat_angle_to_traj = (self.current_orientation[2] - enu_angle_to_traj) % (np.pi)

        boat_orientation_vec = tools.normal_vector_from_rotvec(
            self.current_orientation)

        #angle_error = 0
        #torque_dir = 1
        if boat_dist_to_traj > self.orientation_radius:
            rospy.loginfo('Location: Outside orientation radius')
            # Is the angle to trajectory positive or negative ( dot product of two unit vectors is negative when the
            # angle between them is greater than 90, by doting the orientation of the boat with a vector that is 90 degrees
            # to the trajectory and pointed to the right  we get positive numbers if we are pointed to the right and negative
            # if we are on the left side)
            torque_dir = math.copysign(
                1, np.dot(boat_to_traj_norm, boat_orientation_vec))
            # angle between path to traj and boat orientation
            angle_error = np.arccos(
                np.dot(boat_orientation_vec, boat_to_traj_hat))
        else:
            rospy.loginfo('Location: Inside orientation radius')
            # Same as above but now we are orienting to the desired final orientation instead of towards the trajectory
            torque_dir = math.copysign(1, np.dot(o_norm, boat_orientation_vec))
            # Angle between traj_orientation and boat orientation
            angle_error = np.arccos(np.dot(boat_orientation_vec, o_hat))

        #rospy.loginfo('enu_angle_to_traj:\t' + str(enu_angle_to_traj * 180 / np.pi))
        #rospy.loginfo('Boat orientation:\t' + str(self.current_orientation[2] * 180 / np.pi))
        #rospy.loginfo('Boat angle to traj\t' + str((boat_angle_to_traj) * 180 / np.pi ))

        torque = angle_error * torque_dir * self.p
        force = traj.posetwist.twist.linear.x
        if boat_dist_to_traj < self.orientation_radius and overshoot == -1:
            rospy.loginfo('Status: Overshoot in orientation radius')
            force = force * -1
        elif abs(angle_error) > np.pi / 2:
            rospy.loginfo('Status: angle error > 90')
            force = 0
        else:
            rospy.loginfo('Status: Normal')

        rospy.loginfo('Angle error: ' +
                      str(angle_error * torque_dir * 180 / np.pi))

        rospy.loginfo('torque: ' + str(torque))
        rospy.loginfo('Force: ' + str(force))
        """ Method 1:
		#
		##		P error = - perpendicular_velocity * p_gain * overshoot
		#
		# Velocity error = velocity perpendicular to trajectory orientation
		velocity_error = self.current_velocity - (np.dot(self.current_velocity, o_hat) * o_hat)
		v_dir = np.dot(velocity_error, o_norm)
		velocity_error = math.copysign(np.linalg.norm(velocity_error), v_dir)
		rospy.loginfo('V_perp = ' + str(velocity_error))
		velocity_error = -1 * velocity_error * self.p * overshoot
		rospy.loginfo('P error = ' + str(velocity_error))

		#
		##		I error = - position * i_gain * overshoot * ???
		#
		# Positional error
		#				boat_position		parralel portion of boat position
		pos_error = self.current_position - boat_proj
		p_dir = np.dot(pos_error, o_norm)
		pos_error = math.copysign(np.linalg.norm(pos_error), p_dir)
		rospy.loginfo('Perp_position = ' + str(pos_error))
		pos_error = -1 * pos_error * self.i * overshoot
		rospy.loginfo('I error = ' + str(pos_error))

		#
		##		D error
		#
		# Acceleration error
		acceleration_error = self.d * (velocity_error - self.last_perp_velocity) / dt
		self.last_perp_velocity = velocity_error

		torque = velocity_error + pos_error + acceleration_error


		# Reverse force if overshoot
		force = traj.posetwist.twist.linear.x * overshoot
		rospy.loginfo('torque: ' + str(torque))
		"""

        # Output a wrench!
        if not self.killed:
            self.wrench_pub.publish(
                WrenchStamped(header=Header(frame_id='/base_link', stamp=now),
                              wrench=Wrench(force=Vector3(force, 0, 0),
                                            torque=Vector3(0, 0, torque))))
        else:
            # Publish zero wrench
            self.wrench_pub.publish(WrenchStamped())