Skip to content

Commit

Permalink
Added DroneDustPlugin and added documentation for the plugins (space-…
Browse files Browse the repository at this point in the history
  • Loading branch information
namikxgithub committed Sep 11, 2024
1 parent 6839d24 commit 09b4544
Show file tree
Hide file tree
Showing 9 changed files with 280 additions and 4 deletions.
2 changes: 2 additions & 0 deletions custom_gz_plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ find_package(ament_cmake REQUIRED)
add_subdirectory(src/DayLightManager)
add_subdirectory(src/DustManager)
add_subdirectory(src/VehicleDust)
add_subdirectory(src/DroneDustPlguin)


## Install the launch directory
install(
Expand Down
20 changes: 16 additions & 4 deletions custom_gz_plugins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ The Dust Manager plugin enables the simulation of realistic dust behavior in Mar
![Dust Manager Gui](assets/dust_gui.gif)

### Car Dust Plugin
The Dust Emission Plugin simulates dust clouds generated by heavy vehicles moving across dusty terrains, such as the surfaces of Mars or the Moon. As vehicles traverse these environments, the plugin dynamically controls particle emitters to mimic realistic dust behavior, taking into account vehicle speed, surface texture, and atmospheric conditions. This enhances the accuracy of simulations for planetary exploration by providing lifelike interactions between vehicles and dust, aiding in the design and testing of exploration systems.

> For detailed description of the plugin and it's usage, click [here](src/VehicleDust/README.md)
![Car Dust](assets/car_dust.gif)

### Drone Dust Plugin
The Drone Dust plugin simulates the dust clouds dispersed by a drone's thrusters during takeoff and landing in dusty environments, such as on Mars or the Moon. It dynamically controls particle emitters based on the drone's movement and thruster activity, creating realistic dust dispersion effects. This plugin helps in evaluating how dust affects the drone's performance and surrounding environment, enabling more accurate simulations for planetary exploration and vehicle testing.

> For detailed description of the plugin and it's usage, click [here](src/DroneDustPlugin/README.md)
![Drone Dust](assets/drone_dust.gif)



### Real Surface Models
Custom models made from real elevation data (From NASA's Planetary Data System) of celestial bodies like Moon and Mars is also added.
Expand Down Expand Up @@ -51,10 +66,7 @@ This will run the container where you can launch the simulation.
```shell
ros2 launch custom_gz_plugins demo_world.launch.py
```




> In order to user the GUI Plugin: DustManger or DayLightManger, use to menu option in the simulation (Top Right Corner) to load the plugin


Expand Down
Binary file added custom_gz_plugins/assets/car_dust.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added custom_gz_plugins/assets/drone_dust.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions custom_gz_plugins/src/DroneDustPlugin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR)

find_package(gz-cmake3 REQUIRED)

project(DroneDust)

find_package(gz-plugin2 REQUIRED COMPONENTS register)
set(GZ_PLUGIN_VER ${gz-plugin2_VERSION_MAJOR})

find_package(gz-sim8 REQUIRED)
find_package(GTest REQUIRED)

add_library(DroneDust SHARED DroneDust.cc )
set_property(TARGET DroneDust PROPERTY CXX_STANDARD 17)
target_link_libraries(DroneDust
PRIVATE gz-plugin${GZ_PLUGIN_VER}::gz-plugin${GZ_PLUGIN_VER}
PRIVATE gz-sim8::gz-sim8)

install(TARGETS DroneDust
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
149 changes: 149 additions & 0 deletions custom_gz_plugins/src/DroneDustPlugin/DroneDust.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
The `DroneDustPrivate` is the main script which create a ignition gazebo node in oder to handle communication between the camera topics.
A subsciber is created which subscribes to the `/model/car/cmd_vel` topic build published by the camera plugin in the gazebo world.
The image recieved is first converted into opencv format using the GzCVBridge script on top of which a custom post processing
algorithm is applied using openCV in order to add the rain effect noise on the camera the frame. The rain augmented frame in them
published on a seperate topic called `/model/car/link/dust_link/particle_emitter/emitter/cmd`.
*/

#include <gz/plugin/Register.hh>
#include <gz/sim/components/Name.hh>
#include <gz/msgs.hh>
#include <gz/transport.hh>
#include <gz/msgs/particle_emitter.pb.h>

#include <iostream>
#include <string>
#include <csignal>

#include "DroneDust.hh"


namespace drone_dust
{
class DroneDustPrivate
{
public: gz::transport::Node node;

public: gz::transport::Node velDustNode;
public: gz::transport::Node::Publisher dustPub;

public: std::string robotName;
public: std::string modelName;

public: double actDist, minDist, densityConst, last_distance = 0;
public: double robot_x = 0, robot_y = 0, robot_z = 0;
public: double world_x = 0, world_y = 0, world_z = 0;
public: double scaleConst = 0.01;
public: double rateConst = 0.04;

public: void publish_dust(double rate_calculated, double scale_rate_calculated);
public: void PoseCb(const gz::msgs::Pose_V &_data);
};

void DroneDustPrivate::PoseCb(const gz::msgs::Pose_V &_data)
{
for (int i = 0; i < _data.pose().size(); i++) {
// std::cout<<"Pose Name: "<< pose_name << std::endl;
if ( _data.pose(i).name() == robotName)
{
robot_x = _data.pose(i).position().x();
robot_y = _data.pose(i).position().y();
robot_z = _data.pose(i).position().z();
// std::cout << "Robot " << robotName << " Z: " << robot_z << " index: " << i << std::endl;
}
}
for (int i = 0; i < _data.pose().size(); i++) {
std::string pose_name = _data.pose(i).name();
if (pose_name.find(modelName) != std::string::npos)
{
world_x = _data.pose(i).position().x();
world_y = _data.pose(i).position().y();
world_z = _data.pose(i).position().z();
// std::cout << "World Z: " << world_z << " index: " << i << std::endl;
}
}
double object_distance = robot_z - world_z;
gzmsg << "Object Distance: " << object_distance << std::endl;

if(object_distance < actDist && object_distance > minDist)
{
// std::cout << "World Z: " << world_z << std::endl;
double rate = densityConst * (actDist/object_distance) * this->rateConst;
double scale_rate = densityConst * (actDist/object_distance) * this->scaleConst;
// std::cout << "Scale Rate " << scale_rate << std::endl;
this->publish_dust(rate, scale_rate);
// gzmsg << "Rate: " << rate << " " << "Scale Rate: " << scale_rate << std::endl;
}
else
{
this->publish_dust(0, 0);
}
last_distance = object_distance;
}

void DroneDustPrivate::publish_dust(double rate_calculated, double scale_rate_calculated)
{

gz::msgs::ParticleEmitter *msg = new gz::msgs::ParticleEmitter();
gz::msgs::Float rate, scale_rate;

rate.set_data(rate_calculated);
scale_rate.set_data(scale_rate_calculated);

msg->set_allocated_rate(&rate);
msg->set_allocated_scale_rate(&scale_rate);

this->dustPub.Publish(*msg);

}

DroneDust::DroneDust()
: dataPtr(std::make_unique<DroneDustPrivate>())
{}

DroneDust::~DroneDust()
{}

void DroneDust::Configure(const gz::sim::Entity &_entity,
const std::shared_ptr<const sdf::Element> &_sdf,
gz::sim::EntityComponentManager &_ecm,
gz::sim::EventManager &)
{

auto worldName = _ecm.Component<gz::sim::components::Name>(_entity);

std::string poseInfoTopic = "/world/" + worldName->Data() + "/pose/info";

if(_sdf->HasElement("activation_distance"))
this->dataPtr->actDist = _sdf->Get<double>("activation_distance");
if(_sdf->HasElement("min_distance"))
this->dataPtr->minDist = _sdf->Get<double>("min_distance");
if(_sdf->HasElement("density_constant"))
this->dataPtr->densityConst = _sdf->Get<double>("density_constant");
if(_sdf->HasElement("robot_name"))
this->dataPtr->robotName = _sdf->Get<std::string>("robot_name");
if(_sdf->HasElement("model_name"))
this->dataPtr->modelName = _sdf->Get<std::string>("model_name");

std::string emitterTopic = "/model/" + this->dataPtr->robotName +"/link/dust_link/particle_emitter/emitter/cmd";

std::cout<< "Pose Topic: " << poseInfoTopic << std::endl;
std::cout<< "Emitter Topic: " << emitterTopic << std::endl;
std::cout<< "robot_name: " << this->dataPtr->robotName << std::endl;
std::cout<< "model_name: " << this->dataPtr->modelName << std::endl;

std::string poseTopicProcessed = gz::transport::TopicUtils::AsValidTopic(poseInfoTopic);
std::string poseInfoTopicProcessed = gz::transport::TopicUtils::AsValidTopic(poseInfoTopic);

this->dataPtr->node.Subscribe(poseInfoTopicProcessed, &DroneDustPrivate::PoseCb, this->dataPtr.get());

this->dataPtr->dustPub = this->dataPtr->velDustNode.Advertise<gz::msgs::ParticleEmitter>(emitterTopic);
}
}

GZ_ADD_PLUGIN(
drone_dust::DroneDust,
gz::sim::System,
drone_dust::DroneDust::ISystemConfigure
)
34 changes: 34 additions & 0 deletions custom_gz_plugins/src/DroneDustPlugin/DroneDust.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <string>
#include <gz/msgs.hh>
#include <gz/transport.hh>
#include <gz/sim/System.hh>

#define SCALE_CONST 0.9
#define RATE_CONST 4.0

// used if rain is set as high or low
// random int between these can be used if rain is medium
#define MAX_VEL 5.0

// rain drop maturity means that as the drop falls it gathers more water and falls faster and becomes more blurry
namespace drone_dust
{
class DroneDustPrivate;

class DroneDust:
public gz::sim::System,
public gz::sim::ISystemConfigure
{
public: DroneDust();

public: ~DroneDust() override;

public: void Configure(const gz::sim::Entity &_entity,
const std::shared_ptr<const sdf::Element> &_sdf,
gz::sim::EntityComponentManager &_ecm,
gz::sim::EventManager &_eventMgr) override;

private: std::unique_ptr<DroneDustPrivate> dataPtr;

};
}
32 changes: 32 additions & 0 deletions custom_gz_plugins/src/DroneDustPlugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Drone Dust Plugin

The Drone Dust plugin not only simulates the dust clouds generated by a drone’s thrusters during takeoff and landing, but also replicates how these dust particles affect onboard sensors crucial for autonomous operations.

- Depth Cameras: The dust clouds can scatter infrared or laser signals, causing depth cameras to misinterpret distances or fail to detect objects entirely, which can compromise altitude control and obstacle avoidance.

- RGB Cameras: Dust particles obscure visibility, reducing image clarity and potentially hindering visual navigation, object detection, and scene recognition used for autonomous decisions.

- 3D LiDAR: Dust clouds interfere with LiDAR by scattering its laser pulses, resulting in inaccurate 3D mapping and unreliable data on nearby objects or terrain, impacting the drone's ability to navigate and avoid obstacles autonomously.

By simulating these dust interactions, the plugin provides a realistic testing environment for drones, ensuring that autonomous systems can adapt to harsh planetary conditions where dust is a significant factor.

## Usage

```xml
<plugin
filename="DroneDust"
name="drone_dust::DroneDust">
<activation_distance>5</activation_distance>
<min_distance>0.27</min_distance>
<density_constant>12.0</density_constant>
<model_name>ground_plane</model_name>
<robot_name>ingenuity</robot_name>
</plugin>
```

- In order to load the pugin, add the above plugin tag into the world sdf and configure the following tags:
- robot_name: Name of the robot in the simulation
- model_name: Name of the base model in the simulation (Dusty Model)
- density_const: Multiplier for the amount of dust to be produced
- min_distance: Minimum difference in height at which dust starts to produce
- activation_distance: Maximum difference in height at which dust stops to produce
26 changes: 26 additions & 0 deletions custom_gz_plugins/src/VehicleDust/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Vehicle Dust Plugin
The Dust Emission Plugin not only simulates dust clouds generated by heavy vehicles on planetary surfaces like Mars or the Moon, but it also impacts the performance of various sensors such as depth cameras, RGB cameras, and 3D LiDAR.

- Depth Cameras: Dust particles may scatter infrared light, leading to noise in depth data or complete failure to capture the scene accurately.

- RGB Cameras: Dust clouds can reduce visibility for RGB cameras, as they create a haze that obstructs clear imagery. This reduction in clarity can affect visual navigation, object detection, and color-based tracking.

- 3D LiDAR: Dust interferes with LiDAR systems by scattering laser beams, causing reflections that may distort the returned signal. This can result in inaccurate distance measurements and false readings of the environment, compromising obstacle detection and mapping.

By simulating dust and its interactions with sensors, the plugin provides a more challenging and realistic testing environment, helping to ensure that sensor-based systems function effectively in harsh planetary conditions.


## Usage

```xml
<plugin
filename="VehicleDust"
name="vehicle_dust::VehicleDust">
<topic>/cmd_vel</topic>
<emitter_model>buggy_model</emitter_model>
</plugin>

```
- In order to load the pugin, add the above plugin tag into the world sdf and configure the following tags:
- topic: The command interface topic used to drive the robot
- emitter_model: Name of the robot in the simultion

0 comments on commit 09b4544

Please sign in to comment.