Because of the holidays, TI E2E™ design support forum responses will be delayed from Dec. 25 through Jan. 2. Thank you for your patience.

This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

IWR1443BOOST: AoA calculations - Doppler Compensation is not performing

Part Number: IWR1443BOOST
Other Parts Discussed in Thread: IWR1443

Hello

in the related topic, with the help of mr Curewitz we were able to develop a Platform for acquiring data from 3 TX Antennas based on TDM transmission on our IWR1443Boost connected through a TSW1400 EVM board to our computer.

We are working on objects at ZERO velocity, at the moment. Mostly a Corner Reflector in a non-noisy environment.

We are trying to get AoA. by separating the azimutal and elevation calculations, as suggested earlier on.

For azimutal calculations, we are zero-padding the echoes from the following antennas: TX0RX1 - TX0RX2- TX0RX3 - TX0RX4 - TX2RX1 - TX2RX2 - TX2RX3 - TX2RX4, and we are already obtaining pretty good results by FFTing the rows.


For elevation calculations, we have created a 2x4 Matrix with following echoes:

tx1rx1 tx1rx2 tx1rx3 tx1rx4

tx0rx3 rx0rx4 tx2rx1 tx2rx2

then zero padding the columns, calculating  the FFT, and working on either the average or the sum of the obtained peaks.

Where we are not convinced we are operating correctly,is on the topic of Doppler Compensation

We are currently using the same function contained in the Doxygen demo:

1271 static float aoaHwa_calcCompIdx
 1272 (
 1273     uint16_t dopplerIdx,
 1274     uint32_t numDopplerBins,
 1275     uint32_t numTxAnt
 1276 )
 1277 {
 1278     float      dopplerCompensationIdx;
 1279 
 1280     /* Doppler compensation index calculation */
 1281     if (dopplerIdx >= numDopplerBins/2)
 1282     {
 1283         dopplerCompensationIdx =  ((int32_t) dopplerIdx - (int32_t) numDopplerBins);
 1284     }
 1285     else
 1286     {
 1287         dopplerCompensationIdx =  dopplerIdx;
 1288     }
 1289     
 1290     /* Doppler phase correction is 1/2 or (1/3 in elevation case) of the phase between two chirps of the same antenna */
 1291     dopplerCompensationIdx = dopplerCompensationIdx / (float) numTxAnt;
 1292     if (dopplerCompensationIdx < 0)
 1293     {
 1294         dopplerCompensationIdx +=  (float) numDopplerBins;
 1295     }
 1296 
 1297     return dopplerCompensationIdx;
 1298 }
 1299 
 1318 static void aoaHwa_dopplerComp
 1319 (
 1320     cmplx16ImRe_t *in,
 1321     cmplx16ImRe_t *out,
 1322     float  Cos,
 1323     float  Sin
 1324 )
 1325 {
 1326     float           yRe, yIm;
 1327 
 1328     /* Rotate symbol (correct the phase) */
 1329     yRe = in->real * Cos + in->imag * Sin;
 1330     yIm = in->imag * Cos - in->real * Sin;
 1331     out->real = (int16_t) yRe;
 1332     out->imag = (int16_t) yIm;
 1333 }
 1334 
 1368 static void aoaHwa_dopplerCompensation
 1369 (
 1370     uint32_t numDetectedObjects,
 1371     uint32_t *srcPtrAzim,
 1372     uint32_t *srcPtrElev,
 1373     DPIF_CFARDetList *cfarOutList,
 1374     uint32_t *dstPtrAzim,
 1375     uint32_t *dstPtrElev,
 1376     uint32_t numTxAnt,
 1377     uint32_t numRxAnt,
 1378     uint32_t numVirtualAntAzim,
 1379     uint32_t numVirtualAntElev,
 1380     uint32_t numDopplerBins
 1381 )
 1382 {
 1383     uint32_t   index;
 1384     uint32_t   j;
 1385     uint16_t   dopplerIdx;
 1386     float      dopplerCompensationIdx;
 1387     
 1388     for(index = 0; index < numDetectedObjects; index ++)
 1389     {
 1390         dopplerIdx = cfarOutList->dopplerIdx;
 1391 
 1392         /* transfer data corresponding to azimuth virtual antennas (corresponding to chirp of antenna Tx0) */
 1393         for(j = 0; j < numRxAnt; j++)
 1394         {
 1395             *dstPtrAzim++ = *srcPtrAzim++;
 1396         }
 1397         
 1398         /* transfer data corresponding to azimuth virtual antennas (corresponding to chirp of antenna Tx1) */
 1399         if (numVirtualAntAzim > numRxAnt)
 1400         {
 1401             float Cos,Sin;
 1402 
 1403             dopplerCompensationIdx = aoaHwa_calcCompIdx(dopplerIdx, numDopplerBins, numTxAnt);
 1404 
 1405             Cos = cos(2*PI_*dopplerCompensationIdx/numDopplerBins);
 1406             Sin = sin(2*PI_*dopplerCompensationIdx/numDopplerBins);
 1407 
 1408             for(j = numRxAnt; j < numVirtualAntAzim; j++)
 1409             {
 1410                 aoaHwa_dopplerComp((cmplx16ImRe_t *)srcPtrAzim++, (cmplx16ImRe_t *)dstPtrAzim++, Cos, Sin);
 1411             }
 1412 
 1413             if (numVirtualAntElev > 0)
 1414             {
 1415                 /* transfer data corresponding to elevation virtual antennas, (corresponding to chirp of antenna Tx2) */
 1416                 float Cos2, Sin2;
 1417                 /* Doppler phase shift is 2/3 */
 1418                 Cos2 = Cos * Cos - Sin * Sin;
 1419                 Sin2 = 2 * Cos * Sin;
 1420                 for(j = 0; j < numVirtualAntElev; j++)
 1421                 {
 1422                     aoaHwa_dopplerComp((cmplx16ImRe_t *)srcPtrElev++, (cmplx16ImRe_t *)dstPtrElev++, Cos2, Sin2);
 1423                 }
 1424             }
 1425         }
 1426         cfarOutList++;
 1427     }
 1428 }       

But if feels almost as if the compensation is "compensating too much". Plus, we are never getting NEGATIVE values of phi.
We have created our list of points on phi by separing the -15:15 interval in the amount of points fixed by the dimension of our elev_zeropadding, which seems correct.

Thanks again for your kindness

 

  • Hi,

    Since I am not the one writing that code,  I can  not give you immediate suggestions.  But for static object detection, you should not need any Doppler compensation (dopplerCompensationIdx = 0).  Can you confirm that?

    I have some matlab code for the Doppler compensation, I attached here for your reference.  This code is for 3 TX antennas.

    if (current_obj.dopplerInd ~= dopplerFFTSize/2)

                       dopplerInd1 = current_obj.dopplerInd;

                       deltaPhi = 2*pi*(dopplerInd1-dopplerFFTSize/2)/(3*dopplerFFTSize);

                       corZz = exp(-1j*deltaPhi);

                       X(5:12) = X(5:12)*corZz;

                       X(9:12) = X(9:12)*corZz;

    end

    Let me know whether it is helpful.

  • since we are working on both positive and negative velocities , our 0 velocity bin is in correspondence with n_chirps/2, because our 0 bin is -max_velocity.

    Since the doppler_idx is, for example, 64 (with 128 chirps), we have excluded the compensation for a small interval around 0 velocity.

    The function you are working is exactly the same as we have worked on!

    Any hint about why we are never getting a negative angle for phi (elevation )?
  • What code you are using for elevation angle calculation?

    Best,

    Zigang

  • HI, Michele:

    Your understanding of DOA estimation seems off.  You can download the mmwave SDK 1.2.0.5 and looked at the section about "Data Path - Direction of Arrival Estimation (x,y,z)" on file:///C:/ti/mmwave_sdk_01_02_00_05/packages/ti/demo/xwr14xx/mmw/docs/doxygen/html/index.html.

    You can also find function"void angleEstimationAzimElev "link from the above document.

    Best,

    Zigang

  • Ok thanks. we are taking a look at the C functions.

    How is the elevation Matrix determined? I am attaching an image showing how we are operating, hope this is correct.

    Our main issue is the following: for azimuth, we have a single row contribution for each detected object

    Regarding elevation, we have 4 "columns" (obviously in the end we have to transpose them): to obtain the same configuration and be able to search the peak as in XYZestimation function rows 21-28 (absolute rows 439-446) how should we intersect/average/sum the contributions on each of the 4 elements?

    I cannot find it in the code.

  • Hi, Michele:

    Please download the mmwave SDK version 2.01.00.04, which is MMWAVE-SDK-LTS (mmWave SDK long-term support).  The version I mentioned earlier is no longer supported.   And this version support the same AoA algorithm.  

    file:///C:/ti/mmwave_sdk_02_01_00_04/packages/ti/demo/xwr14xx/mmw/docs/doxygen/html/index.html

    So, the algorithm calculate the azimuth spectrum (azimFFTPtr) based on TX0 and TX2 signal (total 8 elements), and find the maxIdx based on this spectrum.   Then it calculates the azimuth spectrum based on the TX1 signal (total 4 elements), let us call it elevFFTPtr.   Then the phase difference between azimFFTPtr(maxIdx) and elevFFTPtr(maxIdx) is the used to calculate the elevation angle.  Please read the document carefully.

    Best,

    Zigang

    Best,

    Zigang

  • Ok, I understood what you are saying, but we have some trouble interpreting a few parameters inside the code:

      469     if(maxIdx > (numAngleBins/2 -1))
      470     {
      471         sMaxIdx = maxIdx - numAngleBins;
      472     }
      473     else
      474     {
      475         sMaxIdx = maxIdx;
      476     }
      477 
      478     Wx = 2 * (float) sMaxIdx / numAngleBins;
      479     x = range * Wx;
      480 
      481     if (obj->numVirtualAntElev > 0)
      482     {
      483         Wz = atan2(peakAzimIm * peakElevRe - peakAzimRe * peakElevIm,
      484                    peakAzimRe * peakElevRe + peakAzimIm * peakElevIm)/PI_ + (2 * Wx);
      485         if (Wz > 1)
      486         {
      487                 Wz = Wz - 2;
      488         }
      489         else if (Wz < -1)
      490         {
      491                 Wz = Wz + 2;
      492         }
      493         z = range * Wz;
      494         /*record wz for debugging/testing*/
      495         if(objOutIndx < MMW_MAX_ELEV_OBJ_DEBUG)
      496         {
      497             obj->detObjElevationAngle[objOutIndx] = Wz;
      498         }
      499         
      500     }
      501     else
      502     {
      503         z = 0;
      504     }

    This part should calculate the projections on each of the three axis.

    But... can the radar find objects on negative z-axis , i mean, under the plane of the radar?

    What are Wx and Wz? Angles? sin/cos? the results of sin/cos? we have trouble intepreting them and the documentation says nothing about those.


    Thanks for your clairifications!

    Michele

    2)

    516  if(x < 0)
    517  {
    518  objOut[objOutIndx].x = (int16_t) (x * ONE_QFORMAT - 0.5);
    519  }
    520  else
    521  {
    522  objOut[objOutIndx].x = (int16_t) (x * ONE_QFORMAT + 0.5);
    523  }
    524  if(y < 0)
    525  {
    526  objOut[objOutIndx].y = (int16_t) (y * ONE_QFORMAT - 0.5);
    527  }
    528  else
    529  {
    530  objOut[objOutIndx].y = (int16_t) (y * ONE_QFORMAT + 0.5);
    531  }
    532  if(z < 0)
    533  {
    534  objOut[objOutIndx].z = (int16_t) (z * ONE_QFORMAT - 0.5);
    535  }
    536  else
    537  {
    538  objOut[objOutIndx].z = (int16_t) (z * ONE_QFORMAT + 0.5);
    539  }

    is this part relevant also if we replicate the same algorithm on Matlab, or is just a floating point to fixed point conversion?
  • HI, Michele:

    For (1)

    Wz = sin(ElevAngle);

    Wx = sin(AzimAngle)*cos(ElevAngle);

    It is the same definition if you do 2-D FFT on angle spectrum.  The FFT index is not directly in angle. You can also look "Figure A" in doxygen file.

    Yes, we can detect negative z planes.

    For (2)

    It is to convert the floating value into 16 bits fix point with some scale (ONE_QFORMAT).

    Best,

    Zigang

  • Ok thanks a lot Zigang.

    1) Why are you subtracting or adding some amounts to Wz?

    485         if (Wz > 1)
    486         {
    487                 Wz = Wz - 2;
    488         }
    489         else if (Wz < -1)
    490         {
    491                 Wz = Wz + 2;
    492         }

    Is it to have values inside the acceptable ranges of sin and cos?

    2) Wx = 2 * (float) sMaxIdx / numAngleBins;

    So, 2*sMaxIdx/NUM_ANGLE_BINS = sin(AzimAngle)*cos(ElevAngle);

    ***

    Wz = atan2(peakAzimIm * peakElevRe - peakAzimRe * peakElevIm,peakAzimRe * peakElevRe + peakAzimIm * peakElevIm)/PI_ + (2 * Wx);
     
    So, atan2(peakAzimIm * peakElevRe - peakAzimRe * peakElevIm,peakAzimRe * peakElevRe + peakAzimIm * peakElevIm)/PI_ + (2 * Wx) = sin(ElevAngle);

    Could you clarify how and why?

  • HI, Michele:

    For (1),  since PhaseDiff = PI * (sin(ElevAngle) + 2*Wx);

    The phaseDiff can have a ambiguity of +/-2*pi.  Which means sin(ElevAngle) can have a ambiguity of +/-2.   That is why in the code, they adjust +2 or -2 to get sin(ElevAngle) back to the range of [-1, 1]. 

    For (2), Again, you can read the document, I do not think I can explain better than the documentation.  I have highlighted related equations inside the document below. 

    file:///C:/ti/mmwave_sdk_02_01_00_04/packages/ti/demo/xwr14xx/mmw/docs/doxygen/html/index.html

  • the attached document does not exist! :(
  • Hi, Michele:

    You need to download MMWAVE-SDK-LTS installer from:

    http://software-dl.ti.com/ra-processors/esd/MMWAVE-SDK/lts-latest/index_FDS.html

    And after your installation, you can open the Doxygen document at:

    C:\ti\mmwave_sdk_02_01_00_04\packages\ti\demo\xwr14xx\mmw\docs\doxygen\html\index.html

    Search for "Direction of Arrival Estimation", it contains the angle estimation details.

    Best,

    Zigang

  • Hi, Michelle:

    Did you find the information now? Can we close this ticket?
    Best,
    Zigang
  • Hello,

    we have found the information, but they added nothing to what we already knew, or maybe confused us even a little more. For example,when calculating theta or phi with the formulas indicated in the Doxygen manual (the part regarding wx, P1, P2, P1*conj(P2), and wz), we obtain values which are not the same as the calculations through the "angleEstimationAzimElev" C Language function.

    At the present point, we are able to decently estimate the X and Y position of each sample of our item (in this case, a corner reflector), but the Z are off.

    Which seems very strange, since X, Y, and Z are inter-related.

    Something that came to our mind in regard to the estimation of the phase difference, was that maybe we were aligning the symbols related to the TX1 antennas in the wrong positions.

    Previously, for each range bin of interested (filtered through CFAR+extraction of the correct doppler index) ,we were placing the 4 symbols in the first 4 cells of the array, and then zero padding to NUM_ANGLE_BINS dimension.

    For azimuth,  for each range bin of interested (filtered through CFAR+extraction of the correct doppler index) ,we were placing the 8 symbols in the first 8 cells of the array, and then zero padding to NUM_ANGLE_BINS dimension.

    We are currently placing two zeros in the first two ELEVATION symbols, then the 4 echoes from the virtual antennas, and then zero padding.

    1. Is this the correct approach, and should it change the results? We were unsure if we should try to replicate the geometry of the two arrays.

    2. we are not compensating range or phase biases (calibration procedure and .cfg parameters), could they condition our results so badly? We estimated that they would be minor upgrades or corrections, but we might be off.

    3. as a general question and synthesis of our issues: with IWR1443, at an average distance of, let's say, 10m (or 100, if you could reply twice), will we ever be able to reconstruct the contour or shape of different objects, basing on the ensemble of received echoes and post-elaborations on those?

  • Hi, Michele:

    Regarding your three questions:

    1) Based on TI documentation, we do not padding two zeros before calculating the elevFFTPtr.  If you padded two zeros, I would guess you can simplify the Wz calculation from:

    Wz = atan2(peakAzimIm * peakElevRe - peakAzimRe * peakElevIm, 

                        peakAzimRe * peakElevRe + peakAzimIm * peakElevIm)/PI_ + (2 * Wx);

    to

    Wz = atan2(peakAzimIm * peakElevRe - peakAzimRe * peakElevIm, 

                        peakAzimRe * peakElevRe + peakAzimIm * peakElevIm)/PI_ ;

     

    2) I am not sure how much help the phase calibration helps.  Each device can be different.  If the angle estimation is wrong with our approach, it is very possible that it needs the calibration.
    3)  In general, it is very hard to use single radar sensor to get contour of the object, the angle resolution is not fine enough.    Maybe you can consider cascade system in that case.  https://training.ti.com/build-cascaded-radar-using-tis-mmwave-sensors
    Another possibility is when the sensor is moving and you know the location of the sensor, therefore you can combine the detection results over frames (you have to compensate the sensor movement in each frame).   Since radar sensor sees different part of the object at different location, when you combine the detection over frames, you have better chance to see the contour of the object.
    Hope it helps,
    Zigang

     

  • 1) Thanks! We tried removing the "+2Wx" factor from the equation, and we obtained an improvement. Our object, which in reality is around 40 cm along the z-axis, was estimated as 1.2 meters. Without that factor, we now see it as around 0.6 m. We are still unsure why, with X and Y being correct, our Z is over-estimated. Do  you happen to have any suggestion?

    2) We are currently seeing objects at 2meters over the radar in a position around 0meters over the radar. Can the phase calibration influence such measurement?

    3) Thanks for clarifying. Are you planning to release more tutorials or documentation about the usage of Cascaded Radars in the near future? Would any other radar in production by TI allow for better angular estimations?

  • Hi, Michele:

    (1) If the object is 2m away, 0.4m and 0.6m height difference is about asin(0.6/2)*180/pi - asin(0.4/2)*180/pi = 6 degree in estimation error. It is not too bad, check whether your sensor is placed with a little bit tilting angle. Running calibration (step 2) helps too. Please also make sure that your target is clean, means there is no other strong target close by, which can spread into your desired range bin.

    (2) Running angle calibration will benefit angle estimation in any distance. Basically, if the object is placed at zero degree angle (both azimuth and elevation), the phase from all the TX-RX pairs (total 12) should be the same. If not, then this phase/gain calibration routine will correct it. When you run calibration commands, please follows the instruction.

    (3) I will get back to you on cascade radar in a separate reply.
  • HI, Michele:

    I was told that the cascade public release will be mid of this year.

    Best,
    Zigang
  • HI, Michele:

    I have heard from you for a week. I will need to close this ticket.