Skip to content
Snippets Groups Projects
coverage_server.py 8.46 KiB
#!/usr/bin/env python
import rospy
import actionlib
import autonomous_offboard.msg
import numpy as np
import time
import math
from geometry_msgs.msg import PoseStamped, Point
from std_msgs.msg import Float32
from autonomous_offboard.msg import detect_objectAction, detect_objectGoal, goto_position_velAction, goto_position_velGoal


class coverage_server():

    def __init__(self):
        # variables
        self.cur_pose = PoseStamped()
        self.waypoints = np.empty((0,3))
        self.destination = PoseStamped()
        self.angleOfViewWidth = 37.0
        self.angleOfViewHeight = 47.0
        self.areaWidth = 20.0
        self.areaHeight = 20.0
        self.searchHeight = 10.0
        self.detectedPos = PoseStamped()
        self.detectedPos.pose.position.x = float("inf")
        self.result = autonomous_offboard.msg.coverageResult()
        rospy.Subscriber('/tensorflow_detection/cam_point', Point, self.detection_callback)
        rospy.Subscriber('/mavros/local_position/pose', PoseStamped, self.cur_pose_cb)

        self.set_xy_vel = rospy.Publisher('/position_control/set_xy_vel', Float32, queue_size=10)
        self.position_publisher = rospy.Publisher('/coverage_server/position', PoseStamped, queue_size=10)

        self.goto_position_client = actionlib.SimpleActionClient('goto_position_vel', goto_position_velAction)
        #self.detect_object_client = actionlib.SimpleActionClient('detect_object', detect_objectAction)
        self.rate = rospy.Rate(20)
        self.action_server = actionlib.SimpleActionServer('coverage',
                                                          autonomous_offboard.msg.coverageAction,
                                                          execute_cb=self.execute_cb, auto_start=False)
        self.action_server.start()

    def execute_cb(self, goal):
        xyVel = Float32()
        xyVel.data = 1
        self.set_xy_vel.publish(xyVel)
        goto_position_goal = goto_position_velGoal()
        goto_position_goal.destination.pose.orientation.w = 0.707
        goto_position_goal.destination.pose.orientation.z = 0.707
        self.goto_position_client.wait_for_server()
        #self.detect_object_client.wait_for_server()
        self.destination = goal.destination
        self.calculate_waypoints2()
        idx= 0
        while(self.detectedPos.pose.position.x == float("inf")):
            goto_position_goal.destination.pose.position.x = self.waypoints.item((idx, 0))
            goto_position_goal.destination.pose.position.y = self.waypoints.item((idx, 1))
            goto_position_goal.destination.pose.position.z = self.waypoints.item((idx, 2))
            self.position_publisher.publish(self.cur_pose)
            self.goto_position_client.send_goal(goto_position_goal)
            self.goto_position_client.wait_for_result()
            idx = idx + 1
            if idx == self.waypoints.shape[0] or self.detectedPos.pose.position.x != float("inf"):
                idx = 0
                self.result.detected_object_pos = self.detectedPos
                self.result.detected_object_pos.pose.position.z = self.searchHeight
                self.action_server.set_succeeded(self.result)

            #detect_object_goal = detect_objectGoal()
            #self.detect_object_client.send_goal(detect_object_goal)
            #self.detect_object_client.wait_for_result()
            #self.detectedPos = self.detect_object_client.get_result().detected_position
            time.sleep(0.1)





    #calculate waypoints
    def calculate_waypoints(self):
        cameraWidth = 2 * self.searchHeight * math.tan(math.radians(self.angleOfViewWidth/2.0))
        cameraHeight = 2 * self.searchHeight * math.tan(math.radians(self.angleOfViewHeight/2.0))
        lastWaypoint = PoseStamped()
        lastWaypoint.pose.position.x = self.destination.pose.position.x - self.areaWidth/2.0
        lastWaypoint.pose.position.y = self.destination.pose.position.y - self.areaHeight / 2.0
        lastWaypoint.pose.position.z = self.searchHeight
        tempArr = []
        tempArr.append([lastWaypoint.pose.position.x, lastWaypoint.pose.position.y, lastWaypoint.pose.position.z])
        while(lastWaypoint.pose.position.x + cameraWidth/2.0 < self.destination.pose.position.x + self.areaWidth/2.0):
            #check if going upwards or downwards
            if(cameraHeight > 0):
                while(lastWaypoint.pose.position.y + cameraHeight/2.0 < self.destination.pose.position.y + self.areaHeight/2.0):
                    lastWaypoint.pose.position.y = lastWaypoint.pose.position.y + cameraHeight
                    tempArr.append([lastWaypoint.pose.position.x, lastWaypoint.pose.position.y, lastWaypoint.pose.position.z])
            elif(cameraHeight < 0):
                while (lastWaypoint.pose.position.y + cameraHeight / 2.0 > self.destination.pose.position.y - self.areaHeight / 2.0):
                    lastWaypoint.pose.position.y = lastWaypoint.pose.position.y + cameraHeight
                    tempArr.append([lastWaypoint.pose.position.x, lastWaypoint.pose.position.y, lastWaypoint.pose.position.z])

            cameraHeight= cameraHeight*(-1) #make it change direction for zig-zag pattern
            lastWaypoint.pose.position.x = lastWaypoint.pose.position.x + cameraWidth
            tempArr.append([lastWaypoint.pose.position.x, lastWaypoint.pose.position.y, lastWaypoint.pose.position.z])

        self.waypoints = np.asarray(tempArr)
        rospy.loginfo(self.waypoints)

    def calculate_waypoints2(self):
        tempArr = []
        self.cameraWidth = 2.0 * self.searchHeight * math.tan(math.radians(self.angleOfViewWidth / 2.0))
        self.cameraHeight = 2.0 * self.searchHeight * math.tan(math.radians(self.angleOfViewHeight / 2.0))
        startPointX = self.destination.pose.position.x - self.areaWidth / 2.0 + self.cameraWidth / 2.0
        startPointY = self.destination.pose.position.y - self.areaHeight / 2.0 + self.cameraHeight / 2.0
        self.nrOfStepsHeight = int(math.floor(self.areaHeight / self.cameraHeight))
        self.nrOfStepsWidth = int(math.floor(self.areaWidth / self.cameraWidth))

        tempArr.append([startPointX, startPointY, self.searchHeight])

        for i in range(0, self.nrOfStepsWidth):
            for j in range(0, self.nrOfStepsHeight):

                if j == self.nrOfStepsHeight - 1:
                    _last_steplength = self.areaHeight - abs(self.nrOfStepsHeight * self.cameraHeight)
                    if self.cameraHeight > 0:
                        tempArr.append([0, _last_steplength, self.searchHeight])
                    else:
                        tempArr.append([0, -_last_steplength, self.searchHeight])
                else:
                    tempArr.append([0, self.cameraHeight, self.searchHeight])
            if i == self.nrOfStepsWidth-1:
                self.cameraHeight = self.cameraHeight * (-1)  # make it change direction for zig-zag pattern
                _last_steplength = self.areaHeight - abs(self.nrOfStepsWidth * self.cameraWidth)
                if self.cameraWidth > 0:
                    tempArr.append([_last_steplength, 0, self.searchHeight])
                else:
                    tempArr.append([-_last_steplength, 0, self.searchHeight])
                for j in range(0, self.nrOfStepsHeight):

                    if j == self.nrOfStepsHeight - 1:
                        _last_steplength = self.areaHeight - abs(self.nrOfStepsHeight * self.cameraHeight)
                        if self.cameraHeight > 0:
                            tempArr.append([0, _last_steplength, self.searchHeight])
                        else:
                            tempArr.append([0, -_last_steplength, self.searchHeight])
                    else:
                        tempArr.append([0, self.cameraHeight, self.searchHeight])


            elif i != self.nrOfStepsWidth:
                self.cameraHeight = self.cameraHeight * (-1)  # make it change direction for zig-zag pattern
                tempArr.append([self.cameraWidth, 0, self.searchHeight])

        self.waypoints = np.asarray(tempArr)
        rospy.loginfo(self.waypoints)

    def detection_callback(self, data):
        if (data.x != float("inf")):
            self.detectedPos = self.cur_pose
            self.detectedPos.pose.position.x = self.detectedPos.pose.position.x + data.x
            self.detectedPos.pose.position.y = self.detectedPos.pose.position.y + data.y

    def cur_pose_cb(self, data):
        self.cur_pose = data
if __name__ == '__main__':
    try:

        rospy.init_node('coverage_server')
        coverage_server()
    except rospy.ROSInterruptException:
        pass