From 0a38d5f97b9a26143e1c416f3be0fcca5a14507e Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Tue, 14 Apr 2026 14:35:28 -0700 Subject: [PATCH] [nexus] introduce radio model for RSSI calculation (#12892) This commit adds a new RadioModel class to simulate wireless propagation characteristics between Nexus nodes. It implements a simple path-loss model based on node distance to calculate RSSI. Key changes include: - Added RadioModel with CalculateRssi and ShouldDropPacket methods. - Integrated RSSI calculation into the Core radio processing logic. - Implemented packet dropping for signals below -100 dBm sensitivity. - Added nexus_radio_model.cpp to the build system. --- tests/nexus/CMakeLists.txt | 1 + tests/nexus/platform/nexus_core.cpp | 15 ++++- tests/nexus/platform/nexus_node.hpp | 11 ++++ tests/nexus/platform/nexus_radio_model.cpp | 65 +++++++++++++++++++ tests/nexus/platform/nexus_radio_model.hpp | 72 ++++++++++++++++++++++ 5 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 tests/nexus/platform/nexus_radio_model.cpp create mode 100644 tests/nexus/platform/nexus_radio_model.hpp diff --git a/tests/nexus/CMakeLists.txt b/tests/nexus/CMakeLists.txt index 929ded788..75ca19eca 100644 --- a/tests/nexus/CMakeLists.txt +++ b/tests/nexus/CMakeLists.txt @@ -52,6 +52,7 @@ add_library(ot-nexus-platform platform/nexus_node.cpp platform/nexus_pcap.cpp platform/nexus_radio.cpp + platform/nexus_radio_model.cpp platform/nexus_settings.cpp platform/nexus_trel.cpp platform/nexus_udp.cpp diff --git a/tests/nexus/platform/nexus_core.cpp b/tests/nexus/platform/nexus_core.cpp index f4e4cbaee..f6f25f244 100644 --- a/tests/nexus/platform/nexus_core.cpp +++ b/tests/nexus/platform/nexus_core.cpp @@ -33,6 +33,7 @@ #include "mac_frame.h" #include "nexus_node.hpp" +#include "nexus_radio_model.hpp" namespace ot { namespace Nexus { @@ -506,8 +507,18 @@ void Core::ProcessRadio(Node &aNode) Radio::Frame rxFrame(aNode.mRadio.mTxFrame); rxFrame.mInfo.mRxInfo.mTimestamp = mNow; - rxFrame.mInfo.mRxInfo.mRssi = kDefaultRxRssi; - rxFrame.mInfo.mRxInfo.mLqi = kDefaultRxLqi; + + int16_t localRssi = RadioModel::CalculateRssi(aNode, rxNode); + + // Completely intercept and drop packets that dip below target receiver sensitivity + if (RadioModel::ShouldDropPacket(localRssi)) + { + continue; + } + + rxFrame.mInfo.mRxInfo.mRssi = ClampToInt8(localRssi); + + rxFrame.mInfo.mRxInfo.mLqi = kDefaultRxLqi; if (matchesDst && !dstAddr.IsNone() && !dstAddr.IsBroadcast() && ackRequested) { diff --git a/tests/nexus/platform/nexus_node.hpp b/tests/nexus/platform/nexus_node.hpp index 416ed62aa..525127ec8 100644 --- a/tests/nexus/platform/nexus_node.hpp +++ b/tests/nexus/platform/nexus_node.hpp @@ -136,6 +136,13 @@ public: void SetName(const char *aPrefix, uint16_t aIndex); const char *GetName(void) const { return mName.AsCString(); } + void SetPosition(float aX, float aY) + { + mX = aX; + mY = aY; + } + float GetPositionX(void) const { return mX; } + float GetPositionY(void) const { return mY; } //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - template Type &Get(void) { return Instance::Get(); } @@ -168,12 +175,16 @@ public: private: Node(void) : Platform(static_cast(*this)) + , mX(0.0f) + , mY(0.0f) { } void HandleIp6Receive(OwnedPtr aMessagePtr); String<32> mName; + float mX; + float mY; }; inline Node &AsNode(otInstance *aInstance) { return Node::From(aInstance); } diff --git a/tests/nexus/platform/nexus_radio_model.cpp b/tests/nexus/platform/nexus_radio_model.cpp new file mode 100644 index 000000000..068ab8cd9 --- /dev/null +++ b/tests/nexus/platform/nexus_radio_model.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2026, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "nexus_radio_model.hpp" + +#include "nexus_node.hpp" +#include "common/num_utils.hpp" + +#include + +namespace ot { +namespace Nexus { + +int16_t RadioModel::CalculateRssi(const Node &aTxNode, const Node &aRxNode) +{ + static constexpr double kPathLossConstant = 40.0; + static constexpr double kPathLossExponent = 20.0; + + // Simple path loss model + // RSSI = TxPower - PathLoss + // PathLoss = kPathLossExponent * log10(distance) + kPathLossConstant + + double dx = aTxNode.GetPositionX() - aRxNode.GetPositionX(); + double dy = aTxNode.GetPositionY() - aRxNode.GetPositionY(); + double distance = std::hypot(dx, dy); + + distance = Max(distance, 1.0); + + // Assume TxPower = 0 dBm + // RSSI = - (kPathLossConstant + kPathLossExponent * std::log10(distance)) + + double rssi = -(kPathLossConstant + kPathLossExponent * std::log10(distance)); + + return static_cast(std::round(rssi)); +} + +bool RadioModel::ShouldDropPacket(int16_t aRssi) { return aRssi < Radio::kRadioSensitivity; } + +} // namespace Nexus +} // namespace ot diff --git a/tests/nexus/platform/nexus_radio_model.hpp b/tests/nexus/platform/nexus_radio_model.hpp new file mode 100644 index 000000000..6ef0578dc --- /dev/null +++ b/tests/nexus/platform/nexus_radio_model.hpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2026, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OT_NEXUS_PLATFORM_NEXUS_RADIO_MODEL_HPP_ +#define OT_NEXUS_PLATFORM_NEXUS_RADIO_MODEL_HPP_ + +#include + +namespace ot { +namespace Nexus { + +class Node; + +/** + * This class implements a radio model for RSSI calculation. + * + */ +class RadioModel +{ +public: + RadioModel(void) = delete; + + /** + * This static method calculates the RSSI between two nodes based on their distance. + * + * @param[in] aTxNode The transmitter node. + * @param[in] aRxNode The receiver node. + * + * @returns The calculated RSSI in dBm. + */ + static int16_t CalculateRssi(const Node &aTxNode, const Node &aRxNode); + + /** + * This static method determines if a packet should be dropped based on its RSSI. + * + * @param[in] aRssi The RSSI of the packet. + * + * @retval true if the packet should be dropped. + * @retval false if the packet should not be dropped. + */ + static bool ShouldDropPacket(int16_t aRssi); +}; + +} // namespace Nexus +} // namespace ot + +#endif // OT_NEXUS_PLATFORM_NEXUS_RADIO_MODEL_HPP_