Exemplo n.º 1
0
    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.odometry = Odometry()
        self.pidTheta = PIDController(300,
                                      5,
                                      50, [-10, 10], [-200, 200],
                                      is_angle=True)

        # constants
        self.base_speed = 100
        self.variance_sensor = 0.1
        self.variance_distance = 0.01
        self.variance_direction = 0.05
        self.world_width = 3.0  # the x
        self.world_height = 3.0  # the y

        self.filter = ParticleFilter(self.virtual_create,
                                     self.variance_sensor,
                                     self.variance_distance,
                                     self.variance_direction,
                                     num_particles=100,
                                     world_width=self.world_width,
                                     world_height=self.world_height)
    def __init__(self, factory):
        """Constructor.

        Args:
            factory (factory.FactoryCreate)
        """

        # read file and get all paths
        self.img = lab11_image.VectorImage("lab11_img1.yaml")

        # init objects
        self.create = factory.create_create()
        self.time = factory.create_time_helper()
        self.penholder = factory.create_pen_holder()
        self.tracker = Tracker(factory.create_tracker,
                               1,
                               sd_x=0.01,
                               sd_y=0.01,
                               sd_theta=0.01,
                               rate=10)
        self.servo = factory.create_servo()
        self.odometry = Odometry()

        # alpha for tracker
        self.alpha_x = 0.3
        self.alpha_y = self.alpha_x
        self.alpha_theta = 0.3

        # init controllers
        self.pidTheta = PIDController(200,
                                      5,
                                      50, [-10, 10], [-200, 200],
                                      is_angle=True)
        self.pidDistance = PIDController(500,
                                         0,
                                         50, [0, 0], [-200, 200],
                                         is_angle=False)
        self.filter = ComplementaryFilter(
            self.odometry, None, self.time, 0.4,
            (self.alpha_x, self.alpha_y, self.alpha_theta))

        # parameters
        self.base_speed = 100

        # constant
        self.robot_marker_distance = 0.1906

        # debug vars
        self.debug_mode = True
        self.odo = []
        self.actual = []
        self.xi = 0
        self.yi = 0
        self.init = True

        self.penholder_depth = -0.025
Exemplo n.º 3
0
    def __init__(self, factory):
        """Constructor.

        Args:
            factory (factory.FactoryCreate)
        """
        self.create = factory.create_create()
        self.time = factory.create_time_helper()

        self.odometry = Odometry()
        self.pd_controller = PDController(500, 100, -75, 75)
        # self.pid_controller = PIDController(500, 100, 0, -75, 75, -50, 50)
        self.pid_controller = PIDController(250, 30, 1, -100, 100, -100, 100)
Exemplo n.º 4
0
    def __init__(self, factory):
        """Constructor.

        Args:
            factory (factory.FactoryCreate)
        """
        self.create = factory.create_create()
        self.time = factory.create_time_helper()
        self.odometry = Odometry()

        self.x_arr = np.array([])
        self.y_arr = np.array([])
        self.x_arr_truth = np.array([])
        self.y_arr_truth = np.array([])
        self.time_arr = np.array([])
Exemplo n.º 5
0
    def __init__(self, factory):
        """Constructor.

        Args:
            factory (factory.FactoryCreate)
        """
        self.create = factory.create_create()
        self.time = factory.create_time_helper()
        self.odometry = Odometry(
            robotProperties["diameter_left"],
            robotProperties["diameter_right"],
            robotProperties["wheel_base"],
            robotProperties["encoder_count"]
        )
        # self.my_robot = MyRobot(None, self.create, self.time, self.odometry)
        self.prev_r_count = 0
        self.prev_l_count = 0
Exemplo n.º 6
0
class Testloop:
    def __init__(self):
        self.odometry = Odometry()
        self.BASE_SLEEP_TIME_US = 0.250 * 1000000

    def _main_loop(self):
        logs = ["" for _ in range(10000)]
        log_pointer = 0
        speed = 0
        direction = 0

        angle_l = 0
        angle_r = 0

        print('ready')
        for _ in range(100):
            start = datetime.datetime.now()

            direction, speed = self.odometry.target_trace(angle_l, angle_r)

            angle_l += 5
            angle_r += 10

            # 余った時間はsleep
            elapsed_microsecond = (datetime.datetime.now() -
                                   start).microseconds
            if elapsed_microsecond < self.BASE_SLEEP_TIME_US:
                sleep_time = (self.BASE_SLEEP_TIME_US -
                              elapsed_microsecond) / 1000000
                time.sleep(sleep_time)

            logs[log_pointer] = "{}, {}, {}, {}".format(
                angle_l, angle_r, speed, direction)
            log_pointer += 1

        log_file = open("./log_test.csv", 'w')
        for log in logs:
            if log != "":
                log_file.write("{}\n".format(log))
        log_file.close()

        #ログ記録用
        self.odometry.shutdown(0000)
Exemplo n.º 7
0
    def __init__(self, mqtt_client, logger):
        # Create Planet and planet_name variable
        self.planet = Planet()
        self.planet_name = None

        # Setup Sensors, Motors and Odometry
        self.rm = ev3.LargeMotor("outB")
        self.lm = ev3.LargeMotor("outC")
        self.sound = ev3.Sound()
        self.odometry = Odometry(self.lm, self.rm)
        self.motors = Motors(self.odometry)
        self.cs = ColorSensor(self.motors)
        self.us = Ultrasonic()

        # Setup Communication
        self.communication = Communication(mqtt_client, logger, self)

        # Create variable to write to from communication
        self.start_location = None
        self.end_location = None
        self.path_choice = None
        self.running = True
Exemplo n.º 8
0
    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 = lab10_map.Map("lab11.map")
        self.odometry = Odometry()
Exemplo n.º 9
0
    def __init__(self, device_path):
        self.device = serial.Serial(device_path, 115200, timeout=0.5)
        self.write_lock = threading.Lock()

        self.device.write(chr(128) * 3)
        self.device.write(chr(131))

        self.odometry = Odometry()
        self.bumpers = [False, False]
        self.drops = [False, False]

        self.wall = False
        self.cliff = [False, False, False, False]

        self.vwall = False
        self.dirt = 0

        self.buttons = [False, False, False]

        self.charging = 0
        self.charge_current = 0
        self.charge_voltage = 0

        self._odom_left = 0
        self._odom_right = 0
        self._odom_last = [0, 0]
        self._odom_start = True

        self.joint_positions = [0, 0, 0, 0]

        self.temperature = 0
        self._packets = [
            7, 8, 9, 10, 11, 12, 13, 14, 15, 18, 43, 44, 21, 22, 24, 25
        ]
        self._i = 0

        self._unmeasured = [False, False]
Exemplo n.º 10
0
    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()
        self.map = np.loadtxt("map14.txt", delimiter=",")
        self.odometry = Odometry()
        self.search = AStar(self.map)
        self.location = (0,0)
        self.orientation = "east"
        self.pidTheta = pid_controller.PIDController(200, 25, 5, [-1, 1], [-200, 200], is_angle=True)
        self.pidDistance = pid_controller.PIDController(100, 15, 5, [-10, 10], [-200, 200], is_angle=False)
        self.base_speed = 50
Exemplo n.º 11
0
def run():
# the execution of all code shall be started from within this function
    print('Hello World')
    planet = Planet()
    odometry = Odometry()
    movement_functions = Movement(motor_list = (ev3.LargeMotor('outB'), ev3.LargeMotor('outC')), odometry = odometry)
    line_follower = follow.LineFollowing(colour_sensor = ev3.ColorSensor('in2'),
                         ts_list = (ev3.TouchSensor('in1'), ev3.TouchSensor('in4')), movement=movement_functions, odometry = odometry)
    communication = Communication(planet = planet, odometry = odometry)
    communication.connect()
    line_follower.colour_calibration()
    line_follower.line_following()
    communication.first_communication()
    sleep(2)
    line_follower.path_recognising()

    while True:
        #odometry.odometry_calculations()
        line_follower.line_following()
        line_follower.path_recognising()
Exemplo n.º 12
0
 def serialize(dic):
     if 'responses' in dic  and 'frame_name' in dic:
         responses = AnnotateResponse.serialize(dic['responses'])
         env = None
         odometry = None
         width = None
         height = None
         depth = None
         if 'odometry' in dic and dic['odometry'] != None:
             odometry = Odometry.serialize(dic['odometry'])
         if 'environment' in dic and dic['environment'] != None:
             env = Environment.serialize(dic['environment'])
         if 'image_width' in dic:
             width = dic['image_width']
         if 'image_height' in dic:
             height = dic['image_height']
         if 'image_depth' in dic:
             depth = dic['image_depth']
         return Responses(dic['frame_name'], responses, width, height, depth, odometry, env)
     else:
         return dic
print("X is horizontal, robot starts at 90 pose along +Y")

width = 21  #cm

print("Input coords are in grid coords")
start_x_g = float(input("Input the start x coord"))
start_y_g = float(input("Input the start y coord"))
goal_x_g = float(input("Input the desired x coord"))
goal_y_g = float(input("Input the desired y coord"))

# first implement move to point
# then implement hazard avoidance

dt = 0.02

odometry = Odometry(dt)
sensors.initSensors()

goal_location = Translation2d(goal_x_g * width, goal_y_g * width)

odometry.current_pos = RigidTransform2d(Translation2d(start_x_g*width, \
                        start_y_g*width), Rotation2d.fromDegrees(0))

# left A Right B
navigating = True
kP = 0.05
kMP = 0.003
resting_mag = 100
error_mag = 130
speed = 0.15
error_radius = 3  #cm
class Run:
    def __init__(self, factory):
        """Constructor.

        Args:
            factory (factory.FactoryCreate)
        """

        # read file and get all paths
        self.img = lab11_image.VectorImage("lab11_img1.yaml")

        # init objects
        self.create = factory.create_create()
        self.time = factory.create_time_helper()
        self.penholder = factory.create_pen_holder()
        self.tracker = Tracker(factory.create_tracker,
                               1,
                               sd_x=0.01,
                               sd_y=0.01,
                               sd_theta=0.01,
                               rate=10)
        self.servo = factory.create_servo()
        self.odometry = Odometry()

        # alpha for tracker
        self.alpha_x = 0.3
        self.alpha_y = self.alpha_x
        self.alpha_theta = 0.3

        # init controllers
        self.pidTheta = PIDController(200,
                                      5,
                                      50, [-10, 10], [-200, 200],
                                      is_angle=True)
        self.pidDistance = PIDController(500,
                                         0,
                                         50, [0, 0], [-200, 200],
                                         is_angle=False)
        self.filter = ComplementaryFilter(
            self.odometry, None, self.time, 0.4,
            (self.alpha_x, self.alpha_y, self.alpha_theta))

        # parameters
        self.base_speed = 100

        # constant
        self.robot_marker_distance = 0.1906

        # debug vars
        self.debug_mode = True
        self.odo = []
        self.actual = []
        self.xi = 0
        self.yi = 0
        self.init = True

        self.penholder_depth = -0.025

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

        # request sensors
        self.create.start_stream([
            create2.Sensor.LeftEncoderCounts,
            create2.Sensor.RightEncoderCounts,
        ])

        self.penholder.set_color(0.0, 1.0, 0.0)

        # generate spline points and line drawing order
        splines, splines_color = PathFinder.get_spline_points(self.img.paths)
        # in format [index, is_parallel, is_spline]
        line_index_list = PathFinder.find_path(self.img.lines, splines,
                                               splines_color)

        prev_color = None

        # loop to draw all lines and paths
        for draw_info in line_index_list:
            index = int(draw_info[0])
            is_parallel = draw_info[1]
            is_spline = draw_info[2]

            line = self.img.lines[index]
            curr_color = self.img.lines[index].color

            if curr_color != prev_color:
                prev_color = curr_color
                self.penholder.set_color(*get_color(curr_color))

            # ===== spline routine =====
            if is_spline:
                path_points = self.draw_path_coords(splines[index],
                                                    is_parallel)
                self.penholder.set_color(*get_color(splines_color[0]))

                # go to start of the curve and begin drawing
                for i in range(0, 2):
                    # go to start of curve
                    goal_x, goal_y = path_points[0, 0], path_points[0, 1]
                    print("=== GOAL SET === {:.3f}, {:.3f}".format(
                        goal_x, goal_y))
                    if i == 1:
                        goal_x, goal_y = path_points[9, 0], path_points[9, 1]

                    # turn to goal
                    # self.tracker.update()
                    self.filter.update()
                    curr_x = self.filter.x
                    curr_y = self.filter.y
                    goal_theta = math.atan2(goal_y - curr_y, goal_x - curr_x)
                    if i == 1:
                        goal_theta = math.atan2(goal_y - path_points[0, 1],
                                                goal_x - path_points[0, 0])
                    self.penholder.go_to(0.0)
                    self.go_to_angle(goal_theta)
                    self.go_to_goal(goal_x, goal_y)

                # start drawing after correctly oriented
                # uses only odometry during spline drawing
                self.penholder.go_to(self.penholder_depth)
                prev_base_speed = self.base_speed
                self.filter.updateFlag = False
                self.base_speed = 25
                print("Draw!")

                last_drew_index = 0

                # draw the rest of the curve. Draws every 10th point.
                for i in range(10, len(path_points), 5):
                    goal_x, goal_y = path_points[i, 0], path_points[i, 1]
                    print("=== GOAL SET === {:.3f}, {:.3f}".format(
                        goal_x, goal_y))
                    self.go_to_goal(goal_x, goal_y, useOdo=True)

                print("\nlast drew index {}\n".format(last_drew_index))
                if last_drew_index < len(path_points) - 1:
                    goal_x, goal_y = path_points[-1, 0], path_points[-1, 1]
                    print("=== GOAL SET === {:.3f}, {:.3f}".format(
                        goal_x, goal_y))
                    self.go_to_goal(goal_x, goal_y, useOdo=False)

                # stop drawing and restore parameter values
                self.base_speed = prev_base_speed
                self.filter.updateFlag = True
                self.penholder.go_to(0.0)

            # ===== line routine =====
            else:
                for i in range(0, 2):
                    goal_x, goal_y = self.draw_coords(line,
                                                      is_parallel=is_parallel,
                                                      at_start=True)

                    if i == 1:
                        goal_x, goal_y = self.draw_coords(
                            line, is_parallel=is_parallel, at_start=False)

                    print("=== GOAL SET === {:.3f}, {:.3f}".format(
                        goal_x, goal_y))

                    # turn to goal
                    # self.tracker.update()
                    self.filter.update()
                    curr_x = self.filter.x
                    curr_y = self.filter.y
                    goal_theta = math.atan2(goal_y - curr_y, goal_x - curr_x)
                    self.penholder.go_to(0.0)
                    self.go_to_angle(goal_theta)

                    if i == 1:
                        # start drawing
                        self.penholder.go_to(self.penholder_depth)
                        print("Draw!")

                    self.go_to_goal(goal_x, goal_y)

        # graph the final result
        self.draw_graph()
        self.create.stop()

    def drive(self, theta, distance, speed):
        # Sum all controllers and clamp
        self.create.drive_direct(
            max(min(int(theta + distance + speed), 500), -500),
            max(min(int(-theta + distance + speed), 500), -500))

    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:
            self.update()

            t = self.time.time()
            if start + time_in_sec <= t:
                break

    # gives coordinates to draw the lines correctly
    # line: segment to be drawn
    # at_start: set true to retun the first coordinate, set false for the second coordinate
    # returns the x, y coordinates offset
    def draw_coords(self, line, at_start=True, is_parallel=True):
        if is_parallel:
            theta = math.atan2(line.v[1] - line.u[1],
                               line.v[0] - line.u[0]) + math.pi / 2
            if at_start:
                return math.cos(theta) * self.robot_marker_distance + line.u[0], \
                       math.sin(theta) * self.robot_marker_distance + line.u[1]
            else:
                return math.cos(theta) * self.robot_marker_distance + line.v[0], \
                       math.sin(theta) * self.robot_marker_distance + line.v[1]
        else:
            theta = math.atan2(line.v[1] - line.u[1],
                               line.v[0] - line.u[0]) - math.pi / 2
            if at_start:
                return math.cos(theta) * self.robot_marker_distance + line.v[0], \
                       math.sin(theta) * self.robot_marker_distance + line.v[1]
            else:
                return math.cos(theta) * self.robot_marker_distance + line.u[0], \
                       math.sin(theta) * self.robot_marker_distance + line.u[1]

    def draw_path_coords(self, result, is_parallel):
        final_result = np.empty((0, 2))
        if is_parallel:
            for i in range(0, len(result) - 1):
                theta = math.atan2(
                    result[i, 1] - result[i + 1, 1],
                    result[i, 0] - result[i + 1, 0]) - math.pi / 2
                s = math.cos(theta) * self.robot_marker_distance + result[i, 0], \
                    math.sin(theta) * self.robot_marker_distance + result[i, 1]
                final_result = np.vstack([final_result, s])
        else:
            for i in range(len(result) - 1, 1, -1):
                theta = math.atan2(
                    result[i, 1] - result[i - 1, 1],
                    result[i, 0] - result[i - 1, 0]) - math.pi / 2
                s = math.cos(theta) * self.robot_marker_distance + result[i, 0], \
                    math.sin(theta) * self.robot_marker_distance + result[i, 1]
                final_result = np.vstack([final_result, s])
        return final_result

    def go_to_goal(self, goal_x, goal_y, useOdo=False):
        while True:
            state = self.update()

            if state is not None:
                if useOdo:
                    curr_x = self.odometry.x
                    curr_y = self.odometry.y
                    curr_theta = self.odometry.theta
                else:
                    curr_x = self.filter.x
                    curr_y = self.filter.y
                    curr_theta = self.filter.theta

                distance = math.sqrt(
                    math.pow(goal_x - curr_x, 2) +
                    math.pow(goal_y - curr_y, 2))
                output_distance = self.pidDistance.update(
                    0, distance, self.time.time())

                theta = math.atan2(goal_y - curr_y, goal_x - curr_x)
                output_theta = self.pidTheta.update(curr_theta, theta,
                                                    self.time.time())

                print("goal x,y = {:.3f}, {:.3f}, x,y = {:.3f}, {:.3f}".format(
                    goal_x, goal_y, curr_x, curr_y))

                self.drive(output_theta, output_distance, self.base_speed)

                if distance < 0.05:
                    self.create.drive_direct(0, 0)
                    break

                self.sleep(0.01)

    def go_to_angle(self, goal_theta):
        curr_theta = self.filter.theta

        while abs(-math.degrees(
                math.atan2(math.sin(curr_theta - goal_theta),
                           math.cos(curr_theta - goal_theta)))) > 8:
            curr_theta = self.filter.theta

            print("goal_theta = {:.2f}, theta = {:.2f}".format(
                math.degrees(goal_theta), math.degrees(curr_theta)))
            output_theta = self.pidTheta.update(curr_theta, goal_theta,
                                                self.time.time())

            self.drive(output_theta, 0, 0)
            self.sleep(0.01)
        self.create.drive_direct(0, 0)

    # debug function. Draws robot paths
    def draw_graph(self):
        # show drawing progress after each line segment is drawn
        if self.debug_mode:
            if len(self.odo) is not 0 and len(self.actual) is not 0:
                x, y = zip(*self.odo)
                a, b = zip(*self.actual)
                plt.plot(x, y, color='red', label='Sensor path')
                plt.plot(a,
                         b,
                         color='green',
                         label='Actual path',
                         linewidth=1.4)
                self.odo = []
                self.actual = []

            for path in self.img.paths:
                ts = np.linspace(0, 1.0, 100)
                result = np.empty((0, 3))
                for i in range(0, path.num_segments()):
                    for t in ts[:-2]:
                        s = path.eval(i, t)
                        result = np.vstack([result, s])

                plt.plot(result[:, 0], result[:, 1], path.color)

                path_points = self.draw_path_coords(result, True)
                plt.plot(path_points[:, 0], path_points[:, 1], color='aqua')
                path_points = self.draw_path_coords(result, False)
                plt.plot(path_points[:, 0], path_points[:, 1], color='aqua')

            for line in self.img.lines:

                # draw lines
                plt.plot([line.u[0], line.v[0]], [line.u[1], line.v[1]],
                         line.color)
                theta = math.atan2(line.v[1] - line.u[1],
                                   line.v[0] - line.u[0]) + math.pi / 2
                plt.plot([
                    math.cos(theta) * self.robot_marker_distance + line.u[0],
                    math.cos(theta) * self.robot_marker_distance + line.v[0]
                ], [
                    math.sin(theta) * self.robot_marker_distance + line.u[1],
                    math.sin(theta) * self.robot_marker_distance + line.v[1]
                ], 'aqua')

                theta = math.atan2(line.v[1] - line.u[1],
                                   line.v[0] - line.u[0]) - math.pi / 2
                plt.plot([
                    math.cos(theta) * self.robot_marker_distance + line.u[0],
                    math.cos(theta) * self.robot_marker_distance + line.v[0]
                ], [
                    math.sin(theta) * self.robot_marker_distance + line.u[1],
                    math.sin(theta) * self.robot_marker_distance + line.v[1]
                ], 'aqua')

            plt.legend()
            plt.show()

    # updates odometry, filter, and tracker
    def update(self):
        state = self.create.update()
        self.filter.update()
        # self.tracker.update()

        if state is not None:
            self.odometry.update(state.leftEncoderCounts,
                                 state.rightEncoderCounts)
            # print("[{},{},{}]".format(self.odometry.x, self.odometry.y, math.degrees(self.odometry.theta)))

            if self.debug_mode:
                self.odo.append((self.filter.x, self.filter.y))
                self.actual.append(
                    (self.create.sim_get_position()[0] - self.xi,
                     self.create.sim_get_position()[1] - self.yi))

        return state
Exemplo n.º 15
0
from frame_loader import FrameLoader
from odometry import FeatureExtractor
from odometry import Odometry
from visualizator import Visualizator

# Declarations
frame_loader = FrameLoader("data/video.mp4")
extractor = FeatureExtractor("orb")
visual_odometry = Odometry()
visualizator = Visualizator()
frame_read = True

while frame_read:
    # Load and display the frame
    frame_read, frame = frame_loader.get_frame()

    # Extract features and descriptors
    kp, des = extractor.extract_features(frame)

    # Visualize results
    visualizator.show_image(frame)
    visualizator.show_keypoints(frame, kp)

    # Printouts
    print("Captured frame: %d" % frame_loader.frame_num)
    print("Frame shape: %s" % (frame.shape,))
    print("Extracted keypoints: %d" % len(kp))

frame_loader.close()
Exemplo n.º 16
0
from odometry import Odometry
from transforms import *
import sensors
import time
import math

print("CCW is the positive direction!")
angle = float(input("Input the desired turn angle-> "))

dt = 0.01

odometry = Odometry(dt)
sensors.initSensors()

heading_setpoint = Rotation2d.fromDegrees(0)
# left A Right B
def setHeading(offset):
    global heading_setpoint
    sensors.updateSensors()
    deg = odometry.getFieldToVehicle().getRotation().getDegrees()
    heading_setpoint = Rotation2d.fromDegrees(deg).rotateBy(Rotation2d.fromDegrees(offset))
    print("Heading set to: " + str(heading_setpoint))

def getHeadingError():
    current_heading = odometry.getFieldToVehicle().getRotation()
    return current_heading.inverse().rotateBy(heading_setpoint).getDegrees()

turn_speed = 0.15
sensors.setLeftMotor(-turn_speed * angle / math.fabs(angle))
sensors.setRightMotor(turn_speed * angle / math.fabs(angle))
Exemplo n.º 17
0
class Run:
    def __init__(self, factory):
        """Constructor.

        Args:
            factory (factory.FactoryCreate)
        """
        self.create = factory.create_create()
        self.time = factory.create_time_helper()

        self.odometry = Odometry()
        self.pd_controller = PDController(500, 100, -75, 75)
        # self.pid_controller = PIDController(500, 100, 0, -75, 75, -50, 50)
        self.pid_controller = PIDController(250, 30, 1, -100, 100, -100, 100)

    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)
                # print("[{},{},{}]".format(self.odometry.x, self.odometry.y, np.rad2deg(self.odometry.theta)))
            t = self.time.time()
            if start + time_in_sec <= t:
                break

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

        # request sensors
        self.create.start_stream([
            create2.Sensor.LeftEncoderCounts,
            create2.Sensor.RightEncoderCounts,
        ])

        plt_time_arr = np.array([])
        plt_angle_arr = np.array([])

        goal_angle = np.pi / 2
        goal_angle %= 2 * np.pi
        base_speed = 0
        timeout = abs(17 * (goal_angle / np.pi)) + 1

        angle = self.odometry.theta
        plt_time_arr = np.append(plt_time_arr, self.time.time())
        plt_angle_arr = np.append(plt_angle_arr, angle)

        start_time = self.time.time()
        while self.time.time() - start_time < timeout:
            angle = self.odometry.theta
            plt_time_arr = np.append(plt_time_arr, self.time.time())
            plt_angle_arr = np.append(plt_angle_arr, angle)

            # output = self.pd_controller.update(angle, goal_angle, self.time.time())
            output = self.pid_controller.update(angle, goal_angle,
                                                self.time.time())
            # print("angle =%f, output = %f" % (np.rad2deg(angle), output))
            # print("[r = %f, l = %f]\n" % (int(base_speed + output), int(base_speed - output)))
            self.create.drive_direct(int(base_speed + output),
                                     int(base_speed - output))
            self.sleep(0.01)

        np.savetxt("timeOutput.csv", plt_time_arr, delimiter=",")
        np.savetxt("angleOutput.csv", plt_angle_arr, delimiter=",")
Exemplo n.º 18
0
                if not bad_data:
                    predictions.append([i, j, k])
                    errors.append(math.log(error))

    if len(errors) > 0:
        ix = errors.index(min(errors))
        return predictions[ix]

    return -1


if __name__ == '__main__':
    init()
    step()
    odometry = Odometry(ENCODER_UNIT * (positionLeft.getValue()),
                        ENCODER_UNIT * (positionRight.getValue()), INIT_X,
                        INIT_Y, INIT_ANGLE)

    count = 0

    while (True):

        odometry_info = odometry.track_step(
            ENCODER_UNIT * (positionLeft.getValue()),
            ENCODER_UNIT * (positionRight.getValue()))

        if not step():
            # print('saving data')
            data_collector.collect(x_odometry, y_odometry, theta_odometry, x,
                                   y, theta, np.array(distance_sensors_info))
            plot()
Exemplo n.º 19
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.odometry = Odometry()
        self.odometry.x = 1
        self.odometry.y = 0.5
        self.pidTheta = PIDController(300,
                                      5,
                                      50, [-10, 10], [-200, 200],
                                      is_angle=True)

        # constants
        self.base_speed = 100
        self.variance_sensor = 0.1
        self.variance_distance = 0.01
        self.variance_direction = 0.05
        self.world_width = 3.0  # the x
        self.world_height = 3.0  # the y
        self.travel_dist = 0.25
        self.min_dist_to_wall = self.travel_dist + 0.2
        self.min_dist_to_localize = 0.2
        self.min_theta_to_localize = math.pi / 4
        self.n_threshold = math.log(0.09)

        self.filter = ParticleFilter(self.virtual_create,
                                     self.variance_sensor,
                                     self.variance_distance,
                                     self.variance_direction,
                                     num_particles=100,
                                     world_width=self.world_width,
                                     world_height=self.world_height,
                                     input_map=self.map,
                                     n_threshold=self.n_threshold)

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

        # request sensors
        self.create.start_stream([
            create2.Sensor.LeftEncoderCounts,
            create2.Sensor.RightEncoderCounts,
        ])

        isLocalized = False
        angle_counter = 0

        # This is an example on how to detect that a button was pressed in V-REP
        while not isLocalized:
            self.draw_particles()

            # generate random num
            command = random.choice([c for c in Command])

            if command is Command.FORWARD:
                if self.sonar.get_distance() < self.min_dist_to_wall:
                    continue

                self.filter.move(0, self.travel_dist)

                # 100 mm/s = 0.1 m/s
                self.create.drive_direct(self.base_speed, self.base_speed)
                self.sleep(abs(self.travel_dist / 0.1))

                # stop
                self.create.drive_direct(0, 0)
            elif command is Command.TURN_LEFT:
                # turn_angle = math.pi / 2 + self.odometry.theta
                turn_angle = math.pi / 2 + angle_counter
                turn_angle %= 2 * math.pi
                angle_counter += math.pi / 2
                angle_counter %= 2 * math.pi

                self.filter.move(turn_angle, 0)

                # turn left by 90 degree
                self.go_to_angle(turn_angle)
            elif command is Command.TURN_RIGHT:
                # turn_angle = -math.pi / 2 + self.odometry.theta
                turn_angle = -math.pi / 2 + angle_counter
                turn_angle %= 2 * math.pi
                angle_counter -= math.pi / 2
                angle_counter %= 2 * math.pi

                self.filter.move(turn_angle, 0)

                # turn right by 90 degree
                self.go_to_angle(turn_angle)

            self.filter.sense(self.sonar.get_distance())

            # check if localized

            # distance between odometry and estimated positions
            dist_position_to_goal = math.sqrt(
                (self.odometry.x - self.filter.x)**2 +
                (self.odometry.y - self.filter.y)**2)
            diff_theta_to_goal = abs(self.odometry.theta - self.filter.theta)

            isLocalized = dist_position_to_goal < self.min_dist_to_localize and diff_theta_to_goal < self.min_theta_to_localize

    def go_to_angle(self, goal_theta):
        while abs(
                math.atan2(math.sin(goal_theta - self.odometry.theta),
                           math.cos(goal_theta - self.odometry.theta))) > 0.1:
            # print("Go TO: " + str(math.degrees(goal_theta)) + " " + str(math.degrees(self.odometry.theta)))
            output_theta = self.pidTheta.update(self.odometry.theta,
                                                goal_theta, self.time.time())
            self.create.drive_direct(int(+output_theta), int(-output_theta))
            self.sleep(0.01)

        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)
                # print("[{},{},{}]".format(self.odometry.x, self.odometry.y, math.degrees(self.odometry.theta)))
            t = self.time.time()
            if start + time_in_sec <= t:
                break

    def draw_particles(self):
        data = []

        # get position data from all particles
        for particle in self.filter.particles:
            data.extend([particle.x, particle.y, 0.1, particle.theta])

            # paint all particles in simulation
            self.virtual_create.set_point_cloud(data)
Exemplo n.º 20
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 = lab10_map.Map("lab11.map")
        self.odometry = Odometry()
        
    def showParticles(self, particles):
        self.virtual_create.set_point_cloud(particles)
        
    def visualizePose(self,x,y,z,theta):
        self.virtual_create.set_pose((x, y, z), theta)
        
    def turnLeftOneSec(self):
        self.create.drive_direct(50,-50)
        self.time.sleep(1)
        self.create.drive_direct(0,0)
        self.state = self.create.update()
        self.odometry.update(self.state.leftEncoderCounts, self.state.rightEncoderCounts)
        self.pf.TurnLeft()
        
    def redrawParticles(self):
        for particle in self.pf.getParticles():
                self.showParticles([particle.x,particle.y,0.1,particle.theta])
        
    def findAndGoOnClearPath(self):
        #Find new angle to move at
        foundNewAngle = False
        foundStartTime = False
        runTime = 0
        #Turn robot until clear space is found
        while not foundNewAngle:
            #Turn robot
            self.turnLeftOneSec()
            self.redrawParticles()
            distanceFromNearestObstacle = self.sonar.get_distance()
            obstacleAhead = distanceFromNearestObstacle < 0.001
            
            if not obstacleAhead:
                if not foundStartTime:
                    foundStartTime = True
                else:
                    runTime += 1
            
            if foundStartTime and runTime >= 4:
                foundNewAngle = True
            elif obstacleAhead and runTime < 4:
                foundStartTime = False
                runTime = 0

        #Now turn the other way
        turnRightTime = int(runTime / 2)
        for i in range(0, turnRightTime):
            self.create.drive_direct(-50,50)
            self.time.sleep(1)
            self.create.drive_direct(0,0)
            self.state = self.create.update()
            self.odometry.update(self.state.leftEncoderCounts, self.state.rightEncoderCounts)
            self.pf.TurnRight()
            for particle in self.pf.getParticles():
                self.showParticles([particle.x,particle.y,0.1,particle.theta])
                    
        #Actually move forward
        self.create.drive_direct(50,50)
        self.time.sleep(1)
        self.create.drive_direct(0,0)
        self.state = self.create.update()
        self.odometry.update(self.state.leftEncoderCounts, self.state.rightEncoderCounts)
        self.pf.MoveForward()

    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.visualizePose(0.5, 0.5, 0.1, math.pi)

        # 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.showParticles(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), math.pi))
        
        self.state = self.create.update()
        while not self.state:
            self.state = self.create.update()
        self.odometry.update(self.state.leftEncoderCounts, self.state.rightEncoderCounts)
        
        #This is an example on how to use PF
        variances = [0.01,0.01,0.3]
        self.pf = PF([self.map.bottom_left[0], self.map.top_right[0]],[self.map.bottom_left[1], self.map.top_right[1]],[0,2*math.pi], variances, self.map)
        print("Drawing particles")
        for particle in self.pf.getParticles():
            self.showParticles([particle.x,particle.y,0.1,particle.theta])
        
        # This is an example on how to detect that a button was pressed in V-REP
        bNum = 0
        while True:
            self.create.drive_direct(0,0)
            
            self.state = self.create.update()
            if self.state:
                self.odometry.update(self.state.leftEncoderCounts, self.state.rightEncoderCounts)
                prevX = self.odometry.x
                prevY = self.odometry.y
                prevTheta = self.odometry.theta

                #b = self.virtual_create.get_last_button()
                if self.pf.isOneCluster():
                    break
                if bNum % 2 == 0:
                    b = self.virtual_create.Button.Sense
                elif bNum % 4 == 1:
                    b = self.virtual_create.Button.TurnLeft
                elif bNum % 4 == 3:
                    b = self.virtual_create.Button.MoveForward
                bNum += 1
                if b == self.virtual_create.Button.MoveForward:
                    print("Forward pressed!")
                    self.findAndGoOnClearPath()
                    print("Drawing particles")
                    for particle in self.pf.getParticles():
                        self.showParticles([particle.x,particle.y,0.1,particle.theta])
                elif b == self.virtual_create.Button.TurnLeft:
                    print("Turn Left pressed!")
                    self.create.drive_direct(50,-50)
                    self.time.sleep(1)
                    self.create.drive_direct(0,0)
                    self.state = self.create.update()
                    self.odometry.update(self.state.leftEncoderCounts, self.state.rightEncoderCounts)
                    self.pf.TurnLeft()
                    print("Drawing particles")
                    for particle in self.pf.getParticles():
                        self.showParticles([particle.x,particle.y,0.1,particle.theta])
                elif b == self.virtual_create.Button.TurnRight:
                    print("Turn Right pressed!")
                    self.create.drive_direct(-50,50)
                    self.time.sleep(1)
                    self.create.drive_direct(0,0)
                    self.state = self.create.update()
                    self.odometry.update(self.state.leftEncoderCounts, self.state.rightEncoderCounts)
                    self.pf.TurnRight()
                    print("Drawing particles")
                    for particle in self.pf.getParticles():
                        self.showParticles([particle.x,particle.y,0.1,particle.theta])
                elif b == self.virtual_create.Button.Sense:
                    print("Sense pressed!")
                    dist = self.sonar.get_distance()
                    if dist:
                        self.pf.Sensing(dist)
                    print("Drawing particles")
                    for particle in self.pf.getParticles():
                        self.showParticles([particle.x,particle.y,0.1,particle.theta])

                self.time.sleep(0.01)
Exemplo n.º 21
0
class Run:
    def __init__(self, factory):
        """Constructor.

        Args:
            factory (factory.FactoryCreate)
        """
        self.create = factory.create_create()
        self.time = factory.create_time_helper()
        self.odometry = Odometry()

        self.x_arr = np.array([])
        self.y_arr = np.array([])
        self.x_arr_truth = np.array([])
        self.y_arr_truth = np.array([])
        self.time_arr = np.array([])

    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()
        t = start
        while t - start < time_in_sec:
            state = self.create.update()
            if state is not None:
                self.odometry.update(state.leftEncoderCounts, state.rightEncoderCounts)
                # print("[{},{},{}]".format(self.odometry.x, self.odometry.y, np.rad2deg(self.odometry.theta)))
                self.time_arr = np.append(self.time_arr, t)
                self.x_arr = np.append(self.x_arr, self.odometry.x)
                self.y_arr = np.append(self.y_arr, self.odometry.y)
                self.x_arr_truth = np.append(self.x_arr_truth, self.create.sim_get_position()[0])
                self.y_arr_truth = np.append(self.y_arr_truth, self.create.sim_get_position()[1])
            t = self.time.time()

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

        # request sensors
        self.create.start_stream([
            create2.Sensor.LeftEncoderCounts,
            create2.Sensor.RightEncoderCounts,
        ])

        speed = 300  # mm/s
        time_90deg_turn = 1.9 / (speed / 100.0)  # seconds

        # move forward for 1m
        self.create.drive_direct(speed, speed)
        self.sleep(1000 / speed)

        # turn left 90 deg
        self.create.drive_direct(speed, -speed)
        self.sleep(time_90deg_turn)

        # move forward for 0.5m
        self.create.drive_direct(speed, speed)
        self.sleep(500 / speed)

        # turn left 90 deg
        self.create.drive_direct(speed, -speed)
        self.sleep(time_90deg_turn)

        # move forward for 1m
        self.create.drive_direct(speed, speed)
        self.sleep(1000 / speed)

        # turn left 90 deg
        self.create.drive_direct(speed, -speed)
        self.sleep(time_90deg_turn)

        # move forward for 0.5m
        self.create.drive_direct(speed, speed)
        self.sleep(500 / speed)

        # stop simulation
        self.create.stop()

        x_offset = self.x_arr_truth[np.argwhere(self.time_arr > 0.05)[0]]
        y_offset = self.y_arr_truth[np.argwhere(self.time_arr > 0.05)[0]]

        # plt.plot(self.time_arr, self.x_arr + x_offset, label='x coor measured')
        # plt.plot(self.time_arr, self.x_arr_truth, '--', label='x coor truth')
        # plt.plot(self.time_arr, self.y_arr + y_offset, label='y coor measured')
        # plt.plot(self.time_arr, self.y_arr_truth, '--', label='y coor truth')

        plt.plot(self.x_arr + x_offset, self.y_arr + y_offset, label='coor measured')
        plt.plot(self.x_arr_truth, self.y_arr_truth, '--', label='coor truth')
        plt.legend()
        plt.grid()
        plt.show()
Exemplo n.º 22
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.odometry = Odometry()
        self.pidTheta = PIDController(300,
                                      5,
                                      50, [-10, 10], [-200, 200],
                                      is_angle=True)

        # constants
        self.base_speed = 100
        self.variance_sensor = 0.1
        self.variance_distance = 0.01
        self.variance_direction = 0.05
        self.world_width = 3.0  # the x
        self.world_height = 3.0  # the y

        self.filter = ParticleFilter(self.virtual_create,
                                     self.variance_sensor,
                                     self.variance_distance,
                                     self.variance_direction,
                                     num_particles=100,
                                     world_width=self.world_width,
                                     world_height=self.world_height)

    def run(self):
        # # 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))
        #
        # # 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:
        #         print("Forward pressed!")
        #     elif b == self.virtual_create.Button.TurnLeft:
        #         print("Turn Left pressed!")
        #     elif b == self.virtual_create.Button.TurnRight:
        #         print("Turn Right pressed!")
        #     elif b == self.virtual_create.Button.Sense:
        #         print("Sense pressed!")
        #
        #     self.time.sleep(0.01)
        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 detect that a button was pressed in V-REP
        while True:
            self.draw_particles()

            b = self.virtual_create.get_last_button()
            if b == self.virtual_create.Button.MoveForward:
                self.filter.move(0, 0.5)

                # 100 mm/s = 0.1 m/s
                self.create.drive_direct(self.base_speed, self.base_speed)
                self.sleep(abs(0.5 / 0.1))

                # stop
                self.create.drive_direct(0, 0)
            elif b == self.virtual_create.Button.TurnLeft:
                turn_angle = math.pi / 2 + self.odometry.theta
                turn_angle %= 2 * math.pi

                self.filter.move(turn_angle, 0)

                # turn left by 90 degree
                self.go_to_angle(turn_angle)
            elif b == self.virtual_create.Button.TurnRight:
                turn_angle = -math.pi / 2 + self.odometry.theta
                turn_angle %= 2 * math.pi

                self.filter.move(turn_angle, 0)

                # turn right by 90 degree
                self.go_to_angle(turn_angle)
            elif b == self.virtual_create.Button.Sense:
                self.filter.sense(self.sonar.get_distance())

            self.sleep(0.01)

    def go_to_angle(self, goal_theta):
        while abs(
                math.atan2(math.sin(goal_theta - self.odometry.theta),
                           math.cos(goal_theta - self.odometry.theta))) > 0.01:
            print("Go TO: " + str(math.degrees(goal_theta)) + " " +
                  str(math.degrees(self.odometry.theta)))
            output_theta = self.pidTheta.update(self.odometry.theta,
                                                goal_theta, self.time.time())
            self.create.drive_direct(int(+output_theta), int(-output_theta))
            self.sleep(0.01)

        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)
                # print("[{},{},{}]".format(self.odometry.x, self.odometry.y, math.degrees(self.odometry.theta)))
            t = self.time.time()
            if start + time_in_sec <= t:
                break

    def draw_particles(self):
        data = []

        # get position data from all particles
        for particle in self.filter.particles:
            data.extend([particle.x, particle.y, 0.1, particle.theta])

            # paint all particles in simulation
            self.virtual_create.set_point_cloud(data)
Exemplo n.º 23
0
from ev3dev import ev3
from odometry import Odometry
from math import pi

odometry = Odometry(ev3.LargeMotor("outB"), ev3.LargeMotor("outC"), 6.0, 2.7,
                    6.0, 2 * pi / 5.0)
odometry.drive_to(-30.0, 0.0, 0)
odometry.drive_to(-30.0, 30.0, 0)
odometry.drive_to(-60.0, 60.0, pi)
Exemplo n.º 24
0
 def __init__(self):
     self.odometry = Odometry()
     self.BASE_SLEEP_TIME_US = 0.250 * 1000000
Exemplo n.º 25
0
def guide(sh_mem, setting, log_datetime):
    print('Im Guide')

    def shutdown_child(signum=None, frame=None):
        try:
            sleep(0.2)

            log_file = open("./log/log_{}_guide.csv".format(log_datetime), 'w')
            for log in logs:
                if log != "":
                    log_file.write("{}\n".format(log))
            log_file.close()

            if ('line_tracer' in globals()) or ('line_tracer' in locals()):
                line_tracer.shutdown()

            sys.exit()

        except Exception as ex:
            g_log.exception(ex)
            raise ex

    def wait_for_input():
        print('Guide Waiting ...')
        sh_mem.write_guide_is_ready_mem(1)
        while not sh_mem.read_touch_sensor_mem():
            sleep(0.1)

    signal.signal(signal.SIGTERM, shutdown_child)

    try:
        # ここで変数定義などの事前準備を行う
        # Time of each loop, measured in miliseconds.
        loop_time_millisec = 18
        # Time of each loop, measured in seconds.
        loop_time_sec = loop_time_millisec / 1000.0

        # ログ記録用
        logs = ["" for _ in range(10000)]
        log_pointer = 0

        wait_for_input()  # 設置が終わるまで待つ

        line_tracer = LineTracer(setting)

        # プログラム実行時にキャリブレーションを実行する場合は以下のコードを実行する
        # print('Calibrate ColorSensor ...')
        # line_tracer.calibrate_color_sensor()

        print('Configurating Odometry ...')
        odometry = Odometry()

        print('Guide is Ready')

        # タッチセンサー押し待ち
        wait_for_input()

        speed_reference = 0
        direction = 0
        odometry_speed_reference = 0
        odometry_direction = 0
        refrection_raw = 0

        angle_l = 0
        angle_r = 0

        # スタート時の時間取得
        t_line_trace_start = clock()

        while True:
            ###############################################################
            ##  Loop info
            ###############################################################
            t_loop_start = clock()

            # ここでライントレースする
            speed_reference, direction, refrection_raw = line_tracer.line_tracing(
            )

            # 角度を算出してオドメトリーを使用
            angle_l = sh_mem.read_motor_encoder_left_mem()
            angle_r = sh_mem.read_motor_encoder_right_mem()
            # odometry_speed_reference, odometry_direction = odometry.target_trace(angle_l,angle_r)
            # direction = odometry_direction
            # speed_reference = odometry_speed_reference

            # 左右モーターの角度は下記のように取得
            # print(read_motor_encoder_left_mem())
            # print(read_motor_encoder_right_mem())

            # 前進後退・旋回スピードは下記のように入力
            sh_mem.write_speed_mem(speed_reference)
            sh_mem.write_steering_mem(int(round(direction)))

            # 実行時間、PID制御に関わる値をログに出力
            t_loop_end = clock()
            # logs[log_pointer] = "{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}".format(
            logs[log_pointer] = "{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}".format(
                t_loop_end - t_line_trace_start, t_loop_end - t_loop_start,
                speed_reference, direction, refrection_raw,
                line_tracer.refrection_target, line_tracer.e_b,
                line_tracer.p_b, line_tracer.i_b, line_tracer.d_b, angle_l,
                angle_r
                # ,
                # odometry.pre_pos_x,
                # odometry.pre_pos_y,
                # odometry_direction,
                # odometry_speed_reference
            )
            log_pointer += 1

            ###############################################################
            ##  Busy wait for the loop to complete
            ###############################################################
            sleep(max(loop_time_sec - (clock() - t_loop_start), 0.002))

    except Exception as e:
        print("It's a Guide Exception")
        g_log.exception(e)
        shutdown_child()
Exemplo n.º 26
0
from odometry import Odometry
from controller import WheeledRobotController
from math import pi
from ev3dev import ev3
from logger import Logger

odometry = Odometry(ev3.LargeMotor("outB"), ev3.LargeMotor("outC"), 6.0, 2.7,
                    10.0, 2 * pi / 5.0)

controller = WheeledRobotController(ev3.UltrasonicSensor("in2"),
                                    ev3.UltrasonicSensor("in1"),
                                    ev3.UltrasonicSensor("in3"), odometry)

logger = Logger("resources/map.csv")
controller.run_closed_loop(kp=0.025,
                           ki=0.0,
                           kd=0.012,
                           avg_n=4,
                           stop_threshold=5.0,
                           logger=logger,
                           delta=0.1)
logger.complete()
Exemplo n.º 27
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()
        self.map = np.loadtxt("map14.txt", delimiter=",")
        self.odometry = Odometry()
        self.search = AStar(self.map)
        self.location = (0,0)
        self.orientation = "east"
        self.pidTheta = pid_controller.PIDController(200, 25, 5, [-1, 1], [-200, 200], is_angle=True)
        self.pidDistance = pid_controller.PIDController(100, 15, 5, [-10, 10], [-200, 200], is_angle=False)
        self.base_speed = 50
        
    def goToGoal(self, goal, state):
        goal_y = goal[1] / 30
        goal_x = goal[0] / 30
        self.odometry.update(state.leftEncoderCounts, state.rightEncoderCounts)
        goal_theta = math.atan2(goal_y - self.odometry.y, goal_x - self.odometry.x)
        theta = math.atan2(math.sin(self.odometry.x), math.cos(self.odometry.y))
        output_theta = self.pidTheta.update(self.odometry.theta, goal_theta, self.time.time())

        # improved version 2: fuse with velocity controller
        self.distance = math.sqrt(math.pow(goal_x - self.odometry.x, 2) + math.pow(goal_y - self.odometry.y, 2))
        output_distance = self.pidDistance.update(0, self.distance, self.time.time())
        self.create.drive_direct(int(output_theta + output_distance)+self.base_speed, int(-output_theta + output_distance)+self.base_speed)
        return output_distance
        
    def shouldIContinueAlongMyPath(self):
        #First scan ahead
        distance = self.sonar.get_distance()
        if distance < 0.5:
            #Then add the obstacle to the map
            if self.orientation == "east":
                self.map[(self.location[0], self.location[1]+1)] = 1
            elif self.orientation == "west":
                self.map[(self.location[0], self.location[1]-1)] = 1
            elif self.orientation == "north":
                self.map[(self.location[0]-1, self.location[1])] = 1
            else:
                self.map[(self.location[0]+1, self.location[1])] = 1
            return False
        return True
    
    def moveOneSquare(self, goal):
        startX = self.odometry.x
        startY = self.odometry.y
        while True:
            print("Moving")
            #Get state and update the odometry
            self.state = self.create.update()
            while not self.state:
                self.state = self.create.update()
            if abs(self.goToGoal(goal, self.state)) < 10:
                break
        if self.orientation == "east":
            self.location = (self.location[0], self.location[1]+1)
        elif self.orientation == "west":
            self.location = (self.location[0], self.location[1]-1)
        elif self.orientation == "south":
            self.location = (self.location[0]+1, self.location[1])
        else:
            self.location = (self.location[0]-1, self.location[1]+1)
    
    def turnCreate(self, goalTheta, state, pos):
        self.odometry.update(state.leftEncoderCounts, state.rightEncoderCounts)
        theta = math.atan2(math.sin(self.odometry.theta), math.cos(self.odometry.theta))
        output_theta = self.pidTheta.update(self.odometry.theta, goalTheta, self.time.time())
        # improved version 2: fuse with velocity controller
        if pos:
            self.create.drive_direct(int(output_theta), int(-output_theta))
        else:
            self.create.drive_direct(-int(output_theta), int(output_theta))

        return output_theta
    
    def turnTowardsPoint(self, nextPoint):
        startTheta = self.odometry.theta
        if nextPoint[0] < self.location[0]:
            print("Turning north")
            #Then turn north
            goalTheta = math.pi / 2
            while True:
                #Get state
                self.state = self.create.update()
                while not self.state:
                    self.state = self.create.update()
                if abs(self.turnCreate(goalTheta, self.state, True)) < 10:
                    break
            print("Done turning")
            self.orientation = "north"
        elif nextPoint[0] > self.location[0]:
            print("Turning south")
            #Then turn south
            goalTheta = 3 * math.pi / 2
            while True:
                #Get state
                self.state = self.create.update()
                while not self.state:
                    self.state = self.create.update()
                if abs(self.turnCreate(goalTheta, self.state, True)) < 10:
                    break
            print("Done turning")
            self.orientation = "south"
        elif nextPoint[1] < self.location[1]:
            print("Turning west")
            #Then turn west
            goalTheta = math.pi
            while True:
                #Get state
                self.state = self.create.update()
                while not self.state:
                    self.state = self.create.update()
                if abs(self.turnCreate(goalTheta, self.state, True)) < 10:
                    break
            print("Done turning")
            self.orientation = "west"
        else:
            print("Turning east")
            #Then turn east
            goalTheta = 0
            while True:
                #Get state
                self.state = self.create.update()
                while not self.state:
                    self.state = self.create.update()
                if abs(self.turnCreate(goalTheta, self.state, True)) < 10:
                    break
            print("Done turning")
            self.orientation = "east"
        
    def goOnPath(self, path):
        for x, y in path:
            if (x, y) == self.location:
                pass
            #Turn towards the point
            print("Turning towards Point ", (x, y))
            self.turnTowardsPoint((x,y))
            #If point is now obstacle, go in a new path
            if self.shouldIContinueAlongMyPath():
                #Move towards point
                print("No obstacle. Moving toward point")
                self.moveOneSquare((x,y))
            else:
                return False
        return True
        
    def run(self):
        self.create.start()
        self.create.safe()
        
        # request sensors
        self.create.start_stream([
            create2.Sensor.LeftEncoderCounts,
            create2.Sensor.RightEncoderCounts,
        ])
        
        self.state = self.create.update()
        while not self.state:
            self.state = self.create.update()
        self.odometry.update(self.state.leftEncoderCounts, self.state.rightEncoderCounts)
        
        self.location = (9,1)#(self.odometry.x, self.odometry.y)
        goal_pos = (1,9)
        
        path = self.search.a_star(self.location, goal_pos)
        
        print("Path is: ",path)
        
        #Now go on that path
        while not self.goOnPath(path):
            path = self.search.a_star(self.location, goal_pos)
            path.remove(self.location)
            print("New Path is: ", path)
        print("Done! I am at goal.")
        
Exemplo n.º 28
0
class Run:
    def __init__(self, factory):
        """Constructor.

        Args:
            factory (factory.FactoryCreate)
        """
        self.create = factory.create_create()
        self.time = factory.create_time_helper()
        self.odometry = Odometry(robotProperties["diameter_left"],
                                 robotProperties["diameter_right"],
                                 robotProperties["wheel_base"],
                                 robotProperties["encoder_count"])
        # self.my_robot = MyRobot(None, self.create, self.time, self.odometry)
        self.x = 0.0
        self.y = 0.0
        self.angle = 0.0
        self.prev_r_count = 0
        self.prev_l_count = 0

    def print_odometry(self, state_):
        delta_r = self.odometry.get_delta_r(state_.rightEncoderCounts -
                                            self.prev_r_count)
        delta_l = self.odometry.get_delta_l(state_.leftEncoderCounts -
                                            self.prev_l_count)
        self.prev_r_count = state_.rightEncoderCounts
        self.prev_l_count = state_.leftEncoderCounts

        delta_theta = self.odometry.get_delta_theta(delta_r=delta_r,
                                                    delta_l=delta_l)
        delta_d = self.odometry.get_delta_d(delta_r=delta_r, delta_l=delta_l)

        print("[delta_r = %f, delta_l = %f, delta_d = %f, delta_theta = %f]" %
              (delta_r, delta_l, delta_d, delta_theta))
        self.x += delta_d * np.cos(self.angle)
        self.y += delta_d * np.sin(self.angle)
        self.angle += delta_theta
        print("[x = %f, y = %f, angle = %f]\n" %
              (self.x, self.y, np.rad2deg(self.angle)))

    def run(self):
        def move_robot(is_print: bool = False):
            # move forward
            self.my_robot.forward(5 * 0.1, is_print=is_print)

            # left turn (in place)
            self.my_robot.turn_left(2, is_print=is_print)

            # wait
            self.my_robot.wait(2, is_print=is_print)

            # right turn (in place)
            self.my_robot.turn_right(2, is_print=is_print)

            # wait
            self.my_robot.wait(2, is_print=is_print)

            # move forward
            self.my_robot.forward(2 * 0.1, is_print=is_print)

            # move forward while turning
            self.my_robot.move(0.2, 0.1, 7.5, is_print=is_print)

            # move forward
            self.my_robot.forward(5 * 0.1, is_print=is_print)

            # move backwards
            self.my_robot.backward(5 * 0.1, is_print=is_print)

            # stop
            self.my_robot.wait(3, is_print=is_print)

        self.create.start()
        self.create.safe()

        # request sensors
        self.create.start_stream([
            create2.Sensor.LeftEncoderCounts,
            create2.Sensor.RightEncoderCounts,
        ])

        # move forward
        while self.time.time() < 10:
            self.create.drive_direct(50, 50)
            state = self.create.update()
            if state is not None:
                print(state.__dict__)
                self.print_odometry(state)

        print("\n--------------reverse----------------")
        start_time = self.time.time()
        while self.time.time() - start_time < 10:
            self.create.drive_direct(-50, -50)
            state = self.create.update()
            if state is not None:
                print(state.__dict__)
                self.print_odometry(state)

        print("\n--------------turning----------------")
        start_time = self.time.time()
        while self.time.time() - start_time < 10:
            self.create.drive_direct(50, -50)
            state = self.create.update()
            if state is not None:
                print(state.__dict__)
                self.print_odometry(state)
Exemplo n.º 29
0
class Roomba:
    def __init__(self, device_path):
        self.device = serial.Serial(device_path, 115200, timeout=0.5)
        self.write_lock = threading.Lock()

        self.device.write(chr(128) * 3)
        self.device.write(chr(131))

        self.odometry = Odometry()
        self.bumpers = [False, False]
        self.drops = [False, False]

        self.wall = False
        self.cliff = [False, False, False, False]

        self.vwall = False
        self.dirt = 0

        self.buttons = [False, False, False]

        self.charging = 0
        self.charge_current = 0
        self.charge_voltage = 0

        self._odom_left = 0
        self._odom_right = 0
        self._odom_last = [0, 0]
        self._odom_start = True

        self.joint_positions = [0, 0, 0, 0]

        self.temperature = 0
        self._packets = [
            7, 8, 9, 10, 11, 12, 13, 14, 15, 18, 43, 44, 21, 22, 24, 25
        ]
        self._i = 0

        self._unmeasured = [False, False]

    def send_drive(self, forward, rotate):
        left = (forward - rotate * 0.28 / 2.0)
        right = (forward + rotate * 0.28 / 2.0)

        left *= 1000
        right *= 1000

        left = min(500, max(-500, left))
        right = min(500, max(-500, right))
        print(left, right)

        self.device.write(struct.pack("!Bhh", 145, left, right))

    def send_vacum(self, vacum, brush, side, side_clockwise):
        bitfield = 0
        bitfield += int(vacum) << 1
        bitfield += int(brush) << 2
        bitfield += int(side) << 0
        bitfield += int(side_clockwise) << 3

        self._unmeasured = [brush, side]

        self.device.write(chr(138) + chr(bitfield))

    def update_fake_joints(self, duration):
        self.joint_positions[2] += duration * int(self._unmeasured[0]) * 12
        self.joint_positions[3] += duration * int(self._unmeasured[1]) * 20

    def send_leds(self, check, dock, spot, debris, cc, ci):
        bitfield = int(check) << 3
        bitfield += int(dock) << 2
        bitfield += int(debris) << 1
        bitfield += int(debris)

        self.device.write(struct.pack("!BBBB", 139, bitfield, cc, ci))

    def read_sensor(self):
        self.device.write(chr(149))
        self.device.write(chr(len(self._packets)))
        for i in self._packets:
            self.device.write(chr(i))
        self._i = 0
        rospy.sleep(0.005)
        for i in self._packets:
            self._read_data()
        print("B")

    def _read_data(self):
        pid = self._packets[self._i]
        self._i += 1
        self._i %= len(self._packets)
        if pid == 7:
            dat = ord(self.device.read(1))
            self.bumpers[1] = (dat & 0x1) != 0
            self.bumpers[0] = (dat & 0x2) != 0
            self.drops[1] = (dat & 0x4) != 0
            self.drops[0] = (dat & 0x8) != 0
            return 2
        elif pid == 8:
            self.wall = self.device.read(1) == chr(1)
            return 2
        elif 9 <= pid <= 12:
            self.cliff[pid - 9] = self.device.read(1) == chr(1)
            return 2
        elif pid == 13:
            self.vwall = self.device.read(1) == chr(1)
            return 2
        elif pid == 14 or pid == 16 or pid == 17:
            self.device.read(1)
            return 2
        elif pid == 15:
            self.dirt = ord(self.device.read(1)) / 255.0
            return 2
        elif pid == 18:
            dat = ord(self.device.read(1))
            self.buttons[0] = (dat & 0x1)
            self.buttons[1] = (dat & 0x2)
            self.buttons[2] = (dat & 0x4)
            return 2
        elif pid == 21:
            self.charging = ord(self.device.read(1))
            return 2
        elif pid == 22:
            self.charge_voltage = struct.unpack(
                "!H", self.device.read(2))[0] / 1000.0
            return 3
        elif pid == 23:
            self.device.read(2)
            return 3
        elif pid == 24:
            self.temperature = struct.unpack("!b", self.device.read(1))[0]
            return 2
        elif pid == 25:
            self.charge_current = struct.unpack(
                "!H", self.device.read(2))[0] / 1000.0
            return 3
        elif pid == 26:
            self.device.read(2)
            return 3
        elif pid == 43:
            self._odom_left = struct.unpack("!h", self.device.read(2))[0]
            return 3
        elif pid == 44:
            self._odom_right = struct.unpack("!h", self.device.read(2))[0]

            if self._odom_start:
                self._odom_start = False
                self._odom_last = [self._odom_left, self._odom_right]
                return
            # conversion:

            left = self._odom_left - self._odom_last[0]
            right = self._odom_right - self._odom_last[1]

            if left < -32768:
                left += 65536
            elif left > 32767:
                left -= 65536

            if right < -32768:
                right += 65536
            elif right > 32767:
                right -= 65536

            distance = (left + right) / 2
            distance = (distance / encoder_counts) * 2 * math.pi
            distance *= wheel_radius

            angle = (
                ((right / encoder_counts) * 2 * math.pi * wheel_radius) -
                ((left / encoder_counts) * 2 * math.pi * wheel_radius)) / 0.28
            print("ang", angle)
            self.odometry.integrate(distance, angle)

            self._odom_last = [self._odom_left, self._odom_right]

            self.joint_positions[0] += (left / encoder_counts) * 2 * math.pi
            self.joint_positions[1] += (right / encoder_counts) * 2 * math.pi

            return 3
        return 1
Exemplo n.º 30
0
class Robot(object):
    cycle_time = 0.01
    enabled = False
    odometry = Odometry(cycle_time)

    def __init__(self, gui):
        self.gui = gui
        self.drive = Drive(self, gui)

    def initialize(self):
        sensors.initSensors()

    def startLoop(self):
        if (not self.enabled):
            self.gui.log_message("Starting Main Robot Loop")
            self.enabled = True
            self.initialize()
            self.drive.initDrive()
            self.odometry.reset()
            self.drive.setEnableIntersection(self.gui.getIntersectionEnabled())
            self.drive.setEnableEntering(self.gui.getEnteringEnabled())
            self.main_thread = threading.Thread(target=self.loop)
            self.main_thread.start()

    def stopLoop(self):
        if (self.enabled):
            self.gui.log_message("Stopping Main Robot Loop")
            self.enabled = False

    def loop(self):
        loop_counter = 0
        self.current = RigidTransform2d(Translation2d(0, 0),
                                        Rotation2d.fromDegrees(0))

        while (self.enabled):
            loop_counter += 1

            #self.gui.log_message("robot main")

            # Able to decrease sensor update frequency
            if (loop_counter % 1 == 0):
                sensors.updateSensors()

            self.odometry.updateOdometry()
            self.drive.updateDrive()

            if (loop_counter % 1 == 0):
                self.current = self.odometry.getFieldToVehicle()

                self.gui.log_pos(self.current)
                self.gui.log_sonics(sensors.getLeftWallDistance(),
                                    sensors.getForwardWallDistance(),
                                    sensors.getRightWallDistance())
                self.gui.log_mag(sensors.getMagneticMagnitude())
                self.gui.log_ir(0.0, 0.0)
                self.gui.log_state(self.drive.state)

            if (loop_counter >= 1000):
                loop_counter = 0

            time.sleep(self.cycle_time)

        sensors.shutdown()
Exemplo n.º 31
0
class Run:
    def __init__(self, factory):
        """Constructor.

        Args:
            factory (factory.FactoryCreate)
        """
        self.create = factory.create_create()
        self.time = factory.create_time_helper()

        self.odometry = Odometry()
        self.pd_controller = PDController(500, 100, -75, 75)
        # self.pid_controller = PIDController(500, 100, 0, -75, 75, -50, 50)
        self.pid_controller = PIDController(500, 100, 10, -100, 100, -100, 100)
        self.pid_controller_dist = PIDController(500, 100, 10, -100, 100, -100,
                                                 100)

    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)
                # print("[{},{},{}]".format(self.odometry.x, self.odometry.y, np.rad2deg(self.odometry.theta)))
            t = self.time.time()
            if start + time_in_sec <= t:
                break

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

        # request sensors
        self.create.start_stream([
            create2.Sensor.LeftEncoderCounts,
            create2.Sensor.RightEncoderCounts,
        ])

        plt_time_arr = np.array([])
        plt_angle_arr = np.array([])
        plt_goal_angle_arr = np.array([])

        goal_x = -0.5
        goal_y = -0.5
        goal_coor = np.array([goal_x, goal_y])
        goal_angle = np.arctan2(goal_y, goal_x)
        goal_angle %= 2 * np.pi
        print("goal angle = %f" % np.rad2deg(goal_angle))
        base_speed = 100
        # timeout = abs(17 * (goal_angle / np.pi)) + 1
        goal_r = 0.05

        angle = self.odometry.theta
        dist_to_goal = dist(goal_coor,
                            np.array([self.odometry.x, self.odometry.y]))

        plt_time_arr = np.append(plt_time_arr, self.time.time())
        plt_angle_arr = np.append(plt_angle_arr, angle)
        plt_goal_angle_arr = np.append(plt_goal_angle_arr, goal_angle)

        while abs(dist_to_goal) > goal_r:
            goal_angle = np.arctan2(goal_y - self.odometry.y,
                                    goal_x - self.odometry.x)
            goal_angle %= 2 * np.pi
            print("(%f, %f), dist to goal = %f\n" %
                  (self.odometry.x, self.odometry.y, dist_to_goal))
            dist_to_goal = dist(goal_coor,
                                np.array([self.odometry.x, self.odometry.y]))
            angle = self.odometry.theta

            plt_angle_arr = np.append(plt_angle_arr, angle)
            plt_goal_angle_arr = np.append(plt_goal_angle_arr, goal_angle)

            # output = self.pd_controller.update(angle, goal_angle, self.time.time())
            output = self.pid_controller.update(angle, goal_angle,
                                                self.time.time())
            output_dist = self.pid_controller_dist.update(
                0, dist_to_goal, self.time.time())

            self.create.drive_direct(int(base_speed + output),
                                     int(base_speed - output))
            # self.create.drive_direct(
            #     int((dist_to_goal * base_speed) + output),
            #     int((dist_to_goal * base_speed) - output)
            # )
            # self.create.drive_direct(
            #     int(output_dist + output),
            #     int(output_dist - output)
            # )
            self.sleep(0.01)

        np.savetxt("timeOutput.csv", plt_time_arr, delimiter=",")
        np.savetxt("angleOutput.csv", plt_angle_arr, delimiter=",")
        np.savetxt("goalAngleOutput.csv", plt_goal_angle_arr, delimiter=",")
Exemplo n.º 32
0
class Robot:

    def __init__(self, mqtt_client, logger):
        # Create Planet and planet_name variable
        self.planet = Planet()
        self.planet_name = None

        # Setup Sensors, Motors and Odometry
        self.rm = ev3.LargeMotor("outB")
        self.lm = ev3.LargeMotor("outC")
        self.sound = ev3.Sound()
        self.odometry = Odometry(self.lm, self.rm)
        self.motors = Motors(self.odometry)
        self.cs = ColorSensor(self.motors)
        self.us = Ultrasonic()

        # Setup Communication
        self.communication = Communication(mqtt_client, logger, self)

        # Create variable to write to from communication
        self.start_location = None
        self.end_location = None
        self.path_choice = None
        self.running = True

    def run(self):
        counter = 0
        bottle_detected = False
        previous_l, previous_r, previous_b = 0, 0, 350

        start_message = """
##################################
#                                #
#     RoboLab Praktikum 2020     #
#      Exploration by Paula      #
#          ❰❱ with ❤ by          #
#        Eric, Marc, Nico        #
#                                #
##################################
                        """
        # Print start screen
        print(start_message)

        # Calibrate colors for better color accuracy
        self.cs.calibrate_colors()

        # Wait until we want to start
        print("» Press Button to start")
        sensors.button_pressed()
        start_time = time.time()
        print(time.strftime("Starttime: %H:%M:%S", time.localtime()))

        print("Lets start to explore...")

        # Start fancy features
        feature_threads = features.start_features(self)

        # Main robot loop
        while self.running:
            # Test if robot detect an obstacle
            if self.us.get_distance() < 15:
                # Rotate robot to drive back, and save that an obstacle was detected
                self.sound.play("/home/robot/src/assets/found.wav")
                print("Obstacle detected")
                self.cs.rotate_to_path(180)
                bottle_detected = True
                continue

            # Test if robot reached node
            if self.cs.get_node() in ["blue", "red"] and counter == 0:
                counter += 1

                # Drive to center of node to better scanning
                self.motors.drive_in_center_of_node(100, 2)

                # Check if robot reached first node
                if self.planet_name is None:
                    # Tell mothership to send planet information (planet_name and start coordinates)
                    self.communication.send_ready()

                    # Wait until message is received
                    while self.planet_name is None:
                        pass

                    # Reset odometry of last path, not used for first path
                    self.odometry.reset_list()

                    # Current robot orientation
                    forward_dir = self.start_location[1]

                    # End-position and direction of incoming path
                    self.end_location = (self.start_location[0], (forward_dir + 180) % 360)

                    # Save path as blocked for better path calculation
                    self.planet.add_path(self.end_location, self.end_location, -1)
                else:
                    # Test if path is known
                    if self.start_location[0] in self.planet.planet_dict \
                            and self.start_location[1] in self.planet.planet_dict[self.start_location[0]]:
                        # Get end node from planet dictionary
                        ((x, y), send_dir, _) = self.planet.planet_dict[self.start_location[0]][self.start_location[1]]

                        # Reset odometry of last path, not used for first path
                        self.odometry.reset_list()
                    else:
                        # Calculate postion and direction from odometry
                        x, y, forward_dir = self.odometry.calculate_path(
                            self.start_location[1], bottle_detected, self.start_location[0][0], self.start_location[0][1])

                        # Direction facing back, used for path-message
                        send_dir = (forward_dir + 180) % 360

                    # Send path to mothership get real position and direction
                    self.communication.send_path(self.start_location, ((x, y), send_dir), bottle_detected)

                    # Wait until message is received
                    while self.end_location is None:
                        pass

                # Position of current node
                current_pos = self.end_location[0]
                # Direction of robot
                forward_dir = (self.end_location[1] + 180) % 360

                # Test if robot already scanned node
                if current_pos in self.planet.scanned_nodes:
                    # If scanned, wait if mothership sends information like target and pathUnveiled
                    time.sleep(2)
                else:
                    # Scan node for posible directions
                    possible_dirs = self.cs.analyze(forward_dir)

                    # Save direction into unexlored edges if they aren't in the planet dictionary
                    for d in possible_dirs:
                        if current_pos not in self.planet.planet_dict \
                                or d not in self.planet.planet_dict[current_pos].keys():
                            self.planet.add_unexplored_edge(current_pos, d)

                    # Mark node as scanned
                    self.planet.scanned_nodes.append(current_pos)

                # Test if robot reached the target
                if current_pos == self.planet.target:
                    # Send targetReached to mothership
                    self.communication.send_target_reached("Target reached!")

                    # Wait until confirmation
                    while self.running:
                        pass
                    self.sound.play("/home/robot/src/assets/smb_stage_clear.wav")
                    continue

                # Calculate next direction based on planet information and posible directions
                next_dir = self.choose_dir()

                # If no direction is found: Exloration completed
                if next_dir == -1:
                    # Send explorationCompleted to mothership
                    self.communication.send_exploration_completed("Exloration completed!")

                    # Wait until confirmation
                    while self.running:
                        pass
                    self.sound.play("/home/robot/src/assets/metroid.wav")
                    continue

                # Save new starting postion for next path
                self.start_location = (self.end_location[0], next_dir)

                # Rotate to new path
                self.cs.select_new_path(forward_dir, next_dir)

                # Reset variables
                self.end_location = None
                bottle_detected = False
                self.odometry.reset_position()
            else:
                # Follow line and save last data for next tick
                previous_l, previous_r, previous_b = self.motors.follow_line(self.cs, previous_l, previous_r, previous_b)
                # new (better solution?) -> multiple times calles -> ticks_previous needed
                counter = 0

        print(time.strftime("Endtime: %H:%M:%S", time.localtime()))
        delta = (time.time() - start_time) / 60
        print("Timedelta: %.2f min" % delta)

        for thread in feature_threads:
            thread.join()

    def choose_dir(self):
        # Next direction, -1 = no direction found
        choice = -1

        # Test if target is set
        if self.planet.target is not None:
            # Calculate shortest path to target
            shortest = self.planet.shortest_path(self.end_location[0], self.planet.target)

            # Test if target is reachable
            if shortest is not None:
                # Select first direction to get to target
                choice = shortest[0][1]

        # Test if no direction is set (no target or target not reachable)
        if choice == -1:
            # Nodes which need be explored
            incomplete_nodes = []
            # Shortest distance to unexplored node
            distance = math.inf
            # Nearest node
            nearest = None

            # Collect all node, which have open paths
            for node in self.planet.unexplored_edges.keys():
                incomplete_nodes.append(node)

            # Collect all node, which aren't scanned
            for node in self.planet.get_nodes():
                if node not in self.planet.scanned_nodes:
                    incomplete_nodes.append(node)

            # Test if all nodes are explored
            if len(incomplete_nodes) == 0:
                return -1

            # Calculate nearest open node
            for node in incomplete_nodes:
                cur = self.planet.shortest_distance(self.end_location[0], node)
                if cur < distance:
                    distance = cur
                    nearest = node

            # Test if no open node is reachable (explorationCompleted)
            if distance == math.inf:
                return -1
            # Test if open node is reached, choose first open path
            elif distance == 0:
                choice = self.planet.unexplored_edges[nearest][0]
            # Otherwise drive to open node (select first direction to get to open node)
            else:
                choice = self.planet.shortest_next_dir(self.end_location[0], nearest)

        # Send pathSelect to mothership
        self.communication.send_path_select((self.end_location[0], choice))

        # Wait until message receive or 3sec (answer optional)
        start_time = time.time()
        while self.path_choice is None and time.time() - start_time < 3.0:
            pass

        # Test if mothership overwrites direction, use forced direction
        if self.path_choice is not None:
            choice = self.path_choice
        print("Next direction: %s" % Direction(choice))

        # Reset Variable
        self.path_choice = None

        # Play sound
        self.sound.play("/home/robot/src/assets/codecover.wav")

        return choice