CARLA
 
载入中...
搜索中...
未找到
InertialMeasurementUnit.cpp
浏览该文件的文档.
1// Copyright (c) 2019 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
7#include "Carla.h"
8
13
15#include "carla/geom/Math.h"
16#include "carla/ros2/ROS2.h"
18
19#include <limits>
20
21// Based on OpenDRIVE's lon and lat
23 FVector(0.0f, -1.0f, 0.0f);
24
26 const FObjectInitializer &ObjectInitializer)
27 : Super(ObjectInitializer)
28{
29 PrimaryActorTick.bCanEverTick = true;
30 PrimaryActorTick.TickGroup = TG_PostPhysics;
31 RandomEngine = CreateDefaultSubobject<URandomEngine>(TEXT("RandomEngine"));
32 PrevLocation = { FVector::ZeroVector, FVector::ZeroVector };
33 // Initialized to something hight to minimize the artifacts
34 // when the initial values are unknown
35 PrevDeltaTime = std::numeric_limits<float>::max();
36}
37
42
44{
45 Super::Set(ActorDescription);
46 UActorBlueprintFunctionLibrary::SetIMU(ActorDescription, this);
47}
48
50{
51 Super::SetOwner(Owner);
52}
53
54// Returns the angular velocity of Actor, expressed in the frame of Actor
56 AActor &Actor)
57{
58 const auto RootComponent = Cast<UPrimitiveComponent>(Actor.GetRootComponent());
59
60 FVector AngularVelocity;
61
62 if (RootComponent != nullptr) {
63 const FQuat ActorGlobalRotation = RootComponent->GetComponentTransform().GetRotation();
64 const FVector GlobalAngularVelocity = RootComponent->GetPhysicsAngularVelocityInRadians();
65 AngularVelocity = ActorGlobalRotation.UnrotateVector(GlobalAngularVelocity);
66 } else {
67 AngularVelocity = FVector::ZeroVector;
68 }
69
70 return AngularVelocity;
71}
72
74 const FVector &Accelerometer)
75{
76 // Normal (or Gaussian or Gauss) distribution will be used as noise function.
77 // A mean of 0.0 is used as a first parameter, the standard deviation is
78 // determined by the client
79 constexpr float Mean = 0.0f;
81 Accelerometer.X + RandomEngine->GetNormalDistribution(Mean, StdDevAccel.X),
82 Accelerometer.Y + RandomEngine->GetNormalDistribution(Mean, StdDevAccel.Y),
83 Accelerometer.Z + RandomEngine->GetNormalDistribution(Mean, StdDevAccel.Z)
84 };
85}
86
88 const FVector &Gyroscope)
89{
90 // Normal (or Gaussian or Gauss) distribution and a bias will be used as
91 // noise function.
92 // A mean of 0.0 is used as a first parameter.The standard deviation and the
93 // bias are determined by the client
94 constexpr float Mean = 0.0f;
96 Gyroscope.X + BiasGyro.X + RandomEngine->GetNormalDistribution(Mean, StdDevGyro.X),
97 Gyroscope.Y + BiasGyro.Y + RandomEngine->GetNormalDistribution(Mean, StdDevGyro.Y),
98 Gyroscope.Z + BiasGyro.Z + RandomEngine->GetNormalDistribution(Mean, StdDevGyro.Z)
99 };
100}
101
103 const float DeltaTime)
104{
105 // Used to convert from UE4's cm to meters
106 constexpr float TO_METERS = 1e-2;
107 // Gravity set by gamemode
108 const float GRAVITY = UCarlaStatics::GetGameMode(GetWorld())->IMUISensorGravity;
109
110 // 2nd derivative of the polynomic (quadratic) interpolation
111 // using the point in current time and two previous steps:
112 // d2[i] = -2.0*(y1/(h1*h2)-y2/((h2+h1)*h2)-y0/(h1*(h2+h1)))
113 const FVector CurrentLocation = GetActorLocation();
114
115 const FVector Y2 = PrevLocation[0];
116 const FVector Y1 = PrevLocation[1];
117 const FVector Y0 = CurrentLocation;
118 const float H1 = DeltaTime;
119 const float H2 = PrevDeltaTime;
120
121 const float H1AndH2 = H2 + H1;
122 const FVector A = Y1 / ( H1 * H2 );
123 const FVector B = Y2 / ( H2 * (H1AndH2) );
124 const FVector C = Y0 / ( H1 * (H1AndH2) );
125 FVector FVectorAccelerometer = TO_METERS * -2.0f * ( A - B - C );
126
127 // Update the previous locations
129 PrevLocation[1] = CurrentLocation;
130 PrevDeltaTime = DeltaTime;
131
132 // Add gravitational acceleration
133 FVectorAccelerometer.Z += GRAVITY;
134
135 FQuat ImuRotation =
136 GetRootComponent()->GetComponentTransform().GetRotation();
137 FVectorAccelerometer = ImuRotation.UnrotateVector(FVectorAccelerometer);
138
139 // Cast from FVector to our Vector3D to correctly send the data in m/s^2
140 // and apply the desired noise function, in this case a normal distribution
141 const carla::geom::Vector3D Accelerometer =
142 ComputeAccelerometerNoise(FVectorAccelerometer);
143
144 return Accelerometer;
145}
146
148{
149 check(GetOwner() != nullptr);
150 const FVector AngularVelocity =
152
153 const FQuat SensorLocalRotation =
154 RootComponent->GetRelativeTransform().GetRotation();
155
156 const FVector FVectorGyroscope =
157 SensorLocalRotation.RotateVector(AngularVelocity);
158
159 // Cast from FVector to our Vector3D to correctly send the data in rad/s
160 // and apply the desired noise function, in this case a normal distribution
161 const carla::geom::Vector3D Gyroscope =
162 ComputeGyroscopeNoise(FVectorGyroscope);
163
164 return Gyroscope;
165}
166
168{
169 // Magnetometer: orientation with respect to the North in rad
170 const FVector ForwVect = GetActorForwardVector().GetSafeNormal2D();
171 const float DotProd = FVector::DotProduct(CarlaNorthVector, ForwVect);
172
173 // We check if the dot product is higher than 1.0 due to numerical error
174 if (DotProd >= 1.00f)
175 return 0.0f;
176
177 const float Compass = std::acos(DotProd);
178 // Keep the angle between [0, 2pi)
179 if (FVector::CrossProduct(CarlaNorthVector, ForwVect).Z < 0.0f)
180 return carla::geom::Math::Pi2<float>() - Compass;
181
182 return Compass;
183}
184
185void AInertialMeasurementUnit::PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaTime)
186{
187 carla::geom::Vector3D Accelerometer = ComputeAccelerometer(DeltaTime);
189 float Compass = ComputeCompass();
190
191 auto Stream = GetDataStream(*this);
192
193 // ROS2
194 #if defined(WITH_ROS2)
195 auto ROS2 = carla::ros2::ROS2::GetInstance();
196 if (ROS2->IsEnabled())
197 {
198 TRACE_CPUPROFILER_EVENT_SCOPE_STR("ROS2 Send");
200 AActor* ParentActor = GetAttachParentActor();
201 if (ParentActor)
202 {
203 FTransform LocalTransformRelativeToParent = GetActorTransform().GetRelativeTransform(ParentActor->GetActorTransform());
204 ROS2->ProcessDataFromIMU(Stream.GetSensorType(), StreamId, LocalTransformRelativeToParent, Accelerometer, Gyroscope, Compass, this);
205 }
206 else
207 {
208 ROS2->ProcessDataFromIMU(Stream.GetSensorType(), StreamId, Stream.GetSensorTransform(), Accelerometer, Gyroscope, Compass, this);
209 }
210 }
211 #endif
212
213 {
214 TRACE_CPUPROFILER_EVENT_SCOPE(AInertialMeasurementUnit::PostPhysTick);
215 Stream.SerializeAndSend(*this, Accelerometer, Gyroscope, Compass);
216 }
217}
218
223
225{
226 StdDevGyro = Vec;
227}
228
230{
231 BiasGyro = Vec;
232}
233
238
240{
241 return StdDevGyro;
242}
243
245{
246 return BiasGyro;
247}
248
250{
251 Super::BeginPlay();
252}
static FVector FIMU_GetActorAngularVelocityInRadians(AActor &Actor)
float ComputeCompass()
Magnetometer: orientation with respect to the North in rad
const FVector & GetAccelerationStandardDeviation() const
AInertialMeasurementUnit(const FObjectInitializer &ObjectInitializer)
const carla::geom::Vector3D ComputeGyroscopeNoise(const FVector &Gyroscope)
FVector StdDevAccel
Standard deviation for acceleration settings.
const carla::geom::Vector3D ComputeAccelerometerNoise(const FVector &Accelerometer)
void SetGyroscopeBias(const FVector &Vec)
void SetOwner(AActor *Owner) override
static const FVector CarlaNorthVector
Based on OpenDRIVE's lon and lat, North is in (0.0f, -1.0f, 0.0f)
FVector BiasGyro
Bias for gyroscope settings.
carla::geom::Vector3D ComputeGyroscope()
Gyroscope: measures angular velocity in rad/sec
virtual void PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaTime) override
FVector StdDevGyro
Standard deviation for gyroscope settings.
static FActorDefinition GetSensorDefinition()
void Set(const FActorDescription &ActorDescription) override
const FVector & GetGyroscopeBias() const
float PrevDeltaTime
Used to compute the acceleration
void SetAccelerationStandardDeviation(const FVector &Vec)
carla::geom::Vector3D ComputeAccelerometer(const float DeltaTime)
Accelerometer: measures linear acceleration in m/s^2
void SetGyroscopeStandardDeviation(const FVector &Vec)
std::array< FVector, 2 > PrevLocation
Used to compute the acceleration
const FVector & GetGyroscopeStandardDeviation() const
auto GetToken() const
Return the token that allows subscribing to this sensor's stream.
FAsyncDataStream GetDataStream(const SensorT &Self)
Return the FDataStream associated with this sensor.
URandomEngine * RandomEngine
Random Engine used to provide noise for sensor output.
uint64_t GetSensorType()
Definition DataStream.h:58
static void SetIMU(const FActorDescription &Description, AInertialMeasurementUnit *IMU)
static ACarlaGameModeBase * GetGameMode(const UObject *WorldContextObject)
float GetNormalDistribution(float Mean, float StandardDeviation)
static std::shared_ptr< ROS2 > GetInstance()
Definition ROS2.h:51
Serializes a stream endpoint.
A definition of a Carla Actor with all the variation and attributes.
A description of a Carla Actor with all its variation.