Week 08 – Channel Estimation

I implemented a MIMO channel estimator this week.

The purpose of a channel estimator is the estimation of the channel state information (CSI) which is required for many MIMO algorithms. The goals for such an estimator are a small estimation error but also a low estimation complexity and a small proportion of training data in comparison to the actual payload.

The estimator that I am going to implement, is going to have a flexible training sequence length. It can therefore be adjusted to the required estimation accuracy.

Training Sequence

For an orthogonal training sequence  that is flexible in the length, I use an FFT matrix, as proposed in [1].
FFT_matrixThe estimation matrix S has the dimensions M x L_t and each line m is sent from the transmission antenna m.

Channel Estimation

I am using a Maximum-Likelihood (ML) channel estimation:


Due to the fact, that S is not required to be a quadratic matrix (L_t is variable), S is also not invertible. To solve for H anyway, I use the Moore-Penrose inverse.

For the matrix inversion, Eigen3 is used again to estimate the channel for MIMO schemes with M>2. Read the post about V-BLAST for more information about the use of Eigen3 in this project.

Producing CSI stream tags

Once the channel is estimated, we want to signal this CSI to other blocks, for example a MIMO decoder block which relies on the CSI. For this purpose, we introduced a tag reading ability to all the implemented decoding blocks that require CSI. We can therefore just transport the estimated CSI to all downstream blocks via stream tags.

add_item_tag(0, nitems_written(0) + nconsumed, pmt::mp("csi"), csi_pmt);

Stream tags transport data as polymorphic types (PMTs), which are opaque data types that are designed as generic containers of data that can be safely passed around between blocks and threads in GNU Radio [2]. We have to assign a PMT with the estimated CSI:

// Assign the CSI vector to a PMT vector.
pmt::pmt_t csi_pmt = pmt::make_vector(d_N, pmt::make_c32vector(d_M, d_csi[0][0]));
for (int n = 0; n < d_N; ++n){
pmt::pmt_t csi_line_vector = pmt::make_c32vector(d_M, d_csi[n][0]);
for (int m = 0; m < d_M; ++m) {
pmt::c32vector_set(csi_line_vector, m, d_csi[n][m]);
pmt::vector_set(csi_pmt, n, csi_line_vector);

Because the CSI is a 2-dimensional vector, we declare a N-dimensional vector of PMTs. Each element of this vector is a PMT of the ‘data type’ uniform vector of the standard data type std::complex<float> of the length M.


I finished the implementation of the channel estimation block this week. The written qa tests pass for small MIMO configurations. However, for large MIMO schemes segmentation faults occur. I am going to solve this issue at the beginning of the next week.

After finishing the channel estimation, I can create the hierarchical python block ‘MIMO encoder/decoder’ which will be integrated into the OFDM transceiver afterwards.


[1] Qinfang Sun, D. C. Cox, H. C. Huang and A. Lozano, “Estimation of continuous flat fading MIMO channels,” in IEEE Transactions on Wireless Communications, vol. 1, no. 4, pp. 549-553, Oct 2002. doi: 10.1109/TWC.2002.804178

[2] https://www.gnuradio.org/doc/doxygen/page_pmt.html


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s