Skip to content

Commit 67d5b6a

Browse files
authored
Add Wind simulation (#2867)
* Add Wind force calculation to PhysicsEngine Use velocity wrt wind to calculate drag forces * Add Settings field for Wind, simSetWind API * Add documentation, example script for setWind API * [Unity] Set Wind API implementation
1 parent 8d80ccd commit 67d5b6a

File tree

23 files changed

+156
-9
lines changed

23 files changed

+156
-9
lines changed

AirLib/include/api/RpcLibClientBase.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ class RpcLibClientBase {
118118
void stopRecording();
119119
bool isRecording();
120120

121+
void simSetWind(const Vector3r& wind) const;
122+
121123
protected:
122124
void* getClient();
123125
const void* getClient() const;

AirLib/include/api/WorldSimApiBase.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ class WorldSimApiBase {
7171
virtual void startRecording() = 0;
7272
virtual void stopRecording() = 0;
7373
virtual bool isRecording() const = 0;
74+
75+
virtual void setWind(const Vector3r& wind) const = 0;
7476
};
7577

7678

AirLib/include/common/AirSimSettings.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ struct AirSimSettings {
362362
float speed_unit_factor = 1.0f;
363363
std::string speed_unit_label = "m\\s";
364364
std::map<std::string, std::unique_ptr<SensorSetting>> sensor_defaults;
365+
Vector3r wind = Vector3r::Zero();
365366

366367
public: //methods
367368
static AirSimSettings& singleton()
@@ -1064,6 +1065,14 @@ struct AirSimSettings {
10641065
tod_setting.move_sun = tod_settings_json.getBool("MoveSun", tod_setting.move_sun);
10651066
}
10661067
}
1068+
1069+
{
1070+
// Wind Settings
1071+
Settings child_json;
1072+
if (settings_json.getChild("Wind", child_json)) {
1073+
wind = createVectorSetting(child_json, wind);
1074+
}
1075+
}
10671076
}
10681077

10691078
static void loadDefaultCameraSetting(const Settings& settings_json, CameraSetting& camera_defaults)

AirLib/include/physics/FastPhysicsEngine.hpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ namespace msr { namespace airlib {
1818

1919
class FastPhysicsEngine : public PhysicsEngineBase {
2020
public:
21-
FastPhysicsEngine(bool enable_ground_lock = true)
22-
: enable_ground_lock_(enable_ground_lock)
21+
FastPhysicsEngine(bool enable_ground_lock = true, Vector3r wind = Vector3r::Zero())
22+
: enable_ground_lock_(enable_ground_lock), wind_(wind)
2323
{
2424
}
2525

@@ -59,6 +59,12 @@ class FastPhysicsEngine : public PhysicsEngineBase {
5959
}
6060
//*** End: UpdatableState implementation ***//
6161

62+
// Set Wind, for API and Settings implementation
63+
void setWind(const Vector3r& wind) override
64+
{
65+
wind_ = wind;
66+
}
67+
6268
private:
6369
void initPhysicsBody(PhysicsBody* body_ptr)
6470
{
@@ -76,7 +82,7 @@ class FastPhysicsEngine : public PhysicsEngineBase {
7682

7783
//first compute the response as if there was no collision
7884
//this is necessary to take in to account forces and torques generated by body
79-
getNextKinematicsNoCollision(dt, body, current, next, next_wrench);
85+
getNextKinematicsNoCollision(dt, body, current, next, next_wrench, wind_);
8086

8187
//if there is collision, see if we need collision response
8288
const CollisionInfo collision_info = body.getCollisionInfo();
@@ -255,9 +261,9 @@ class FastPhysicsEngine : public PhysicsEngineBase {
255261
}
256262

257263
static Wrench getDragWrench(const PhysicsBody& body, const Quaternionr& orientation,
258-
const Vector3r& linear_vel, const Vector3r& angular_vel_body)
264+
const Vector3r& linear_vel, const Vector3r& angular_vel_body, const Vector3r& wind_world)
259265
{
260-
//add linear drag due to velocity we had since last dt seconds
266+
//add linear drag due to velocity we had since last dt seconds + wind
261267
//drag vector magnitude is proportional to v^2, direction opposite of velocity
262268
//total drag is b*v + c*v*v but we ignore the first term as b << c (pg 44, Classical Mechanics, John Taylor)
263269
//To find the drag force, we find the magnitude in the body frame and unit vector direction in world frame
@@ -268,9 +274,13 @@ class FastPhysicsEngine : public PhysicsEngineBase {
268274
Wrench wrench = Wrench::zero();
269275
const real_T air_density = body.getEnvironment().getState().air_density;
270276

277+
// Use relative velocity of the body wrt wind
278+
const Vector3r relative_vel = linear_vel - wind_world;
279+
const Vector3r linear_vel_body = VectorMath::transformToBodyFrame(relative_vel, orientation);
280+
271281
for (uint vi = 0; vi < body.dragVertexCount(); ++vi) {
272282
const auto& vertex = body.getDragVertex(vi);
273-
const Vector3r vel_vertex = VectorMath::transformToBodyFrame(linear_vel, orientation) + angular_vel_body.cross(vertex.getPosition());
283+
const Vector3r vel_vertex = linear_vel_body + angular_vel_body.cross(vertex.getPosition());
274284
const real_T vel_comp = vertex.getNormal().dot(vel_vertex);
275285
//if vel_comp is -ve then we cull the face. If velocity too low then drag is not generated
276286
if (vel_comp > kDragMinVelocity) {
@@ -312,7 +322,7 @@ class FastPhysicsEngine : public PhysicsEngineBase {
312322
}
313323

314324
static void getNextKinematicsNoCollision(TTimeDelta dt, PhysicsBody& body, const Kinematics::State& current,
315-
Kinematics::State& next, Wrench& next_wrench)
325+
Kinematics::State& next, Wrench& next_wrench, const Vector3r& wind)
316326
{
317327
const real_T dt_real = static_cast<real_T>(dt);
318328

@@ -338,13 +348,13 @@ class FastPhysicsEngine : public PhysicsEngineBase {
338348
next.accelerations.linear = Vector3r::Zero();
339349
}
340350
else {
341-
//add linear drag due to velocity we had since last dt seconds
351+
//add linear drag due to velocity we had since last dt seconds + wind
342352
//drag vector magnitude is proportional to v^2, direction opposite of velocity
343353
//total drag is b*v + c*v*v but we ignore the first term as b << c (pg 44, Classical Mechanics, John Taylor)
344354
//To find the drag force, we find the magnitude in the body frame and unit vector direction in world frame
345355
avg_linear = current.twist.linear + current.accelerations.linear * (0.5f * dt_real);
346356
avg_angular = current.twist.angular + current.accelerations.angular * (0.5f * dt_real);
347-
const Wrench drag_wrench = getDragWrench(body, current.pose.orientation, avg_linear, avg_angular);
357+
const Wrench drag_wrench = getDragWrench(body, current.pose.orientation, avg_linear, avg_angular, wind);
348358

349359
next_wrench = body_wrench + drag_wrench;
350360

@@ -449,6 +459,7 @@ class FastPhysicsEngine : public PhysicsEngineBase {
449459
std::stringstream debug_string_;
450460
bool enable_ground_lock_;
451461
TTimePoint last_message_time;
462+
Vector3r wind_;
452463
};
453464

454465
}} //namespace

AirLib/include/physics/PhysicsEngineBase.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class PhysicsEngineBase : public UpdatableObject {
4444
virtual void erase_remove(TUpdatableObjectPtr obj) {
4545
members_.erase(std::remove(members_.begin(), members_.end(), obj), members_.end()); }
4646

47+
virtual void setWind(const Vector3r& wind) {};
48+
4749
private:
4850
MembersContainer members_;
4951
};

AirLib/src/api/RpcLibClientBase.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,12 @@ bool RpcLibClientBase::isRecording()
444444
return pimpl_->client.call("isRecording").as<bool>();
445445
}
446446

447+
void RpcLibClientBase::simSetWind(const Vector3r& wind) const
448+
{
449+
RpcLibAdapatorsBase::Vector3r conv_wind(wind);
450+
pimpl_->client.call("simSetWind", conv_wind);
451+
}
452+
447453
void* RpcLibClientBase::getClient()
448454
{
449455
return &pimpl_->client;

AirLib/src/api/RpcLibServerBase.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,10 @@ RpcLibServerBase::RpcLibServerBase(ApiProvider* api_provider, const std::string&
370370
return getWorldSimApi()->isRecording();
371371
});
372372

373+
pimpl_->server.bind("simSetWind", [&](const RpcLibAdapatorsBase::Vector3r& wind) -> void {
374+
getWorldSimApi()->setWind(wind.to());
375+
});
376+
373377
//if we don't suppress then server will bomb out for exceptions raised by any method
374378
pimpl_->server.suppress_exceptions(true);
375379
}

PythonClient/airsim/client.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,15 @@ def isRecording(self):
781781
"""
782782
return self.client.call('isRecording')
783783

784+
def simSetWind(self, wind):
785+
"""
786+
Set simulated wind, in World frame, NED direction, m/s
787+
788+
Args:
789+
wind (Vector3r): Wind, in World frame, NED direction, in m/s
790+
"""
791+
self.client.call('simSetWind', wind)
792+
784793
# ----------------------------------- Multirotor APIs ---------------------------------------------
785794
class MultirotorClient(VehicleClient, object):
786795
def __init__(self, ip = "", port = 41451, timeout_value = 3600):
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import setup_path
2+
import airsim
3+
import time
4+
5+
client = airsim.MultirotorClient()
6+
client.confirmConnection()
7+
client.enableApiControl(True)
8+
9+
client.armDisarm(True)
10+
11+
print("Setting wind to 10m/s in forward direction") # NED
12+
wind = airsim.Vector3r(10, 0, 0)
13+
client.simSetWind(wind)
14+
15+
# Takeoff or hover
16+
landed = client.getMultirotorState().landed_state
17+
if landed == airsim.LandedState.Landed:
18+
print("taking off...")
19+
client.takeoffAsync().join()
20+
else:
21+
print("already flying...")
22+
client.hoverAsync().join()
23+
24+
time.sleep(5)
25+
26+
print("Setting wind to 15m/s towards right") # NED
27+
wind = airsim.Vector3r(0, 15, 0)
28+
client.simSetWind(wind)
29+
30+
time.sleep(5)
31+
32+
# Set wind to 0
33+
print("Resetting wind to 0")
34+
wind = airsim.Vector3r(0, 0, 0)
35+
client.simSetWind(wind)

Unity/AirLibWrapper/AirsimWrapper/Source/SimMode/SimModeBase.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ void SimModeBase::setTimeOfDay(bool is_enabled, const std::string& start_datetim
8686
//throw std::domain_error("setTimeOfDay is not implemented by SimMode");
8787
}
8888

89+
void SimModeBase::setWind(const msr::airlib::Vector3r& wind) const
90+
{
91+
// should be overridden by derived class
92+
unused(wind);
93+
throw std::domain_error("setWind is not implemented by SimMode");
94+
}
95+
8996
std::unique_ptr<msr::airlib::ApiServerBase> SimModeBase::createApiServer() const
9097
{
9198
//this will be the case when compilation with RPCLIB is disabled or simmode doesn't support APIs

0 commit comments

Comments
 (0)