Main Content

Bluetooth LE Channel Sounding for Asset Tracking

Since R2025a

This example shows how to track the 2-D or 3-D position of a Bluetooth® low energy (LE) asset by using the Channel Sounding (CS) capabilities of Bluetooth Toolbox in the presence of radio frequency (RF) impairments.

Using this example, you can:

  • Create, configure, and generate a Bluetooth LE CS waveform.

  • Simulate CS packet exchange in the presence of RF impairments and additive white Gaussian noise (AWGN).

  • Add propagation delay and pathloss to the generated waveform.

  • Compute the distance between a locator (Initiator) and an asset (Reflector) by using the round-trip time (RTT) of flight or phase based ranging (PBR) distance measurement method.

  • Simulate the asset tracking scenario, and estimate the position of the unknown asset by using the positions of locators.

  • Track the asset trajectory by using the estimated positions of the unknown asset.

Distance Measurement Methods in Bluetooth CS

In Bluetooth Core Specification v6.0, the Bluetooth Special Interest Group (SIG) [1] introduces the Bluetooth CS capability, which facilitates secure fine ranging between two Bluetooth devices. When using this capability, the Initiator device measures the distance to the Reflector device, by exchanging CS waveforms with it. The Bluetooth Core Specification v6.0 [2] supports two distinct methods of distance measurement, which you can use independently or in combination: PBR and RTT.

In PBR distance measurement, the devices measure the distance between them by using the phase difference of the CS waveforms propagating on two distance frequencies. To learn how you can estimate the distance between Bluetooth LE devices using the PBR distance measurement method, see the Estimate Distance Between Bluetooth LE Devices by Using Channel Sounding and Phase-Based Ranging example.

In RTT distance measurement, the devices measure the distance between them by calculating the time of flight (ToF), which is the time taken for a packet exchange between the Initiator and the Reflector. Both devices record the time of arrival (ToA) and the time of departure (ToD) of the packet. By analyzing the differences between the ToA and ToD for both the Initiator and the Reflector, the devices accurately estimate the distance between them. To learn how you can estimate the distance between Bluetooth LE devices using the RTT distance measurement method, see the Estimate Distance Between Bluetooth LE Devices by Using Channel Sounding and Round-Trip Timing example. To explore the basic concepts of Bluetooth CS, see the What Is Bluetooth Channel Sounding? topic.

Asset Tracking Scenario and Simulation Procedure

This example enables you to create, configure, and simulate an asset tracking scenario involving different movement trajectories within an indoor environment. This figure shows a Bluetooth LE asset connected to four Bluetooth LE locators in a 3-D scenario. Each circle represents the range of a Bluetooth LE locator. When the asset enters the range of the locator, you can calculate the distance between the asset and a locator by using the RTT or PBR distance measurement method. Using these distance calculations, estimate the position of the asset by using the trilateration method. For more information on trilateration, see the Bluetooth Location and Direction Finding topic.

Trilateration, with 4 Locators and 1 Asset

The example uses these terminologies:

  • Asset — The device whose location you want to estimate.

  • Locator — A device whose location is known.

The scenario consists of known locators in an environment transmitting a Bluetooth LE CS packet for a CS exchange procedure. An asset with an unknown location is present inside the environment. This scenario implements a custom indoor path loss model [3]. In this example, each Bluetooth LE packet is distorted with these RF impairments.

  1. Carrier frequency offset

  2. Carrier phase offset

  3. Timing drift

  4. DC offset

  5. Phase noise

This figure shows a Bluetooth LE CS packet exchange procedure performed by a locator and the asset.

Bluetooth LE CS packet exchange procedure within one asset-locator pair

The Bluetooth LE CS packet exchange procedure estimates the position of the asset by performing these operations.

  1. Generates the CS waveform at the locator.

  2. Adds the propagation delay to the generated Bluetooth LE CS waveform.

  3. Adds the RF impairments, path loss and AWGN to the delayed waveform.

  4. Receives the noisy waveform at the asset.

  5. Estimates the distance of the asset from the locator, and generates a response waveform at the asset.

  6. Adds the propagation delay to the response CS waveform.

  7. Adds the RF impairments, path loss and AWGN to the delayed response waveform.

  8. Receives the noisy response waveform at the locator.

  9. Estimates the distance of the asset from the locator by using the PBR or RTT distance measurement method.

  10. Using these distances and the known positions of the locators, estimates the position of the asset using the blePositionEstimate function.

  11. Performs these steps for each asset position, to track the trajectory of the asset in motion.

  12. Plots the asset positions and trajectory in a 2-D or 3-D plot.

Simulation Configuration

To ensure repeatability of results, set the seed for the random number generator to default. The seed value controls the pattern of random number generation. Initializing the random number generator using the same seed ensures the same result. To improve the accuracy of your results, after running the simulation, you can change the seed value, run the simulation again, and average the results over multiple simulations.

rng("default");

Specify the simulation environment.

environmentModel = "Office";

Specify the motion trajectory of the asset as "Circular Path", "Fixed Path", "Linear Path", or "Random Path".

trajectory = "Circular Path";

Specify the motion model of the asset as "2-D Constant Velocity", "3-D Constant Velocity", "2-D Constant Acceleration", or "3-D Constant Acceleration".

motionModel = "3-D Constant Velocity";

Specify the dimensions of the room in meters.

roomSize = [40 50 10];          % In x-, y-, and z-coordinates

Specify the noise power spectral density (Eb/No), samples per symbol, and the speed of light.

EbNo = 24;              % Eb/No in dB
sps = 16;                                 % Samples per symbol
lightSpeedConst = physconst("LightSpeed");% Speed of light in m/s

Set the signal-to-noise ratio (SNR).

snr = convertSNR(EbNo,"ebno",SamplesPerSymbol=sps);

Specify the PHY transmission mode as "LE1M" or "LE2M".

phyMode = "LE1M";

Specify the CS step mode as 1 or 2, indicating CS SYNC or CS Tone exchange, respectively.

csStepMode = 2;

Specify the duration of the CS Tone as 10, 20, or 40 microseconds.

toneDuration = 40;

Specify the type of optional sequence in the CS SYNC packet format as "Sounding Sequence".

sequenceType = "Sounding Sequence";

Specify the sounding sequence length as 32 or 96.

sequenceLength = 96;

Create and configure a Bluetooth LE CS configuration object.

cfgChannelSounding = bleCSConfig(StepMode=csStepMode, ...
    SamplesPerSymbol=sps, ...
    Mode=phyMode, ...
    ToneDuration=toneDuration, ...
    SequenceLength=sequenceLength, ...
    SequenceType=sequenceType, ...
    OutputDataType="double");

Specify the types of device roles.

deviceRoles = ["Initiator","Reflector"];

Calculate the sampling frequency (in Hz) of the generated CS waveform.

sampleRate = sps*1e6*(1 + 1*(phyMode=="LE2M"));

Specify the transmitter power in dBm.

txPower = 0;

Specify the conversion rate of dBm.

dBmConverter = 30;

Create and configure a Bluetooth range configuration object.

cfgPathLoss = bluetoothPathLossConfig(Environment=environmentModel);

Specify the maximum number of packets simulated at each Eb/No point. Once the number of packets reaches this value, the simulation is complete.

maxNumPackets = 10;

Compute the number of dimensions of motion to generate asset positions.

numDimensions = 2 + any(motionModel==["3-D Constant Velocity","3-D Constant Acceleration"]);

Specify the number of locators and asset positions in the scenario.

numLocators = 15;
numPositionsAsset = 20;

Generate the positions of the asset and locators by using the motion model and motion trajectory.

[posAsset,posLocators] = helperBLEPositions(motionModel,numPositionsAsset,numLocators,roomSize,trajectory);

Preallocate memory to store the estimated positions of the asset.

posAssetEstimate = zeros(numDimensions,numPositionsAsset);

Preallocate memory to store the active locator positions corresponding to each asset positions.

posLocatorBuffer = cell(1,numPositionsAsset);

To configure the delay profile, create a variable fractional delay object by using the dsp.VariableFractionalDelay (DSP System Toolbox) System object™.

timingDelay = dsp.VariableFractionalDelay;

To configure the RF impairments, use the helperBLEImpairmentsInit helper object.

initImp = helperBLEImpairmentsInit(phyMode,sps);

Create and configure a coarse frequency compensator to compensate for RF impairments.

if csStepMode == 1
    % Specify modulation type as orthogonal quadrature phase shift keying
    % (OQPSK) for CS step mode 1.
    freqCompensator = comm.CoarseFrequencyCompensator(Modulation="OQPSK", ...
        SampleRate=sampleRate, ...
        SamplesPerSymbol=2*sps, ...
        FrequencyResolution=100);
else
    % Specify modulation type as quadrature amplitude modulation (QAM) for
    % CS step mode 2.
    freqCompensator = comm.CoarseFrequencyCompensator(Modulation="QAM", ...
        SampleRate=sampleRate, ...
        FrequencyResolution=100);
end

Initialize the random stream count to 1.

countStream = 1;

Simulation and Visualizations

For all the generated asset positions, simulate the motion of the asset.

for countPositionAsset = 1:numPositionsAsset

Configure nearest active locators to the Asset.

    [posActiveLocators,~,distanceActive] = helperBLEActiveLocators(posAsset(:,countPositionAsset),posLocators,"lateration");

Compute the number of active locators.

    numActiveLocators = size(posActiveLocators,2);

Preallocate the space to store the measured distance values.

    distanceMeasured = zeros(1,numActiveLocators);

Update the buffer of active locator positions.

    posLocatorBuffer{:,countPositionAsset} = posActiveLocators;

Estimate the path loss between each locator and the asset, based on the simulation environment and the distance between them, by using the bluetoothPathLoss function.

    plLinear = 10.^(bluetoothPathLoss(distanceActive,cfgPathLoss)/20);

Loop over the number of active locators.

    for countLocators = 1:numActiveLocators

To ensure that each iteration uses a repeatable set of random numbers, set a random substream index for each iteration by using the RandStream function.

        stream = RandStream("combRecursive");
        stream.Substream = countStream;
        RandStream.setGlobalStream(stream)

Get the distance (in meters) between the asset and the locator.

        distance = distanceActive(countLocators);

Compute the waveform propagation time (in seconds) between the devices.

        tPropagation = distance/lightSpeedConst;

Specify the carrier frequencies for two channels in the range [2.404, 2.478] GHz.

        carrierFrequency = randi([2404 2478])*1e6;

Specify the initial phases (in radians) of the Initiator and the Reflector.

        phi0I = rand*pi/4;
        phi0R = rand*pi/4;

Specify the delay structure for the Bluetooth LE CS waveform.

        delayStructure = struct(propagationTime=tPropagation, ...
            Fc=[carrierFrequency carrierFrequency+1e6], ...
            timingDelayVFD=timingDelay, ...
            phi0=phi0I-phi0R);

Preallocate the space to store the estimated distance values.

        estimatedDistance = zeros(maxNumPackets,2);

Initialize the packet count to 1.

        countPacket = 1;

Simulate each Bluetooth LE CS packet by performing the CS packet exchange procedure.

        while countPacket <= maxNumPackets

Initialize the device count to 1.

            countDevice = 1;

Simulate each Bluetooth LE CS packet by performing the CS packet exchange procedure.

            while countDevice <= 2
                cfgChannelSounding.DeviceRole = deviceRoles(countDevice);

Generate the Bluetooth LE CS waveform by using the bleCSWaveform function.

                [txWaveform,accessAddress] = bleCSWaveform(cfgChannelSounding);

Configure and add the RF impairment to the generated Bluetooth LE waveform.

                initImp.pfo.FrequencyOffset = randi([-150e2,150e2])*10; % Frequency offset in Hz, range is [-150000,+150000]
                initImp.pfo.PhaseOffset = randi([-2,2])*5;              % Phase offset in degrees
                initImp.vdelay = 0;                                     % Variable timing offset
                initImp.dc = 0;                                        % Percentage related to maximum amplitude value

                txImpairedWfm = helperBLEImpairmentsAddition(txWaveform,initImp);

Add propagation delay to the impaired waveform.

                delayWaveform = addPropagationDelay(txImpairedWfm,delayStructure,cfgChannelSounding,countDevice);

Apply transmitter power and path loss to the delayed waveform.

                txImpairedWaveform = 10^((txPower-dBmConverter)/20)*delayWaveform/plLinear(countLocators);

Add AWGN to the waveform.

                noisyWaveform = awgn(txImpairedWaveform,snr,"measured");

Estimate the distance (in meters).

                [estimatedDistance(countPacket,countDevice),qIndex] = estimateDistance(noisyWaveform, ...
                    cfgChannelSounding,accessAddress,freqCompensator);

If the quality index is 0, increment the device count by 1.

                if ~qIndex
                    countDevice = countDevice + 1;
                end
            end

Increment the packet count by 1.

            countPacket = countPacket + 1;
        end

Increment the random stream count by 1.

        countStream = countStream + 1;

Compute the average distance estimate over all packets.

        distanceMeasured(countLocators) = rms(mean(estimatedDistance,2));
    end

Estimate the position of the asset by using the trilateration method.

    posAssetEstimate(:,countPositionAsset) = blePositionEstimate(posActiveLocators,"lateration",distanceMeasured);
end

Compute the position error.

posError = rms(posAssetEstimate - posAsset);
csMethod = ["RTT","PBR"];

Display the average positioning error.

disp("Average positioning error is " + num2str(mean(posError)) + " meters by using the " + csMethod(csStepMode)+" method.")
Average positioning error is 0.20946 meters by using the PBR method.

Visualize the Bluetooth LE asset tracking.

if ~all(isnan(posAssetEstimate(1,:))) && isscalar(snr)
    helperBLEVisualizeNodeTracking(posLocators,posAsset,posLocatorBuffer,posAssetEstimate,roomSize)
end

Figure contains an axes object and an object of type uipanel. The axes object with title Bluetooth LE Asset Tracking, xlabel X (meters), ylabel Y (meters) contains 25 objects of type line, scatter. One or more of the lines displays its values using only markers These objects represent Locator Positions, Active Locator Positions, Current Asset Position, Asset Positions History, Current Estimated Asset Position, Estimated Asset Positions History.

Appendix

The example uses these helpers.

References

[1] Bluetooth Technology Website. “Bluetooth Technology Website | The Official Website of Bluetooth Technology.” Accessed November 11, 2024. https://www.bluetooth.com/

[2] Bluetooth Technology Website. "Bluetooth Core Specification." Version 6.0. Accessed November 11, 2024. https://www.bluetooth.com/specifications/specs/core-specification-6-0/.

[3] Bluetooth Range Estimator. "Path Loss (Propagation) Models." Bluetooth Special Interest Group (SIG). https://www.bluetooth.com.

Local Functions

function waveformOut = addPropagationDelay(waveformIn,impairments,cfgCS,countDeviceRole)
% Add propagation delay to the Bluetooth LE CS waveform

% Specify the samples per symbol
sps = cfgCS.SamplesPerSymbol;

% Specify the sample rate in Hz
sampleRate = 1e6*sps*(1 + 1*(cfgCS.Mode == "LE2M"));

if cfgCS.StepMode == 1
    % Specify the number of samples to delay
    samplesToDelay = cast(impairments.propagationTime*sampleRate,class(waveformIn));

    % Add propagation delay to the waveform
    waveformOut = impairments.timingDelayVFD([waveformIn; zeros((ceil(samplesToDelay/sps))*sps,1)],samplesToDelay);
elseif cfgCS.StepMode == 2
    % Specify the phase delay
    phaseToDelay = (2*pi*impairments.Fc)*impairments.propagationTime;

    % Delay the waveform with phase
    waveformOut = waveformIn*exp(1j*(-phaseToDelay))*exp((-1j)*(-1)^countDeviceRole*(impairments.phi0));
end
end

function [distanceEstimate,qIndex] = estimateDistance(rxWaveform,cfgCS,accessAddress,freqCompensator)
% Estimate the distance between the Initiator and the Reflector for CS step
% mode 1 or 2
rxDCFree = rxWaveform - mean(rxWaveform);
correctedWaveform = zeros(size(rxDCFree));
for countColumn = 1:width(rxDCFree)
    correctedWaveform(:,countColumn) = freqCompensator(rxDCFree(:,countColumn));
    release(freqCompensator)
end

% Specify the speed of light in meters / second
lightSpeedConst = 299792458;

if cfgCS.StepMode == 1
    % Estimate time of flight for CS step mode 1
    [tof,qIndex] = helperBLETOAEstimate(correctedWaveform,cfgCS,accessAddress);

    % Compute the estimate for distance by using the time of flight
    distanceEstimate = tof*lightSpeedConst;

elseif cfgCS.StepMode == 2
    % Specify the quality index as 0
    qIndex = 0;

    % Estimate the phase rotations for two channels
    phaseRotations = helperBLEPhaseEstimate(correctedWaveform,cfgCS);

    % Compute the difference of the phase-based rotations between the
    % different channels
    phaseChangeCalc = phaseRotations(2) - phaseRotations(1);

    % Wrap the difference in the phase rotations to 2 pi
    deltaPhaseASK = wrapTo2Pi(phaseChangeCalc);

    % Estimate the distance between the Initiator and the Reflector
    distanceEstimate = (lightSpeedConst/(2*pi*1e6))*deltaPhaseASK;

    % If estimated distance is out of expected range, assign quality index as 1
    if distanceEstimate < 0 || distanceEstimate > 150
        qIndex = 1;
    end
end
end

See Also

Functions

Objects

Topics