예제 #1
0
class Run:
    def __init__(self, factory):
        """Constructor.

        Args:
            factory (factory.FactoryCreate)
        """
        self.create = factory.create_create()
        self.time = factory.create_time_helper()
        self.servo = factory.create_servo()
        self.sonar = factory.create_sonar()
        # Add the IP-address of your computer here if you run on the robot
        self.virtual_create = factory.create_virtual_create()
        self.pdTheta = pd_controller.PDController(500, 40, -200, 200)
        self.pidTheta = pid_controller.PIDController(200,
                                                     5,
                                                     50, [-10, 10],
                                                     [-200, 200],
                                                     is_angle=True)
        self.map = lab8_map.Map("lab8_map.json")
        self.base_speed = 100
        self.odometry = odometry.Odometry()
        self.particle_filter = ParticleFilter(
            map=self.map,
            virtual_create=self.virtual_create,
            num_particles=100,
            distance=STRAIGHT_DISTANCE,
            sigma_sensor=0.1,
            sigma_theta=0.05,
            sigma_distance=0.01,
        )
        _ = self.create.sim_get_position()

    def run(self):
        self.create.start()
        self.create.safe()

        # request sensors
        self.create.start_stream([
            create2.Sensor.LeftEncoderCounts,
            create2.Sensor.RightEncoderCounts,
        ])
        # This is an example on how to visualize the pose of our estimated position
        # where our estimate is that the robot is at (x,y,z)=(0.5,0.5,0.1) with heading pi
        # self.virtual_create.set_pose((0.5, 0.5, 0.1), 0)

        # This is an example on how to show particles
        # the format is x,y,z,theta,x,y,z,theta,...
        # data = [0.5, 0.5, 0.1, math.pi / 2, 1.5, 1, 0.1, 0]
        # self.virtual_create.set_point_cloud(data)

        # This is an example on how to estimate the distance to a wall for the given
        # map, assuming the robot is at (0, 0) and has heading math.pi
        # print(self.map.closest_distance((0.5, 0.5), 0))
        self.particle_filter.draw_particles()

        # This is an example on how to detect that a button was pressed in V-REP
        while True:
            # self.particle_filter.draw_particles()
            b = self.virtual_create.get_last_button()
            if b == self.virtual_create.Button.MoveForward:
                self.forward(STRAIGHT_DISTANCE)
                self.particle_filter.movement(Command.straight, 0)
                # print("Forward pressed!")
            elif b == self.virtual_create.Button.TurnLeft:
                desired_angle = math.pi / 2
                # desired_angle %= 2 * math.pi
                self.particle_filter.movement(Command.turn_left, desired_angle)
                self.sleep(0.01)
                self.turn_left()

                # self.go_to_angle(self.odometry.theta+math.pi/2)
                # print("Turn Left pressed!")
            elif b == self.virtual_create.Button.TurnRight:
                desired_angle = -math.pi / 2
                # desired_angle %= 2 * math.pi
                self.particle_filter.movement(Command.turn_right,
                                              desired_angle)
                self.sleep(0.01)
                self.turn_right()

                # self.go_to_angle(self.odometry.theta-math.pi/2)
                # print("Turn Right pressed!")
            elif b == self.virtual_create.Button.Sense:
                distance = self.sonar.get_distance()
                self.particle_filter.sensing(distance)

            self.sleep(0.01)

    # def go_to_angle(self, goal_theta):
    #     while math.fabs(math.atan2(
    #             math.sin(goal_theta - self.odometry.theta),
    #             math.cos(goal_theta - self.odometry.theta))) > 0.01:
    #         output_theta = self.pidTheta.update(self.odometry.theta, goal_theta, self.time.time())
    #         self.create.drive_direct(+output_theta, -output_theta)
    #         self.update_odometry()
    #     self.create.drive_direct(0, 0)

    def turn_left(self):
        self.create.drive_direct(self.base_speed, -self.base_speed)
        current_theta = self.odometry.theta
        while abs(
                math.degrees(current_theta) -
                math.degrees(self.odometry.theta)) < 90:
            self.update_odometry()
        self.create.drive_direct(0, 0)

    def turn_right(self):
        self.create.drive_direct(int(-self.base_speed), int(self.base_speed))
        current_theta = self.odometry.theta
        while abs(
                math.degrees(current_theta) -
                math.degrees(self.odometry.theta)) < 90:
            self.update_odometry()
        self.create.drive_direct(0, 0)

    def forward(self, distance):
        self.create.drive_direct(int(self.base_speed), int(self.base_speed))
        self.sleep(distance / (self.base_speed / 1000))
        self.create.drive_direct(0, 0)

    def sleep(self, time_in_sec):
        """Sleeps for the specified amount of time while keeping odometry up-to-date
        Args:
            time_in_sec (float): time to sleep in seconds
        """
        start = self.time.time()
        while True:
            state = self.create.update()
            if state is not None:
                self.odometry.update(state.leftEncoderCounts,
                                     state.rightEncoderCounts)
            t = self.time.time()
            if start + time_in_sec <= t:
                break

    def update_odometry(self):
        state = self.create.update()
        if state is not None:
            self.odometry.update(state.leftEncoderCounts,
                                 state.rightEncoderCounts)
예제 #2
0
class Run:
    def __init__(self, factory):
        """Constructor.

        Args:
            factory (factory.FactoryCreate)
        """
        self.create = factory.create_create()
        self.time = factory.create_time_helper()
        self.servo = factory.create_servo()
        self.sonar = factory.create_sonar()
        # Add the IP-address of your computer here if you run on the robot
        self.virtual_create = factory.create_virtual_create()
        self.map = lab8_map.Map("lab8_map.json")
        self.robot = MyRobot(self.create, self.time, base_speed=0.1)
        self.odometry = odometry.Odometry()

    def run(self):
        self.create.start()
        self.create.safe()

        self.create.start_stream([
            create2.Sensor.LeftEncoderCounts,
            create2.Sensor.RightEncoderCounts,
        ])
        # This is an example on how to visualize the pose of our estimated position
        # where our estimate is that the robot is at (x,y,z)=(0.5,0.5,0.1) with heading pi
        # self.virtual_create.set_pose((0.5, 0.5, 0.1), 0)

        origin = (0.5, 0.5, 0.1, 0)             # partical origin
        noise = (0.01, 0.05, 0.1)     # sd for (distance, theta, sonar)
        
        self.odometry.x = origin[0]
        self.odometry.y = origin[1]

        self.pf = ParticleFilter(origin, noise, 1000, self.map)
        self.virtual_create.set_point_cloud(self.pf.get_particle_list())

        # This is an example on how to show particles
        # the format is x,y,z,theta,x,y,z,theta,...
        # data = [0.5, 0.5, 0.1, math.pi/2, 1.5, 1, 0.1, 0]
        # self.virtual_create.set_point_cloud(data)

        # This is an example on how to estimate the distance to a wall for the given
        # map, assuming the robot is at (0, 0) and has heading math.pi
        # print(self.map.closest_distance((0.5,0.5), 0))

        # self.positioning()
        # This is an example on how to detect that a button was pressed in V-REP
        while True:
            b = self.virtual_create.get_last_button()
            if b == self.virtual_create.Button.MoveForward:
                self.forward()
            elif b == self.virtual_create.Button.TurnLeft:
                self.turn_left()
            elif b == self.virtual_create.Button.TurnRight:
                self.turn_right()
            elif b == self.virtual_create.Button.Sense:
                self.sense()
            self.time.sleep(0.01)


    def forward(self):
        print("Forward pressed!")
        FORWARD_DISTANCE = 0.5
        self.robot.forward(FORWARD_DISTANCE)
        self.robot.stop()
        self.pf.movement(FORWARD_DISTANCE, 0)
        self.virtual_create.set_point_cloud(self.pf.get_particle_list())
        self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)

    def turn_left(self):
        print("Turn Left pressed!")
        self.robot.turn_left(1.8)
        self.robot.stop()
        self.pf.movement(0, math.pi/2)
        self.virtual_create.set_point_cloud(self.pf.get_particle_list())
        self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)

    def turn_right(self):
        print("Turn Right pressed!")
        self.robot.turn_right(1.8)
        self.robot.stop()
        self.pf.movement(0, -math.pi/2)
        self.virtual_create.set_point_cloud(self.pf.get_particle_list())
        self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)

    def sense(self):
        print("Sense pressed!")
        self.pf.sensing(self.sonar.get_distance())
        self.virtual_create.set_point_cloud(self.pf.get_particle_list())
        self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)

    def positioning(self):
        for _ in range(21):
            self.robot.turn_left(0.3)
            self.robot.stop()
            self.pf.movement(0, math.pi/12)
            self.virtual_create.set_point_cloud(self.pf.get_particle_list())
            self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)
            self.pf.sensing(self.sonar.get_distance())
            self.virtual_create.set_point_cloud(self.pf.get_particle_list())
            self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)
예제 #3
0
class Run:
    def __init__(self, factory):
        """Constructor.

        Args:
            factory (factory.FactoryCreate)
        """
        self.create = factory.create_create()
        self.time = factory.create_time_helper()
        self.servo = factory.create_servo()
        self.sonar = factory.create_sonar()
        # Add the IP-address of your computer here if you run on the robot
        self.virtual_create = factory.create_virtual_create()
        self.map = lab8_map.Map("lab8_map.json")
        self.robot = MyRobot(self.create, self.time, base_speed=0.1)
        self.odometry = odometry.Odometry()
        self.travel_dist = 0.4
        self.current_dist_to_wall = 0
        self.base_speed = 100

        self.min_dist_to_wall = self.travel_dist + 0.2
        self.min_dist_to_localize = 0.45
        self.min_theta_to_localize = math.pi / 4
        _ = self.create.sim_get_position()

    def run(self):
        self.create.start()
        self.create.safe()

        self.create.start_stream([
            create2.Sensor.LeftEncoderCounts,
            create2.Sensor.RightEncoderCounts,
        ])
        # This is an example on how to visualize the pose of our estimated position
        # where our estimate is that the robot is at (x,y,z)=(0.5,0.5,0.1) with heading pi
        # self.virtual_create.set_pose((0.5, 0.5, 0.1), 0)

        origin = (0.5, 0.5, 0.1, 0)  # partical origin
        noise = (0.01, 0.05, 0.1)  # sd for (distance, theta, sonar)

        self.odometry.x = origin[0]
        self.odometry.y = origin[1]

        self.pf = ParticleFilter(origin, noise, 5000, self.map)
        self.virtual_create.set_point_cloud(self.pf.get_particle_list())

        self.virtual_create.set_point_cloud(self.pf.get_particle_list())
        self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)

        self.turn_left()
        self.turn_left()

        self.forward()
        self.turn_right()
        self.sense()

        for angle in range(90, 360, 90):
            print("angle, ", angle)
            print("math_radians, ", math.radians(angle))
            self.turn_left()
            self.sense()

        self.go_to_angle(0, 1)

        self.sense()
        self.forward()

        current_angle = 100
        self.turn_left_degrees(current_angle)
        breakNextTime = False
        for angle in range(current_angle, 0, -20):
            self.turn_right_degrees(20)
            current_angle -= 20
            self.sense()
            if breakNextTime:
                break

            if self.isLocalized():
                self.robot.stop()
                return

            if self.isThetaLocalizaed():
                breakNextTime = True

        if self.isLocalized():
            self.robot.stop()
            return

        self.go_to_angle(0, 1)
        if current_angle < 0:
            self.turn_left_degrees(current_angle, speed=50)
        else:
            self.turn_right_degrees(current_angle, speed=50)

        if self.isLocalized():
            self.robot.stop()
            return

        self.forward()
        self.sense()

        # Pretty sure here is localized
        self.min_dist_to_localize += 0.15
        if self.isLocalized():
            self.robot.stop()
            return
        self.forward()
        if self.isLocalized():
            self.robot.stop()
            return
        while True:
            command = random.choice([c for c in Command])
            print(command)
            self.current_dist_to_wall = self.sonar.get_distance()
            if command is Command.FORWARD:
                for angle in range(-50, 50, 25):
                    self.go_to_angle(angle, 2)
                    self.current_dist_to_wall = self.sonar.get_distance()
                    if self.current_dist_to_wall < 0.75:
                        self.go_to_angle(0, 1)
                        break
                self.go_to_angle(0, 1)
                self.forward()
            elif command is Command.TURN_LEFT:
                self.turn_left()
                self.current_dist_to_wall = self.sonar.get_distance()
                if self.current_dist_to_wall < 0.75:
                    self.turn_right()
                    continue
            elif command is Command.TURN_RIGHT:
                self.turn_right()
                self.current_dist_to_wall = self.sonar.get_distance()
                if self.current_dist_to_wall < 0.75:
                    self.turn_right()
                    continue

            self.sense()
            self.time.sleep(0.01)

            if self.isLocalized():
                self.robot.stop()
                return

    def sleep(self, time_in_sec):
        start = self.time.time()
        while True:
            self.update_odometry()
            t = self.time.time()
            if start + time_in_sec <= t:
                break

    def go_to_angle(self, angle: float = 0, sleep_time: float = 0.5):
        self.servo.go_to(angle)
        return self.sleep(sleep_time)

    def turn_left(self):
        self.pf.movement(0, math.pi / 2)
        self.virtual_create.set_point_cloud(self.pf.get_particle_list())
        self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)
        self.create.drive_direct(self.base_speed, -self.base_speed)
        current_theta = self.odometry.theta
        while abs(
                math.degrees(current_theta) -
                math.degrees(self.odometry.theta)) < 90:
            self.update_odometry()
        self.create.drive_direct(0, 0)

    def turn_right(self):
        self.pf.movement(0, -math.pi / 2)
        self.virtual_create.set_point_cloud(self.pf.get_particle_list())
        self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)
        self.create.drive_direct(int(-self.base_speed), int(self.base_speed))
        current_theta = self.odometry.theta
        while abs(
                math.degrees(current_theta) -
                math.degrees(self.odometry.theta)) < 90:
            self.update_odometry()
        self.create.drive_direct(0, 0)

    def turn_left_degrees(self, degrees, speed=80):
        self.pf.movement(0, math.radians(degrees))
        self.virtual_create.set_point_cloud(self.pf.get_particle_list())
        self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)
        self.create.drive_direct(speed, -speed)
        current_theta = self.odometry.theta
        while abs(
                math.degrees(current_theta) -
                math.degrees(self.odometry.theta)) < degrees:
            self.update_odometry()
        self.create.drive_direct(0, 0)

    def turn_right_degrees(self, degrees, speed=None):
        if speed is None:
            speed = self.base_speed
        self.pf.movement(0, -math.radians(degrees))
        self.virtual_create.set_point_cloud(self.pf.get_particle_list())
        self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)
        self.create.drive_direct(-self.base_speed, self.base_speed)
        current_theta = self.odometry.theta
        while abs(
                math.degrees(current_theta) -
                math.degrees(self.odometry.theta)) < degrees:
            self.update_odometry()
        self.create.drive_direct(0, 0)

    def forward(self):
        FORWARD_DISTANCE = 0.5
        self.pf.movement(FORWARD_DISTANCE, 0)
        self.virtual_create.set_point_cloud(self.pf.get_particle_list())
        self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)
        self.create.drive_direct(int(self.base_speed), int(self.base_speed))
        self.sleep(FORWARD_DISTANCE / (self.base_speed / 1000))
        self.create.drive_direct(0, 0)

    def sense(self, replace=True):
        print("Sense executed!")
        self.current_dist_to_wall = self.sonar.get_distance()
        self.pf.sensing(self.current_dist_to_wall, replace)
        self.virtual_create.set_point_cloud(self.pf.get_particle_list())
        self.virtual_create.set_pose((self.pf.xyz), self.pf.theta)

    def isThetaLocalizaed(self):
        self.pf.theta %= (2 * math.pi)
        self.odometry.theta %= (2 * math.pi)
        diff_theta_to_goal = abs(self.odometry.theta - self.pf.theta)
        return diff_theta_to_goal < 0.1

    def isLocalized(self):
        self.pf.theta %= (2 * math.pi)
        self.odometry.theta = self.odometry.theta % (2 * math.pi)

        ground_truth = self.create.sim_get_position()
        self.odometry.x = ground_truth[0]
        self.odometry.y = ground_truth[1]

        dist_position_to_goal = math.sqrt((self.odometry.x - self.pf.x)**2 +
                                          (self.odometry.y - self.pf.y)**2)
        print("self.odometry.x " + str(self.odometry.x) + " self.odometry.y " +
              str(self.odometry.y) + " self.odometry.theta " +
              str(self.odometry.theta))
        print("self.pf.x " + str(self.pf.x) + " self.pf.y " + str(self.pf.y) +
              " self.pf.theta " + str(self.pf.theta))

        diff_theta_to_goal = abs(self.odometry.theta - self.pf.theta)
        print("EUCLIDEAN_DISTANCE ", dist_position_to_goal)
        print("DISTANCE_theta ", diff_theta_to_goal)

        isLocalized = dist_position_to_goal < self.min_dist_to_localize and diff_theta_to_goal < self.min_theta_to_localize
        if isLocalized:
            print("Localized")
        return isLocalized

    def update_odometry(self):
        state = self.create.update()
        if state is not None:
            self.odometry.update(state.leftEncoderCounts,
                                 state.rightEncoderCounts)