CARLA
Loading...
Searching...
No Matches
V2XSensor.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
8
9#include "Carla.h"
14#include "V2X/CaService.h"
15#include "V2X/PathLossModel.h"
16
17#include <algorithm>
18#include <string.h>
19
20
22
23AV2XSensor::AV2XSensor(const FObjectInitializer &ObjectInitializer)
24 : Super(ObjectInitializer)
25{
26 PrimaryActorTick.bCanEverTick = true;
27 RandomEngine = CreateDefaultSubobject<URandomEngine>(TEXT("RandomEngine"));
28
29 // Init path loss model
30 PathLossModelObj = std::make_unique<PathLossModel>(RandomEngine, this);
31 CaServiceObj = std::make_unique<CaService>(RandomEngine);
32
33 // we can't intialize owner for RSUs here, because CALRA Actor not yet existing... have to check on the fly
34}
35
37 // Defensive: CaServiceObj is owned by a unique_ptr created in the
38 // constructor and lives until destruction, so this is normally non-null.
39 if (!CaServiceObj)
40 {
41 return;
42 }
43 UWorld *world = GetWorld();
44 CaServiceObj->SetActor(world, NewOwner);
45}
46
48{
49 Super::SetOwner(NewOwner);
50 InitModel(NewOwner);
51}
52
53void AV2XSensor::EndPlay(const EEndPlayReason::Type EndPlayReason)
54{
55 // Drop our entry from the shared static map so a destroyed sensor cannot
56 // leave a dangling AActor* key for the surviving V2X sensors to dereference.
58
59 // CaServiceObj / PathLossModelObj are std::unique_ptr: they are released
60 // automatically in the destructor, which runs after UE's teardown clears
61 // ownership (SetOwner(nullptr) -> InitModel). Do not reset them here, or
62 // that teardown call would dereference a freed object.
63 Super::EndPlay(EndPlayReason);
64}
65
70
71/* Function to add configurable parameters*/
72void AV2XSensor::Set(const FActorDescription &ActorDescription)
73{
74 Super::Set(ActorDescription);
75 UActorBlueprintFunctionLibrary::SetV2X(ActorDescription, this);
76}
77
78void AV2XSensor::SetCaServiceParams(const float GenCamMin, const float GenCamMax, const bool FixedRate)
79{
80 // forward parameters to CaService Obj
81 CaServiceObj->SetParams(GenCamMin, GenCamMax, FixedRate);
82}
83
84void AV2XSensor::SetPropagationParams(const float TransmitPower,
85 const float ReceiverSensitivity,
86 const float Frequency,
87 const float combined_antenna_gain,
88 const float path_loss_exponent,
89 const float reference_distance_fspl,
90 const float filter_distance,
91 const bool use_etsi_fading,
92 const float custom_fading_stddev)
93{
94 // forward parameters to PathLossModel Obj
95 PathLossModelObj->SetParams(TransmitPower, ReceiverSensitivity, Frequency, combined_antenna_gain, path_loss_exponent, reference_distance_fspl, filter_distance, use_etsi_fading, custom_fading_stddev);
96}
97
99{
100 PathLossModelObj->SetPathLossModel(path_loss_model);
101}
102
104{
105 PathLossModelObj->SetScenario(scenario);
106}
107
108/*
109 * Function stores the actor details in to the static list.
110 * Calls the CaService object to generate CAM message
111 * Stores the message in static map
112 */
113void AV2XSensor::PrePhysTick(float DeltaSeconds)
114{
115 if ( !CaServiceObj->CarlaActorInitialized() ) {
116 // ensure a CarlaActor to be the owner if no parent actor
117 InitModel(this);
118 }
119
120 Super::PrePhysTick(DeltaSeconds);
121 // Clear the message created during the last sim cycle
123
124 // Step 0: Create message to send, if triggering conditions fulfilled
125 // this needs to be done in pre phys tick to enable synchronous reception in all other v2x sensors
126 // Check whether the message is generated
127 if (CaServiceObj->Trigger(DeltaSeconds))
128 {
129 // If message is generated store it
130 // make a pair of message and sending power
131 // if different v2x sensors send with different power, we need to store that
133 cam_pw.Message = CaServiceObj->GetCamMessage();
134 cam_pw.Power = PathLossModelObj->GetTransmitPower();
135 AV2XSensor::mActorV2XDataMap.insert({this, cam_pw});
136 }
137}
138
140{
141 CaServiceObj->SetAccelerationStandardDeviation(Vec);
142}
143
144void AV2XSensor::SetGNSSDeviation(const float noise_lat_stddev,
145 const float noise_lon_stddev,
146 const float noise_alt_stddev,
147 const float noise_head_stddev,
148 const float noise_lat_bias,
149 const float noise_lon_bias,
150 const float noise_alt_bias,
151 const float noise_head_bias)
152{
153 CaServiceObj->SetGNSSDeviation(noise_lat_stddev,
154 noise_lon_stddev,
155 noise_alt_stddev,
156 noise_head_stddev,
157 noise_lat_bias,
158 noise_lon_bias,
159 noise_alt_bias,
160 noise_head_bias);
161}
162
163void AV2XSensor::SetVelDeviation(const float noise_vel_stddev)
164{
165 CaServiceObj->SetVelDeviation(noise_vel_stddev);
166}
167
168void AV2XSensor::SetYawrateDeviation(const float noise_yawrate_stddev, const float noise_yawrate_bias)
169{
170 CaServiceObj->SetYawrateDeviation(noise_yawrate_stddev, noise_yawrate_bias);
171}
172
173/*
174 * Function takes care of sending messages to the current actor.
175 * First simulates the communication by calling LOSComm object.
176 * If there is a list present then messages from those list are sent to the current actor
177 */
178void AV2XSensor::PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaTime)
179{
180 TRACE_CPUPROFILER_EVENT_SCOPE(AV2XSensor::PostPhysTick);
181 // Step 1: Create an actor list which has messages to send targeting this v2x sensor instance
182 std::vector<ActorPowerPair> ActorPowerList;
183 for (const auto &pair : AV2XSensor::mActorV2XDataMap)
184 {
185 if (pair.first != this)
186 {
187 ActorPowerPair actor_power_pair;
188 actor_power_pair.first = pair.first;
189 // actor sending with transmit power
190 actor_power_pair.second = pair.second.Power;
191 ActorPowerList.push_back(actor_power_pair);
192 }
193 }
194
195 carla::sensor::data::CAMDataS msg_received_power_list;
196 // Step 2: Simulate the communication for the actors in actor list to current actor.
197 if (!ActorPowerList.empty())
198 {
199 UCarlaEpisode *carla_episode = UCarlaStatics::GetCurrentEpisode(GetWorld());
200 PathLossModelObj->Simulate(ActorPowerList, carla_episode, GetWorld());
201 // Step 3: Get the list of actors who can send message to current actor, and the receive power of their messages.
202 ActorPowerMap actor_receivepower_map = PathLossModelObj->GetReceiveActorPowerList();
203 // Step 4: Retrieve the messages of the actors that are received
204
205 // get registry to retrieve carla actor IDs
206 const FActorRegistry &Registry = carla_episode->GetActorRegistry();
207
208 for (const auto &pair : actor_receivepower_map)
209 {
210 // Note: AActor* sender_actor = pair.first;
211 // find + skip-on-miss: at() would throw std::out_of_range if the
212 // sender dropped out of the map between simulate and retrieval.
213 const auto sender_it = AV2XSensor::mActorV2XDataMap.find(pair.first);
214 if (sender_it == AV2XSensor::mActorV2XDataMap.end())
215 {
216 continue;
217 }
218 carla::sensor::data::CAMData const &send_msg_and_pw = sender_it->second;
219 carla::sensor::data::CAMData received_msg_and_pw;
220 // sent CAM
221 received_msg_and_pw.Message = send_msg_and_pw.Message;
222 // receive power
223 received_msg_and_pw.Power = pair.second;
224
225 msg_received_power_list.WriteMessage(received_msg_and_pw);
226 }
227 }
228 // Step 5: Send message
229
230 if (msg_received_power_list.GetMessageCount() > 0)
231 {
232 auto DataStream = GetDataStream(*this);
233 DataStream.SerializeAndSend(*this, msg_received_power_list, DataStream.PopBufferFromPool());
234 }
235}
std::pair< AActor *, float > ActorPowerPair
std::map< AActor *, float > ActorPowerMap
EScenario
EPathLossModel
FAsyncDataStream GetDataStream(SensorType &&Self)
Return the FDataStream associated with this sensor.
URandomEngine * RandomEngine
Random Engine used to provide noise for sensor output.
void Set(const FActorDescription &ActorDescription) override
Definition V2XSensor.cpp:72
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
Definition V2XSensor.cpp:53
void SetPropagationParams(const float TransmitPower, const float ReceiverSensitivity, const float Frequency, const float combined_antenna_gain, const float path_loss_exponent, const float reference_distance_fspl, const float filter_distance, const bool use_etsi_fading, const float custom_fading_stddev)
Definition V2XSensor.cpp:84
virtual void PrePhysTick(float DeltaSeconds) override
static ActorV2XDataMap mActorV2XDataMap
Definition V2XSensor.h:71
std::unique_ptr< CaService > CaServiceObj
Definition V2XSensor.h:65
void SetGNSSDeviation(const float noise_lat_stddev, const float noise_lon_stddev, const float noise_alt_stddev, const float noise_head_stddev, const float noise_lat_bias, const float noise_lon_bias, const float noise_alt_bias, const float noise_head_bias)
void InitModel(AActor *Owner)
Definition V2XSensor.cpp:36
void SetAccelerationStandardDeviation(const FVector &Vec)
void SetPathLossModel(const EPathLossModel path_loss_model)
Definition V2XSensor.cpp:98
static FActorDefinition GetSensorDefinition()
Definition V2XSensor.cpp:66
std::map< AActor *, carla::sensor::data::CAMData > ActorV2XDataMap
Definition V2XSensor.h:70
std::unique_ptr< PathLossModel > PathLossModelObj
Definition V2XSensor.h:66
virtual void PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaTime) override
AV2XSensor(const FObjectInitializer &ObjectInitializer)
Definition V2XSensor.cpp:23
void SetScenario(EScenario scenario)
void SetOwner(AActor *Owner) override
Definition V2XSensor.cpp:47
void SetYawrateDeviation(const float noise_yawrate_stddev, const float noise_yawrate_bias)
void SetCaServiceParams(const float GenCamMin, const float GenCamMax, const bool FixedRate)
Definition V2XSensor.cpp:78
void SetVelDeviation(const float noise_vel_stddev)
A registry of all the Carla actors.
static void SetV2X(const FActorDescription &Description, AV2XSensor *V2X)
A simulation episode.
const FActorRegistry & GetActorRegistry() const
static UCarlaEpisode * GetCurrentEpisode(const UObject *WorldContextObject)
void WriteMessage(const CAMData &message)
Adds a new message.
Definition V2XData.h:54
size_t GetMessageCount() const
Returns the number of currently received messages.
Definition V2XData.h:44
A definition of a Carla Actor with all the variation and attributes.
A description of a Carla Actor with all its variation.