Ejemplo n.º 1
0
    def test_cart2polar_and_polar2cart(self):
        # loop test
        expected = np.array([1,1,0,1,-1,0,-1,-1,0])
        np.testing.assert_almost_equal(utils.polar2cart(utils.cart2polar(expected)), expected)
        np.testing.assert_almost_equal(utils.cart2polar(utils.polar2cart(expected)), expected)

        expected = np.array([1,np.pi/4,np.pi/4,4,5,6,7,8,9])
        np.testing.assert_almost_equal(utils.polar2cart(utils.cart2polar(expected)), expected)
        np.testing.assert_almost_equal(utils.cart2polar(utils.polar2cart(expected)), expected)

        expected = np.array([1,np.pi*3/4,-np.pi/4,4,5,6,7,8,9])
        np.testing.assert_almost_equal(utils.polar2cart(utils.cart2polar(expected)), expected)
        np.testing.assert_almost_equal(utils.cart2polar(utils.polar2cart(expected)), expected)

        # approach target
        expected_car = np.array([1,1,0,-1,-1,0,0,0,0])
        expected_pol = np.array([np.sqrt(2),np.pi/4,0,-np.sqrt(2),0,0,0,0,0])
        np.testing.assert_almost_equal(utils.cart2polar(expected_car), expected_pol)
        np.testing.assert_almost_equal(utils.polar2cart(expected_pol), expected_car)

        # horizontal turn target
        expected_car = np.array([1,1,0,-1,1,0,-1,-1,0])
        expected_pol = np.array([np.sqrt(2),np.pi/4,0,0,1,0,0,0,0])
        np.testing.assert_almost_equal(utils.cart2polar(expected_car), expected_pol)
        np.testing.assert_almost_equal(utils.polar2cart(expected_pol), expected_car)

        # vertical turn target
        expected_car = np.array([1,0,-1,-1,0,-1,-1,0,+1])
        expected_pol = np.array([np.sqrt(2),0,np.pi/4,0,0,1,0,0,0])
        np.testing.assert_almost_equal(utils.cart2polar(expected_car), expected_pol)
        np.testing.assert_almost_equal(utils.polar2cart(expected_pol), expected_car)
Ejemplo n.º 2
0
def gen_dirty_img(visi, pos_mic_x, pos_mic_y, omega_band, sound_speed,
                  phi_plt):
    """
    Compute the dirty image associated with the given measurements. Here the Fourier transform
    that is not measured by the microphone array is taken as zero.
    :param visi: the measured visibilites
    :param pos_mic_x: a vector contains microphone array locations (x-coordinates)
    :param pos_mic_y: a vector contains microphone array locations (y-coordinates)
    :param omega_band: mid-band (ANGULAR) frequency [radian/sec]
    :param sound_speed: speed of sound
    :param phi_plt: plotting grid (azimuth on the circle) to show the dirty image
    :return:
    """
    img = np.zeros(phi_plt.size, dtype=complex)
    x_plt, y_plt = polar2cart(1, phi_plt)
    num_mic = pos_mic_x.size

    pos_mic_x_normalised = pos_mic_x / (sound_speed / omega_band)
    pos_mic_y_normalised = pos_mic_y / (sound_speed / omega_band)

    count_visi = 0
    for q in xrange(num_mic):
        p_x_outer = pos_mic_x_normalised[q]
        p_y_outer = pos_mic_y_normalised[q]
        for qp in xrange(num_mic):
            if not q == qp:
                p_x_qqp = p_x_outer - pos_mic_x_normalised[qp]  # a scalar
                p_y_qqp = p_y_outer - pos_mic_y_normalised[qp]  # a scalar
                # <= the negative sign converts DOA to propagation vector
                img += visi[count_visi] * \
                       np.exp(-1j * (p_x_qqp * x_plt + p_y_qqp * y_plt))
                count_visi += 1
    return img / (num_mic * (num_mic - 1))
Ejemplo n.º 3
0
    def compute_weights(self, direction=None):

        if direction is not None:
            self.direction = direction

        phi = self.direction * np.pi / 180.
        src = polar2cart(np.array([1, phi]))

        # near-field
        # dist_m = np.linalg.norm(self.L - np.tile(src, (self.M,1)).T,
        #     axis=0)
        # dist_c = np.linalg.norm(self.center-src)
        # dist_m = dist_m-dist_c

        # far-field
        dist_m = -np.dot(self.L.T, src)
        dist_m = dist_m - dist_m.min()

        for i, f in enumerate(self.frequencies):
            wavenum = 2 * np.pi * f / self.c
            # mode_vecs = 1./dist_m * np.exp(-1j*wavenum*dist_m) # near field model
            mode_vecs = np.exp(-1j * wavenum * dist_m)  # fair field model
            w = np.dot(
                H(mode_vecs),
                np.linalg.pinv(self.Rhat[i, :, :] +
                               self.mu * np.diag(self.Rhat[i, :, :]) *
                               np.identity(self.M, dtype=complex)))
            self.weights[i, :] = w / np.dot(w, mode_vecs)
Ejemplo n.º 4
0
    def compute_mode(self, freq, phi):

        X = polar2cart(np.array([1, phi]))

        dist = np.linalg.norm(self.L - np.tile(X, (self.M, 1)).T, axis=0)
        wavenum = 2 * np.pi * freq / self.c

        return np.exp(1j * wavenum * dist)
Ejemplo n.º 5
0
def gen_sig_at_mic(sigmak2_k,
                   phi_k,
                   pos_mic_x,
                   pos_mic_y,
                   omega_band,
                   sound_speed,
                   SNR,
                   Ns=256):
    """
    generate complex base-band signal received at microphones
    :param sigmak2_k: the variance of the circulant complex Gaussian signal
                emitted by the K sources
    :param phi_k: source locations (azimuths)
    :param pos_mic_x: a vector that contains microphones' x coordinates
    :param pos_mic_y: a vector that contains microphones' y coordinates
    :param omega_band: mid-band (ANGULAR) frequency [radian/sec]
    :param sound_speed: speed of sound
    :param SNR: SNR for the received signal at microphones
    :param Ns: number of snapshots used to estimate the covariance matrix
    :return: y_mic: received (complex) signal at microphones
    """
    num_mic = pos_mic_x.size
    xk, yk = polar2cart(1, phi_k)  # source locations in cartesian coordinates
    # reshape to use broadcasting
    xk = np.reshape(xk, (1, -1), order='F')
    yk = np.reshape(yk, (1, -1), order='F')
    pos_mic_x = np.reshape(pos_mic_x, (-1, 1), order='F')
    pos_mic_y = np.reshape(pos_mic_y, (-1, 1), order='F')

    t = np.reshape(np.linspace(0, 10 * np.pi, num=Ns), (1, -1), order='F')
    K = sigmak2_k.size
    sigmak2_k = np.reshape(sigmak2_k, (-1, 1), order='F')

    # x_tilde_k size: K x length_of_t
    # circular complex Gaussian process
    x_tilde_k = np.sqrt(sigmak2_k / 2.) * (np.random.randn(K, Ns) +
                                           1j * np.random.randn(K, Ns))
    y_mic = np.dot(
        np.exp(-1j * (xk * pos_mic_x + yk * pos_mic_y) /
               (sound_speed / omega_band)),
        x_tilde_k * np.exp(1j * omega_band * t))
    signal_energy = linalg.norm(y_mic, 'fro')**2
    noise_energy = signal_energy / 10**(SNR * 0.1)
    sigma2_noise = noise_energy / (Ns * num_mic)
    noise = np.sqrt(sigma2_noise / 2.) * (np.random.randn(*y_mic.shape) +
                                          1j * np.random.randn(*y_mic.shape))
    y_mic_noisy = y_mic + noise
    return y_mic_noisy, y_mic
Ejemplo n.º 6
0
    def compute_weights(self, direction=None):

        if direction is not None:
            self.direction = direction

        phi = self.direction*np.pi/180.
        src = utils.polar2cart(np.array([1, phi]))
        dist_m = np.linalg.norm(self.L - np.tile(src, (self.M,1)).T, 
            axis=0)

        for i, f in enumerate(self.frequencies):
            wavenum = 2*np.pi*f/self.c
            mode_vecs = 1./dist_m * np.exp(-1j*wavenum*dist_m) # near field model
            w = np.dot(H(mode_vecs),
                np.linalg.pinv(self.Rhat[i,:,:]+0.1*np.identity(self.M,dtype=complex)))
            self.weights[i,:] = w / np.dot(w,mode_vecs)
Ejemplo n.º 7
0
def gen_visibility(alphak, phi_k, pos_mic_x, pos_mic_y):
    """
    generate visibility from the Dirac parameter and microphone array layout
    :param alphak: Diracs' amplitudes
    :param phi_k: azimuths
    :param pos_mic_x: a vector that contains microphones' x coordinates
    :param pos_mic_y: a vector that contains microphones' y coordinates
    :return:
    """
    xk, yk = polar2cart(1, phi_k)
    num_mic = pos_mic_x.size
    visi = np.zeros((num_mic, num_mic), dtype=complex)
    for q in xrange(num_mic):
        p_x_outer = pos_mic_x[q]
        p_y_outer = pos_mic_y[q]
        for qp in xrange(num_mic):
            p_x_qqp = p_x_outer - pos_mic_x[qp]  # a scalar
            p_y_qqp = p_y_outer - pos_mic_y[qp]  # a scalar
            visi[qp, q] = np.dot(np.exp(-1j * (xk * p_x_qqp + yk * p_y_qqp)),
                                 alphak)
    return visi
Ejemplo n.º 8
0
    def compute_weights(self, direction=None):

        if direction is not None:
            self.direction = direction

        phi = self.direction * np.pi / 180.
        src = polar2cart(np.array([1, phi]))

        # near-field
        # dist_m = np.linalg.norm(self.L - np.tile(src, (self.M,1)).T,
        #     axis=0)
        # dist_c = np.linalg.norm(self.center-src)
        # self.dist_cent = dist_m-dist_c

        # far-field
        dist_m = -np.dot(self.L.T, src)
        self.dist_cent = dist_m - dist_m.max()

        for i, f in enumerate(self.frequencies):
            wavenum = 2 * np.pi * f / self.c
            self.weights[i, :] = np.exp(
                1j * wavenum * self.dist_cent) / self.L.shape[1]
Ejemplo n.º 9
0
	def step(self, dt, save_state=True, integration_method='leapfrog'):

		if integration_method == 'leapfrog':
			"""
			Works great, see here why: https://introcs.cs.princeton.edu/java/94diffeq/
			"""
			
			d = np.hypot(self.x, self.y)
			a = -constants.muE / d / d / d
			
			if self.utmdt is None or self.vtmdt is None:
				self.utmdt = self.u + a * self.x * -dt/2.
				self.vtmdt = self.v + a * self.y * -dt/2.

			ax = a * self.x 
			ay = a * self.y
			
			utpdt = self.utmdt + ax * dt
			vtpdt = self.vtmdt + ay * dt
			
			self.x += utpdt * dt 
			self.y += vtpdt * dt
			
			self.u = (self.utmdt + utpdt) / 2.
			self.v = (self.vtmdt + vtpdt) / 2.
			
			self.utmdt = utpdt
			self.vtmdt = vtpdt
			
		elif integration_method=='euler-r':
			"""
			Euler in polar coordinates
			Bad because of the many trigo computations
			"""
			r = np.hypot(self.x, self.y)
			_, theta = utils.cart2polar(self.u, self.v)
		
			rp = -np.sin(theta) * self.u + np.cos(theta) * self.v

			rp -= constants.muE / (r * r) * dt
			
			du, dv = utils.polar2cart(rp, np.pi/2.+theta)

			self.u += du
			self.v += dv 
		
			self.x += self.u * dt
			self.y += self.v * dt
		
		elif integration_method == 'euler':
			"""
			Okay, but not great
			"""
		
			d = np.hypot(self.x, self.y)
			a = -constants.muE / d / d / d
		
			self.u += a * self.x * dt
			self.v += a * self.y * dt
		
			self.x += self.u * dt 
			self.y += self.v * dt
		


		
		if save_state: 
			self.save_state()
Ejemplo n.º 10
0
	def plot(self, time_ticks=1, save=True, highlight_new_orbit=True):
		"""
		A lot of things here could be computed only once
		"""
		
		t = np.arange(len(self.target.speed_x)) * self.dt / self.chaser.P
		vtgt = np.hypot(self.target.speed_x, self.target.speed_y) * 1e-3
		vcha = np.hypot(self.chaser.speed_x, self.chaser.speed_y) * 1e-3
		
		#################################

		chaserspeed = np.array([self.chaser.speed_x, self.chaser.speed_y]).T
			
		vch = np.hypot(chaserspeed[:,0], chaserspeed[:,1])# * 1e-3
		chxy = np.array([self.chaser.trajectory_x, np.array(self.chaser.trajectory_y)])
		
		r = u.unit_vector(chxy).T
		
		aalpha = u.vangle_between(chaserspeed, r)
		
		dxo = 3. * np.pi * (self.target.a - self.chaser.a)
		
		v_bar = np.zeros_like(aalpha)
		for jjk in range(len(chxy[0])):
			try:
				vb = (self.distances.trajectory_x[jjk-1] - self.distances.trajectory_x[jjk]) / (self.dt)
			except:
				vb = np.nan 
			if jjk == 0:
				vb = np.nan
			v_bar[jjk] = vb
			
				
		vz_bar = vch * np.cos(aalpha) * 1e-3
		#v_bar *= dxo / (np.nanmean((v_bar[:self.idch])) * 1e3 * self.chaser.P)
		
		##############################
		
		if self.chaser.hp == self.chaser.ha:
			txtch = r"$\mathrm{%s:\,%d\,km\,alt.}$" % (self.chaser.name, self.chaser.hp)
		else:
			txtch = r"$\mathrm{%s}:\,%d\times%d\mathrm{\,km\,alt.}$" % (self.chaser.name, self.chaser.hp, self.chaser.ha)
		txttgt = r"$\mathrm{%s:\,%d\,km\,alt.}$" % (self.target.name, self.target.hp)
		
		nimg = 0
		for ii in range(len(self.target.speed_x)-1):
			
			if not ii % time_ticks == 0: continue
			
			#if ii > len(self.target.speed_x): continue
	
			fig = plt.figure(figsize=(18,10))
			plt.subplots_adjust(wspace=0.)
			plt.subplots_adjust(bottom=0.01)
			plt.subplots_adjust(top=0.95)
			plt.subplots_adjust(right=0.98)
			plt.subplots_adjust(left=0.)
			
			gs = gridspec.GridSpec(4, 3)
			
			# This where we plot the Earth orbit at the right scale
			ax0 = fig.add_subplot(gs[:2,0])
			#ax0.plot([1,2,3,4,5], [10,5,10,5,10], 'r-')
			ax0.set_aspect("equal")
			
			circle1 = plt.Circle((0, 0), constants.radiusE, color='b', alpha=0.5)
			ax0.add_artist(circle1)
			ax0.plot(self.target.trajectory_x[:self.idtgt], -1 * np.array(self.target.trajectory_y[:self.idtgt]), c='k')
			ax0.plot(self.chaser.trajectory_x[:self.idch], -1 * np.array(self.chaser.trajectory_y[:self.idch]), c='r')
			ax0.scatter(self.target.trajectory_x[ii], -1 * np.array(self.target.trajectory_y[ii]), c='k')
			ax0.scatter(self.chaser.trajectory_x[ii], -1 * np.array(self.chaser.trajectory_y[ii]), c='r')
			ax0.set_xticks([])
			ax0.set_yticks([])
			ax0.axis('off')
			
			ax1 = fig.add_subplot(gs[0,1:])
			#t = np.arange(len(self.target.speed_x)) * self.dt / self.chaser.P
			#vtgt = np.hypot(self.target.speed_x, self.target.speed_y) * 1e-3
			#vcha = np.hypot(self.chaser.speed_x, self.chaser.speed_y) * 1e-3
			ax1.plot(t, vtgt, c='k', label=self.target.name)
			ax1.plot(t, vcha, c='r', label=self.chaser.name)
			xmin1, xmax1 = ax1.get_xlim()
			ymin1, ymax1 = ax1.get_ylim()
			ax1.scatter(t[ii], vtgt[ii], c='k')
			ax1.scatter(t[ii], vcha[ii], c='r')			
			#ax1.plot(t, vcha-vtgt, c='b', label=r"$\Delta v$")
			ax1.legend(fontsize=self.txtsize - 2)
			ax1.xaxis.set_ticklabels([])
			ax1.set_ylabel(r"$v\,\mathrm{[km/s]}$")
			ax1.grid()
			ax1.set_xlim([xmin1, xmax1])
			ax1.set_ylim([ymin1, ymax1])
			
			ax2 = fig.add_subplot(gs[2:,0])
			ax2.set_aspect("equal")
			
			r, theta = u.cart2polar(self.target.trajectory_x, self.target.trajectory_y)
			r -= constants.radiusE
			x, y = u.polar2cart(r, theta)
			ax2.plot(x[:self.idtgt] * 1e-3, -1e-3 * y[:self.idtgt], c='k')
			ax2.scatter(x[ii] * 1e-3, -1e-3 * y[ii], c='k')
			
			r, theta = u.cart2polar(self.chaser.trajectory_x, self.chaser.trajectory_y)
			r -= constants.radiusE
			x, y = u.polar2cart(r, theta)
			
			lim2 = 1.15 * np.amax([self.chaser.ha, self.target.ha])
			ax2.set_xlim([-lim2, lim2])
			ax2.set_ylim([-lim2, lim2])
			
			ax2.plot(x[:self.idtgt] * 1e-3, -1e-3 * y[:self.idtgt], c='r')
			ax2.scatter(x[ii] * 1e-3, -1e-3 * y[ii], c='r')
			ax2.set_xticklabels([])
			ax2.set_yticks([])
			ax2.axis('off')
			
			ax3 = fig.add_subplot(gs[1, 1:])#, sharex=ax1)
			ax3.set_xlabel("$\mathrm{Time\,[Orbits\,of\,chaser]}$")
			ax3.plot(t, v_bar*1e3, c='gold', label=r"$\bar{V}$")
			ax3.plot(t, vz_bar*1e3, c='g', label=r"$v_R$")
			ymin3, ymax3 = ax3.get_ylim()
			ax3.scatter(t[ii], v_bar[ii]*1e3, c='gold')
			ax3.scatter(t[ii], vz_bar[ii]*1e3, c='g')
			ax3.set_xlim([xmin1, xmax1])
			ax3.set_ylim([ymin3, ymax3])
			ax3.legend(fontsize=self.txtsize - 2)
			ax3.grid()
			ax3.axhline(0, c='k', ls='--')
			ax3.set_ylabel(r"$\bar{V},\,v_R\,\mathrm{[m/s]}$")
			
			ax4 = fig.add_subplot(gs[2:,1:])
			
			ax4.spines['left'].set_position('zero')
			ax4.spines['right'].set_color('none')
			ax4.spines['bottom'].set_position('zero')
			ax4.spines['top'].set_color('none')
			
			# remove the ticks from the top and right edges
			ax4.xaxis.set_ticks_position('bottom')
			ax4.yaxis.set_ticks_position('left')
			ax4.invert_xaxis()
			ax4.invert_yaxis()
			
			ax4.plot(-np.array(self.distances.trajectory_x), -np.array(self.distances.trajectory_y))
			ax4.scatter(-np.array(self.distances.trajectory_x)[ii], -np.array(self.distances.trajectory_y)[ii])
			
			# For correctly plotting the vbar axis
			ax4.plot([0], [0], c='k')
			
			xmin, xmax = ax4.get_xlim()
			ymin, ymax = ax4.get_ylim()
			
			if t[ii] > 1 and highlight_new_orbit:
				ax4.axvline(-self.distances.trajectory_x[0], c='k', ls='--')
				ax4.axvline(-self.distances.trajectory_x[int(np.ceil(self.chaser.P / self.dt))], c='k', ls='--')
				x4t = -(self.distances.trajectory_x[0] + self.distances.trajectory_x[int(np.ceil(self.chaser.P / self.dt))])/2.
				
				y4t = (ymax - ymin) * 0.5 + ymin
				y4tt = (ymax - ymin) * 0.51 + ymin

				ax4.plot([-self.distances.trajectory_x[0], -self.distances.trajectory_x[int(np.ceil(self.chaser.P / self.dt))]], [y4t, y4t], ls='--', c='k')
				ax4.annotate(r'$1\,\mathrm{orbit\,}\Delta x = 3\pi\Delta a\approx %3.0f\,\mathrm{km}$' % (dxo/1e3), xy=(x4t, y4tt), ha='center')
			
			xx = ((1. - xmax / (xmax - xmin)) * 1.005 * (xmax - xmin) + xmin)
			yy = ((1. - ymax / (ymax - ymin)) * 1.015 * (ymax - ymin) + ymin)
			ax4.annotate(r'$\bar{V}\,\mathrm{[km]}$', xy=((xmax - xmin) * 0.01 + xmin, yy))
			ax4.annotate(r'$\bar{R}\,\mathrm{[km]}$', xy=(xx, (ymax - ymin) * 0.02 + ymin))
			
			if self.ax4_xmin is None:
				self.ax4_xmin = xmin
				self.ax4_xmax = xmax
				self.ax4_ymin = ymin
				self.ax4_ymax = ymax
			gs.update(wspace=0.05, hspace=0.3)
			
			ax4.set_xlim([self.ax4_xmin, self.ax4_xmax])
			ax4.set_ylim([self.ax4_ymin, self.ax4_ymax])
			

			plt.suptitle(txtch + r"$\quad$--$\quad$" + txttgt + r"$\quad$--$\quad$" + r"Time {:03d} min".format(int(self.dt*ii/60.)))
			
			if not os.path.exists(self.outdir):
				os.mkdir(self.outdir)
				
			if save:
				fig.savefig(os.path.join(self.outdir, "img_{:05d}.png".format(nimg)), dpi=200)
				plt.close()
			else:
				plt.show()
			
			nimg += 1