Ejemplo n.º 1
0
    def __init__(self,
                 compass=CompassSensor(nb_lenses=60,
                                       fov=np.deg2rad(COMPASS_FOV)),
                 *args,
                 **kwargs):
        """

        :param init_pos: the initial position
        :type init_pos: np.ndarray
        :param init_rot: the initial orientation
        :type init_rot: np.ndarray
        :param condition:
        :type condition: Hybrid
        :param live_sky: flag to update the sky with respect to the time
        :type live_sky: bool
        :param rgb: flag to set as input to the network all the channels (otherwise use only green)
        :type rgb: bool
        :param compass: the compass sensor
        :type compass: CompassSensor
        :param visualiser:
        :type visualiser: Visualiser
        :param name: a name for the agent
        :type name: string
        """
        if 'fov' in kwargs.keys() and kwargs['fov'] is None:
            kwargs['fov'] = CXAgent.FOV

        super(CXAgent, self).__init__(*args, **kwargs)

        self._net = CX(noise=0., pontin=False)
        self.compass = compass
        self.bump_shift = 0.
        self.log = CXLogger()

        try:
            self.compass.load_weights()
        except Exception as e:
            print("No parameters found for compass.")
            print(e)

        if 'name' in kwargs.keys() and kwargs['name'] is None:
            self.name = "cx_agent_%02d" % self.id
Ejemplo n.º 2
0
def create_ephem_paths():
    # sensor design
    n = 60
    omega = 56
    theta, phi, fit = angles_distribution(n, float(omega))
    theta_t, phi_t = 0., 0.

    # ant-world
    noise = 0.0
    ttau = .06
    dx = 1e-02  # meters
    dt = 2. / 60.  # min
    delta = timedelta(minutes=dt)
    routes = load_routes()
    flow = dx * np.ones(2) / np.sqrt(2)
    max_theta = 0.


    def encode(theta, phi, Y, P, A, theta_t=0., phi_t=0., d_phi=0., nb_tcl=8, sigma=np.deg2rad(13),
               shift=np.deg2rad(40)):
        alpha = (phi + np.pi / 2) % (2 * np.pi) - np.pi
        phi_tcl = np.linspace(0., 2 * np.pi, nb_tcl, endpoint=False)  # TB1 preference angles
        phi_tcl = (phi_tcl + d_phi) % (2 * np.pi)

        # Input (POL) layer -- Photo-receptors
        s_1 = Y * (np.square(np.sin(A - alpha)) + np.square(np.cos(A - alpha)) * np.square(1. - P))
        s_2 = Y * (np.square(np.cos(A - alpha)) + np.square(np.sin(A - alpha)) * np.square(1. - P))
        r_1, r_2 = np.sqrt(s_1), np.sqrt(s_2)
        r_pol = (r_1 - r_2) / (r_1 + r_2 + eps)

        # Tilting (CL1) layer
        d_cl1 = (np.sin(shift - theta) * np.cos(theta_t) +
                 np.cos(shift - theta) * np.sin(theta_t) *
                 np.cos(phi - phi_t))
        gate = np.power(np.exp(-np.square(d_cl1) / (2. * np.square(sigma))), 1)
        w = -float(nb_tcl) / (2. * float(n)) * np.sin(phi_tcl[np.newaxis] - alpha[:, np.newaxis]) * gate[:, np.newaxis]
        r_tcl = r_pol.dot(w)

        R = r_tcl.dot(np.exp(-np.arange(nb_tcl) * (0. + 1.j) * 2. * np.pi / float(nb_tcl)))
        res = np.clip(3.5 * (np.absolute(R) - .53), 0, 2)  # certainty of prediction
        ele_pred = 26 * (1 - 2 * np.arcsin(1 - res) / np.pi) + 15
        d_phi += np.deg2rad(9 + np.exp(.1 * (54 - ele_pred))) / (60. / float(dt))

        return r_tcl, d_phi

    stats = {
        "max_alt": [],
        "noise": [],
        "opath": [],
        "ipath": [],
        "d_x": [],
        "d_c": [],
        "tau": []
    }

    avg_time = timedelta(0.)
    terrain = z_terrain.copy()
    for enable_ephemeris in [False, True]:
        if enable_ephemeris:
            print "Foraging with the time compensation mechanism."
        else:
            print "Foraging without the time compensation mechanism."

        # stats
        d_x = []  # logarithmic distance
        d_c = []
        tau = []  # tortuosity
        ri = 0

        print "Routes: ",
        for route in routes[::2]:
            net = CX(noise=0., pontin=False)
            net.update = True

            # sun position
            cur = datetime(2018, 6, 21, 10, 0, 0)
            seville_obs.date = cur
            sun.compute(seville_obs)
            theta_s = np.array([np.pi / 2 - sun.alt])
            phi_s = np.array([(sun.az + np.pi) % (2 * np.pi) - np.pi])

            sun_azi = []
            sun_ele = []
            time = []

            # outward route
            route.condition = Hybrid(tau_x=dx)
            oroute = route.reverse()
            x, y, yaw = [(x0, y0, yaw0) for x0, y0, _, yaw0 in oroute][0]
            opath = [[x, y, yaw]]

            v = np.zeros(2)
            tb1 = []
            d_phi = 0.

            for _, _, _, yaw in oroute:
                theta_n, phi_n = tilt(theta_t, phi_t, theta, phi + yaw)

                sun_ele.append(theta_s[0])
                sun_azi.append(phi_s[0])
                time.append(cur)
                sky.theta_s, sky.phi_s = theta_s, phi_s
                Y, P, A = sky(theta_n, phi_n, noise=noise)

                if enable_ephemeris:
                    r_tb1, d_phi = encode(theta, phi, Y, P, A, d_phi=d_phi)
                else:
                    r_tb1, d_phi = encode(theta, phi, Y, P, A, d_phi=0.)
                yaw0 = yaw
                _, yaw = np.pi - decode_sph(r_tb1) + phi_s

                net(yaw, flow)
                yaw = (yaw + np.pi) % (2 * np.pi) - np.pi
                v = np.array([np.sin(yaw), np.cos(yaw)]) * route.dx
                opath.append([opath[-1][0] + v[0], opath[-1][1] + v[1], yaw])
                tb1.append(net.tb1)

                cur += delta
                seville_obs.date = cur
                sun.compute(seville_obs)
                theta_s = np.array([np.pi / 2 - sun.alt])
                phi_s = np.array([(sun.az + np.pi) % (2 * np.pi) - np.pi])
            opath = np.array(opath)

            yaw -= phi_s

            # inward route
            ipath = [[opath[-1][0], opath[-1][1], opath[-1][2]]]
            L = 0.  # straight distance to the nest
            C = 0.  # distance towards the nest that the agent has covered
            SL = 0.
            TC = 0.
            tb1 = []
            tau.append([])
            d_x.append([])
            d_c.append([])

            while C < 15:
                theta_n, phi_n = tilt(theta_t, phi_t, theta, phi + yaw)

                sun_ele.append(theta_s[0])
                sun_azi.append(phi_s[0])
                time.append(cur)
                sky.theta_s, sky.phi_s = theta_s, phi_s
                Y, P, A = sky(theta_n, phi_n, noise=noise)

                if enable_ephemeris:
                    r_tb1, d_phi = encode(theta, phi, Y, P, A, d_phi=d_phi)
                else:
                    r_tb1, d_phi = encode(theta, phi, Y, P, A, d_phi=0.)
                _, yaw = np.pi - decode_sph(r_tb1) + phi_s
                motor = net(yaw, flow)
                yaw = (ipath[-1][2] + motor + np.pi) % (2 * np.pi) - np.pi
                v = np.array([np.sin(yaw), np.cos(yaw)]) * route.dx
                ipath.append([ipath[-1][0] + v[0], ipath[-1][1] + v[1], yaw])
                tb1.append(net.tb1)
                L = np.sqrt(np.square(opath[0][0] - ipath[-1][0]) + np.square(opath[0][1] - ipath[-1][1]))
                C += route.dx
                d_x[-1].append(L)
                d_c[-1].append(C)
                tau[-1].append(L / C)
                if C <= route.dx:
                    SL = L
                if TC == 0. and len(d_x[-1]) > 50 and d_x[-1][-1] > d_x[-1][-2]:
                    TC = C

                cur += delta
                seville_obs.date = cur
                sun.compute(seville_obs)
                theta_s = np.array([np.pi / 2 - sun.alt])
                phi_s = np.array([(sun.az + np.pi) % (2 * np.pi) - np.pi])

            ipath = np.array(ipath)
            d_x[-1] = np.array(d_x[-1]) / SL * 100
            d_c[-1] = np.array(d_c[-1]) / TC * 100
            tau[-1] = np.array(tau[-1])

            ri += 1

            avg_time += cur - datetime(2018, 6, 21, 10, 0, 0)

            stats["max_alt"].append(0.)
            stats["noise"].append(noise)
            stats["opath"].append(opath)
            stats["ipath"].append(ipath)
            stats["d_x"].append(d_x[-1])
            stats["d_c"].append(d_c[-1])
            stats["tau"].append(tau[-1])
            print ".",
        print ""
        print "average time:", avg_time / ri  # 1:16:40

    np.savez_compressed("data/pi-stats-ephem.npz", **stats)
Ejemplo n.º 3
0
def create_paths(noise_type="uniform"):
    global seville_obs, sun, dx

    # sensor design
    n = 60
    omega = 56
    theta, phi, fit = angles_distribution(n, float(omega))
    theta_t, phi_t = 0., 0.

    # sun position
    seville_obs.date = datetime(2018, 6, 21, 9, 0, 0)
    sun.compute(seville_obs)
    theta_s = np.array([np.pi / 2 - sun.alt])
    phi_s = np.array([(sun.az + np.pi) % (2 * np.pi) - np.pi])

    # ant-world
    noise = 0.0
    ttau = .06
    dx = 1e-02
    routes = load_routes()
    flow = dx * np.ones(2) / np.sqrt(2)
    max_theta = 0.

    stats = {
        "max_alt": [],
        "noise": [],
        "opath": [],
        "ipath": [],
        "d_x": [],
        "d_c": [],
        "tau": []
    }

    for max_altitude in [.0, .1, .2, .3, .4, .5]:
        for ni, noise in enumerate([0.0, 0.2, 0.4, 0.6, 0.8, .97]):

            # stats
            d_x = []  # logarithmic distance
            d_c = []
            tau = []  # tortuosity
            ri = 0

            for route in routes[::2]:
                dx = route.dx

                net = CX(noise=0., pontin=False)
                net.update = True

                # outward route
                route.condition = Hybrid(tau_x=dx)
                oroute = route.reverse()
                x, y, yaw = [(x0, y0, yaw0) for x0, y0, _, yaw0 in oroute][0]
                opath = [[x, y, yaw]]

                v = np.zeros(2)
                tb1 = []

                for _, _, _, yaw in oroute:
                    theta_t, phi_t = get_3d_direction(opath[-1][0], opath[-1][1], yaw, tau=ttau)
                    max_theta = max_theta if max_theta > np.absolute(theta_t) else np.absolute(theta_t)
                    theta_n, phi_n = tilt(theta_t, phi_t, theta, phi + yaw)

                    sky.theta_s, sky.phi_s = theta_s, phi_s
                    Y, P, A = sky(theta_n, phi_n, noise=get_noise(theta_n, phi_n, noise, mode=noise_type))

                    r_tb1 = encode(theta, phi, Y, P, A)
                    yaw0 = yaw
                    _, yaw = np.pi - decode_sph(r_tb1) + phi_s

                    net(yaw, flow)
                    yaw = (yaw + np.pi) % (2 * np.pi) - np.pi
                    v = np.array([np.sin(yaw), np.cos(yaw)]) * route.dx
                    opath.append([opath[-1][0] + v[0], opath[-1][1] + v[1], yaw])
                    tb1.append(net.tb1)
                opath = np.array(opath)

                yaw -= phi_s

                # inward route
                ipath = [[opath[-1][0], opath[-1][1], opath[-1][2]]]
                L = 0.  # straight distance to the nest
                C = 0.  # distance towards the nest that the agent has covered
                SL = 0.
                TC = 0.
                tb1 = []
                tau.append([])
                d_x.append([])
                d_c.append([])

                while C < 15:
                    theta_t, phi_t = get_3d_direction(ipath[-1][0], ipath[-1][1], yaw, tau=ttau)
                    theta_n, phi_n = tilt(theta_t, phi_t, theta, phi + yaw)

                    sky.theta_s, sky.phi_s = theta_s, phi_s
                    Y, P, A = sky(theta_n, phi_n, noise=noise)

                    r_tb1 = encode(theta, phi, Y, P, A)
                    _, yaw = np.pi - decode_sph(r_tb1) + phi_s
                    motor = net(yaw, flow)
                    yaw = (ipath[-1][2] + motor + np.pi) % (2 * np.pi) - np.pi
                    v = np.array([np.sin(yaw), np.cos(yaw)]) * route.dx
                    ipath.append([ipath[-1][0] + v[0], ipath[-1][1] + v[1], yaw])
                    tb1.append(net.tb1)
                    L = np.sqrt(np.square(opath[0][0] - ipath[-1][0]) + np.square(opath[0][1] - ipath[-1][1]))
                    C += route.dx
                    d_x[-1].append(L)
                    d_c[-1].append(C)
                    tau[-1].append(L / C)
                    if C <= route.dx:
                        SL = L
                    if TC == 0. and len(d_x[-1]) > 50 and d_x[-1][-1] > d_x[-1][-2]:
                        TC = C

                ipath = np.array(ipath)
                d_x[-1] = np.array(d_x[-1]) / SL * 100
                d_c[-1] = np.array(d_c[-1]) / TC * 100
                tau[-1] = np.array(tau[-1])

                ri += 1

                stats["max_alt"].append(max_altitude)
                stats["noise"].append(noise)
                stats["opath"].append(opath)
                stats["ipath"].append(ipath)
                stats["d_x"].append(d_x[-1])
                stats["d_c"].append(d_c[-1])
                stats["tau"].append(tau[-1])

    np.savez_compressed("../data/pi-stats-%s.npz" % noise_type, **stats)
Ejemplo n.º 4
0
class CXAgent(Agent):
    FOV = (-np.pi / 6, np.pi / 3)
    COMPASS_FOV = 60

    def __init__(self,
                 compass=CompassSensor(nb_lenses=60,
                                       fov=np.deg2rad(COMPASS_FOV)),
                 *args,
                 **kwargs):
        """

        :param init_pos: the initial position
        :type init_pos: np.ndarray
        :param init_rot: the initial orientation
        :type init_rot: np.ndarray
        :param condition:
        :type condition: Hybrid
        :param live_sky: flag to update the sky with respect to the time
        :type live_sky: bool
        :param rgb: flag to set as input to the network all the channels (otherwise use only green)
        :type rgb: bool
        :param compass: the compass sensor
        :type compass: CompassSensor
        :param visualiser:
        :type visualiser: Visualiser
        :param name: a name for the agent
        :type name: string
        """
        if 'fov' in kwargs.keys() and kwargs['fov'] is None:
            kwargs['fov'] = CXAgent.FOV

        super(CXAgent, self).__init__(*args, **kwargs)

        self._net = CX(noise=0., pontin=False)
        self.compass = compass
        self.bump_shift = 0.
        self.log = CXLogger()

        try:
            self.compass.load_weights()
        except Exception as e:
            print("No parameters found for compass.")
            print(e)

        if 'name' in kwargs.keys() and kwargs['name'] is None:
            self.name = "cx_agent_%02d" % self.id

    @property
    def sky(self):
        return self.world.sky

    @sky.setter
    def sky(self, value):
        self.world.sky = value

    def reset(self):
        if super(CXAgent, self).reset():
            # reset to the nest instead of the feeder
            self.pos[:2] = self.nest.copy()
            self.yaw = (self.homing_routes[-1].phi[-2] + np.pi) % (2 * np.pi)
            self._net.update = True

            return True
        else:
            return False

    def start_learning_walk(self):

        if self.world is None:
            # TODO: warn about not setting the world
            return None
        elif len(self.homing_routes) == 0:
            # TODO: warn about not setting the homing route
            return None

        print("Resetting...")
        self.reset()
        self.log.stage = "training"

        # initialise visualisation
        if self.visualiser is not None:
            self.visualiser.reset()

        # follow a reverse homing route
        rt = self.homing_routes[-1].reverse()  # type: Route

        # add a copy of the current route to the world to visualise the path
        self.log.add(self.pos[:3], self.yaw)
        self.world.routes.append(
            route_like(rt,
                       self.log.x,
                       self.log.y,
                       self.log.z,
                       self.log.phi,
                       self.condition,
                       agent_no=self.id - 1,
                       route_no=1))
        counter = 0  # count the steps

        phi_ = (np.array([np.pi - phi for _, _, _, phi in rt]) +
                np.pi) % (2 * np.pi) - np.pi
        # phi_ = np.roll(phi_, 1)  # type: np.ndarray

        for phi in phi_:
            if not self.step(phi, counter):
                break
            counter += 1

        self.log.update_outbound_end()
        # remove the copy of the route from the world
        rt = self.world.routes[-1]
        self.world.routes.remove(self.world.routes[-1])

        return rt  # return the learned route

    def start_homing(self, reset=True):
        if self.world is None:
            # TODO: warn about not setting the world
            return None

        if reset:
            print("Resetting...")
            super(CXAgent, self).reset()
        self.log.stage = "homing"

        # initialise the visualisation
        if self.visualiser is not None:
            self.visualiser.reset()

        phi, _ = self.update_state(np.pi - self.yaw)
        # add a copy of the current route to the world to visualise the path
        self.world.routes.append(
            route_like(self.world.routes[0],
                       self.log.x,
                       self.log.y,
                       self.log.z,
                       self.log.phi,
                       agent_no=self.id,
                       route_no=len(self.world.routes) + 1))

        counter = 0
        start_time = datetime.now()
        while self.d_nest > 0.1:
            if not self.step(phi, counter, start_time):
                break
            phi = np.pi - self.yaw
            counter += 1

        # remove the copy of the route from the world
        self.world.routes.remove(self.world.routes[-1])
        return Route(self.log.x,
                     self.log.y,
                     self.log.z,
                     self.log.phi,
                     condition=self.condition,
                     agent_no=self.id,
                     route_no=len(self.world.routes) + 1)

    def step(self, phi, counter=0, start_time=None, use_flow=False):
        # stop the loop when we close the visualisation window
        if self.visualiser is not None and self.visualiser.is_quit():
            return False

        sun = self.read_sensor()
        if isinstance(sun, np.ndarray) and sun.size == 8:
            heading = decode_sun(sun)[0]
        else:
            # heading = self.compass.sky.lon-self.yaw
            heading = sun

        if use_flow:
            self.world_snapshot()
            self.log.snap.append(self.world.eye.L[:, 0].flatten())
            # TODO: fix error in the optic-flow calculation
            # flow = self.get_flow(self.log.snap[-1], self.log.snap[-2] if len(self.log.snap) > 1 else None)
            v_trans = self.dx * np.array([np.sin(heading), np.cos(heading)])
            flow = self._net.get_flow(heading, v_trans)
        else:
            flow = self.dx * np.ones(2) / np.sqrt(2)

        # make a forward pass from the network
        if isinstance(sun, np.ndarray) and sun.size == 8:
            motor = self._net(sun,
                              flow,
                              tl2=self.compass.tl2,
                              cl1=self.compass.cl1)
        else:
            motor = self._net(sun, flow)

        phi, v = self.update_state(phi, rotation=motor)
        v_trans = self.transform_velocity(heading, v)

        self.log.update_hist(tl2=self._net.tl2,
                             cl1=self._net.cl1,
                             tb1=self._net.tb1,
                             cpu4=self._net.cpu4_mem,
                             cpu1=self._net.cpu1,
                             tn1=self._net.tn1,
                             tn2=self._net.tn2,
                             motor0=motor,
                             flow0=flow,
                             v0=v,
                             v1=v_trans,
                             phi=phi,
                             sun=heading)

        # update the route in the world
        self.world.routes[-1] = route_like(self.world.routes[-1], self.log.x,
                                           self.log.y, self.log.z,
                                           self.log.phi)

        # update view
        img_func = None
        if self.visualiser is not None and self.visualiser.mode == "top":
            img_func = self.world.draw_top_view
        elif self.visualiser is not None and self.visualiser.mode == "panorama":
            img_func = self.world_snapshot
        if self.visualiser is not None:
            names = self.name.split('_')
            names[0] = self.world.date.strftime(datestr)
            names.append(counter)
            names.append(self.d_feeder)
            names.append(self.d_nest)
            names.append(np.rad2deg(motor))
            n = 4
            if start_time is not None:
                now = datetime.now()
                now = now - start_time
                names.append(now.seconds // 60)
                names.append(now.seconds % 60)
                n += 2

            capt_format = "%s " * (
                len(names) -
                n) + "| C: % 2d D_f: % 2.2f D_n: % 2.2f MTR: % 3.1f | "
            if start_time is not None:
                capt_format += " | Elapsed time: %02d:%02d"

            self.visualiser.update_main(img_func,
                                        caption=capt_format % tuple(names))

        d_max = 2 * np.sqrt(np.square(self.feeder - self.nest).sum())
        if self.d_feeder > d_max and self.d_nest > d_max or counter > 20 / self.dx:
            return False

        return True

    def get_flow(self, now, previous=None):
        if previous is not None:
            flow = -get_sph_flow(
                n_val=np.array(now).flatten(),
                o_val=np.array(previous).flatten(),
                rdir=np.array([
                    self.world.eye.theta_global, self.world.eye.phi_global
                ]).T,
                rsensor=np.array(
                    [[0, self._net.tn_prefs], [0, -self._net.tn_prefs]])).mean(
                        axis=1)  # TODO: scale the value so that it fits better
            flow = self.dx * flow / np.sqrt(np.square(flow).sum())
        else:
            flow = self.dx * np.ones(2)
            # flow = self._net.get_flow(heading, v_trans)
        return flow

    def read_sensor(self, decode=False):
        self.compass.rotate(yaw=self.yaw - self.compass.yaw,
                            # pitch=self.pitch - self.compass.pitch
                            )
        self.compass.refresh()
        if decode:
            # sun = self.compass.facing_direction - self.world.sky.lon
            sun = self.compass(self.world.sky, decode=decode).flatten()
            sun = (sun[0] + np.pi) % (2 * np.pi) - np.pi
        else:
            sun = self.compass(self.world.sky, decode=decode).flatten()
            # sun = (sun / np.absolute(sun).max() + 1.) / 2.

        return sun

    def transform_velocity(self, heading, velocity):
        """

        :param heading:
        :param velocity:
        :type velocity: np.ndarray
        :return:
        """
        # R = np.array([[np.sin(heading), -np.cos(heading)],
        #               [np.cos(heading), np.sin(heading)]]).T

        r = np.sqrt(np.square(velocity).sum())
        return self.get_velocity(heading, r)
Ejemplo n.º 5
0
        # stats
        d_x = []  # logarithmic distance
        d_c = []
        tau = []  # tortuosity
        ri = 0

        print "Noise:", noise
        sky.theta_s, sky.phi_s = np.pi / 6, np.pi
        eta = get_noise(theta_sky, phi_sky, noise, noise_type)
        Y, P, A = sky(theta_sky, phi_sky, noise=eta)
        plt.figure("Sky-%d-%s" % (noise * 10, noise_type), figsize=(7.5, 2.5))
        plot_sky(phi_sky, theta_sky, Y, P, A)

        # for route in routes[::2]:
        for route in [routes[0]]:
            net = CX(noise=0., pontin=False)
            net.update = True

            # outward route
            route.condition = Hybrid(tau_x=dx)
            oroute = route.reverse()
            x, y, yaw = [(x0, y0, yaw0) for x0, y0, _, yaw0 in oroute][0]
            opath = [[x, y, yaw]]

            v = np.zeros(2)
            tb1 = []
            # print np.rad2deg(phi_s)

            # plt.figure("yaws")
            for _, _, _, yaw in oroute:
                if mode == "uneven":