Ejemplo n.º 1
0
 def __init__(self):
     self.goal_x = 0
     self.goal_y = 0
     self.heading = 0
     self.initGoal = True
     self.get_goalbox = False
     self.position = Pose()
     self.pub_cmd_vel = rospy.Publisher('cmd_vel', Twist, queue_size=5)
     self.sub_odom = rospy.Subscriber('odom', Odometry, self.getOdometry)
     self.reset_proxy = rospy.ServiceProxy('gazebo/reset_simulation', Empty)
     self.unpause_proxy = rospy.ServiceProxy('gazebo/unpause_physics', Empty)
     self.pause_proxy = rospy.ServiceProxy('gazebo/pause_physics', Empty)
     self.respawn_goal = Respawn()
     self.past_distance = 0.
     self.stopped = 0
     #Keys CTRL + c will stop script
     rospy.on_shutdown(self.shutdown)
Ejemplo n.º 2
0
class Env():
    def __init__(self, linear_velocity=0.15):
        self.goal_x = 0
        self.goal_y = 0
        self.heading = 0
        self.initGoal = True
        self.get_goalbox = False
        self.position = Pose()
        self.pub_cmd_vel = rospy.Publisher('cmd_vel', Twist, queue_size=5)
        self.sub_odom = rospy.Subscriber('odom', Odometry, self.getOdometry)
        self.reset_proxy = rospy.ServiceProxy('gazebo/reset_simulation', Empty)
        self.unpause_proxy = rospy.ServiceProxy('gazebo/unpause_physics',
                                                Empty)
        self.pause_proxy = rospy.ServiceProxy('gazebo/pause_physics', Empty)
        self.respawn_goal = Respawn()
        self.past_distance = 0.
        self.stopped = 0
        self.linear_velocity = linear_velocity
        #Keys CTRL + c will stop script
        rospy.on_shutdown(self.shutdown)

    def shutdown(self):
        #---you can stop turtlebot by publishing an empty Twist message---#
        rospy.loginfo("Stopping TurtleBot")
        self.pub_cmd_vel.publish(Twist())
        rospy.sleep(1)

    def getGoalDistance(self):
        goal_distance = round(
            math.hypot(self.goal_x - self.position.x,
                       self.goal_y - self.position.y), 2)
        self.past_distance = goal_distance

        return goal_distance

    def getOdometry(self, odom):
        self.past_position = copy.deepcopy(self.position)
        self.position = odom.pose.pose.position
        orientation = odom.pose.pose.orientation
        orientation_list = [
            orientation.x, orientation.y, orientation.z, orientation.w
        ]
        _, _, yaw = euler_from_quaternion(orientation_list)

        goal_angle = math.atan2(self.goal_y - self.position.y,
                                self.goal_x - self.position.x)

        heading = goal_angle - yaw

        if heading > pi:
            heading -= 2 * pi

        elif heading < -pi:
            heading += 2 * pi

        self.heading = round(heading, 3)

    def getState(self, scan):
        scan_range = []
        heading = self.heading
        min_range = 0.135
        done = False

        for i in range(len(scan.ranges)):
            if scan.ranges[i] == float('Inf'):
                scan_range.append(3.5)
            elif np.isnan(scan.ranges[i]):
                scan_range.append(0)
            else:
                scan_range.append(scan.ranges[i])

        if min_range > min(scan_range) > 0:
            done = True

        current_distance = round(
            math.hypot(self.goal_x - self.position.x,
                       self.goal_y - self.position.y), 2)
        if current_distance < 0.2:
            self.get_goalbox = True

        return scan_range + [heading, current_distance], done

    def setReward(self, state, done):

        current_distance = state[-1]
        heading = state[-2]

        distance_rate = (self.past_distance - current_distance)
        if distance_rate > 0:
            # reward = 200.*distance_rate
            reward = 1.

        if distance_rate <= 0:
            # reward = -8.
            reward = 0.

        self.past_distance = current_distance

        a, b, c, d = float('{0:.3f}'.format(self.position.x)), float(
            '{0:.3f}'.format(self.past_position.x)), float('{0:.3f}'.format(
                self.position.y)), float('{0:.3f}'.format(
                    self.past_position.y))
        if a == b and c == d:
            self.stopped += 1
            if self.stopped == 20:
                rospy.loginfo('Robot is in the same 20 times in a row')
                self.stopped = 0
                done = True
        else:
            self.stopped = 0

        if done:
            rospy.loginfo("Collision!!")
            # reward = -550.
            reward = -10.
            self.pub_cmd_vel.publish(Twist())

        if self.get_goalbox:
            rospy.loginfo("Goal!!")
            # reward = 500.
            reward = 100.
            self.pub_cmd_vel.publish(Twist())
            if world:
                self.goal_x, self.goal_y = self.respawn_goal.getPosition(
                    True, delete=True, running=True)
                if target_not_movable:
                    self.reset()
            else:
                self.goal_x, self.goal_y = self.respawn_goal.getPosition(
                    True, delete=True)
            self.goal_distance = self.getGoalDistance()
            self.get_goalbox = False

        return reward, done

    def step(self, action):
        ang_vel = action
        vel_cmd = Twist()
        vel_cmd.linear.x = self.linear_velocity
        vel_cmd.angular.z = ang_vel
        # print('action: ' + str(vel_cmd.linear.x) + ' m/s and ' + str(vel_cmd.angular.z) + ' rad/s')
        self.pub_cmd_vel.publish(vel_cmd)

        data = None
        while data is None:
            try:
                data = rospy.wait_for_message('scan', LaserScan, timeout=5)
            except:
                pass

        state, done = self.getState(data)
        reward, done = self.setReward(state, done)

        return np.asarray(state), reward, done

    def reset(self):

        rospy.wait_for_service('gazebo/reset_simulation')
        try:
            self.reset_proxy()
        except (rospy.ServiceException) as e:
            print("gazebo/reset_simulation service call failed")

        data = None
        while data is None:
            try:
                data = rospy.wait_for_message('scan', LaserScan, timeout=5)
            except:
                pass

        if self.initGoal:
            self.goal_x, self.goal_y = self.respawn_goal.getPosition()
            self.initGoal = False
        else:
            self.goal_x, self.goal_y = self.respawn_goal.getPosition(
                True, delete=True)

        self.goal_distance = self.getGoalDistance()
        state, _ = self.getState(data)

        return np.asarray(state)