Skip to content

Commit

Permalink
Add lunar pole exploration assets and plugins (fix issue #22)
Browse files Browse the repository at this point in the history
This commit adds the following:
- A Gazebo model for a lunar rover inspired by the VIPER rover
- A 3D terrain model of the Mons Mouton from NASA LRO DEM data
- A series of power generation and management plugins
  - A solar panel plugin
  - An RTG plugin
  - A rechargeable battery
  - A sensor power load system
  • Loading branch information
RBinsonB committed Sep 6, 2024
1 parent 5a67b1c commit 3b11546
Show file tree
Hide file tree
Showing 36 changed files with 6,412 additions and 1 deletion.
79 changes: 78 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,15 +1,92 @@
cmake_minimum_required(VERSION 3.8)
project(simulation)

# Find required packages
find_package(ament_cmake REQUIRED)
find_package(ignition-plugin1 REQUIRED COMPONENTS register)
find_package(ignition-gazebo6 REQUIRED)
find_package(ignition-physics5 REQUIRED)
find_package(ignition-common4 REQUIRED)
find_package(ignition-rendering6 REQUIRED)

# Set Gazebo plugin and sim versions
set(IGNITION_PLUGIN_VER ${ignition-plugin1_VERSION_MAJOR})
set(IGNITION_SIM_VER ${ignition-gazebo6_VERSION_MAJOR})
set(IGNITION_COMMON_VER ${ignition-common4_VERSION_MAJOR})
set(IGNITION_RENDERING_VER ${ignition-rendering6_VERSION_MAJOR})
set(IGNITION_SENSORS_VER ${ignition-sensors6_VERSION_MAJOR})

# Add the plugins directory to the include path
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Plugins)

# Add the SolarPanelPlugin library
add_library(SolarPanelPlugin SHARED
plugins/SolarPanelPlugin.cc
)

# Link the SolarPanelPlugin library with required dependencies
target_link_libraries(SolarPanelPlugin
PRIVATE ignition-plugin${IGNITION_PLUGIN_VER}::ignition-plugin${IGNITION_PLUGIN_VER}
PRIVATE ignition-common${IGNITION_COMMON_VER}::ignition-common${IGNITION_COMMON_VER}
PRIVATE ignition-rendering${IGNITION_RENDERING_VER}::ignition-rendering${IGNITION_RENDERING_VER}
PRIVATE ignition-gazebo${IGNITION_SIM_VER}::core
)

# Add the RadioisotopeThermalGeneratorPlugin library
add_library(RadioisotopeThermalGeneratorPlugin SHARED
plugins/RadioisotopeThermalGeneratorPlugin.cc
)

# Link the RadioisotopeThermalGeneratorPlugin library with required dependencies
target_link_libraries(RadioisotopeThermalGeneratorPlugin
PRIVATE ignition-plugin${IGNITION_PLUGIN_VER}::ignition-plugin${IGNITION_PLUGIN_VER}
PRIVATE ignition-gazebo${IGNITION_SIM_VER}::core
)

# Add the RechargeableBatteryPlugin library
add_library(RechargeableBatteryPlugin SHARED
plugins/RechargeableBatteryPlugin.cc
)

# Link the RechargeableBatteryPlugin library with required dependencies
target_link_libraries(RechargeableBatteryPlugin
PRIVATE ignition-plugin${IGNITION_PLUGIN_VER}::ignition-plugin${IGNITION_PLUGIN_VER}
PRIVATE ignition-gazebo${IGNITION_SIM_VER}::core
# PRIVATE ignition-common${IGN_COMMON_VER}::ignition-common${IGNITION_COMMON_VER}
)


# add the SensorPowerSystemPlugin library
add_library(SensorPowerSystemPlugin SHARED
plugins/SensorPowerSystemPlugin.cc
)

# Link the SensorPowerSystemPlugin library with required dependencies
target_link_libraries(SensorPowerSystemPlugin
PRIVATE ignition-plugin${IGNITION_PLUGIN_VER}::ignition-plugin${IGNITION_PLUGIN_VER}
PRIVATE ignition-gazebo${IGNITION_SIM_VER}::core
PRIVATE ignition-gazebo${IGNITION_SIM_VER}::ignition-gazebo${IGNITION_SIM_VER}
PRIVATE ignition-sensors${IGNITION_SENSORS_VER}::ignition-sensors${IGNITION_SENSORS_VER}
)


# Create the models directory
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/models/curiosity_path)

# Install directories
install(DIRECTORY
models
${CMAKE_CURRENT_BINARY_DIR}/models
DESTINATION share/${PROJECT_NAME}/
)

# Install the plugin library
install(TARGETS SolarPanelPlugin RadioisotopeThermalGeneratorPlugin RechargeableBatteryPlugin SensorPowerSystemPlugin
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)

ament_environment_hooks("${CMAKE_CURRENT_SOURCE_DIR}/hooks/${PROJECT_NAME}.dsv.in")

ament_package()
ament_package()
228 changes: 228 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,230 @@
# simulation
Simulation assets of space-ros demos

## Plugins
Custom Gazebo plugins are included in the package.

### SolarPanelPlugin
The solar panel plugin allows to simulate solar panel power output depending on the panel orientation relative to the sun and LOS.

* Required elements
* **link_name** (`str`) -- The solar panel link in the model
* **nominal_power** (`float`) -- The maximum power supplied by the solar panel when the sun is hitting perdendicular

* Publications
* **/model/<model_name>/<link_name>/solar_panel_output** (`std_msgs::msg::Float`) -- Publishes the current solar panel output in watt.

#### How to setup the plugin
The plugin needs to be attached to a model. The link specified by **<link_name>** is the solar panel.


```XML
<plugin filename="libSolarPanelPlugin.so" name="simulation::SolarPanelPlugin">
<link_name>rear_solar_panel</link_name>
<nominal_power>150.0</nominal_power>
</plugin>
```
- The solar panel link needs to have a visual element. The power output is calculated by using the Z-axis of the solar panel link (Z-axis is considered the normal axis to the solar panel).
- **Important**: Some URDF parsers lump together links with fixed joints. To ensure the plugin is working correctly, it might be necessary for the solar panel link to be joined with a dynamic type of joint (and by setting the limits to zero if no motion is required). Example below:

```XML
<joint name="solar_panel_joint" type="revolute">
<parent link="body"/>
<child link="solar_panel"/>
<origin xyz="0.0252 0.7253 0.3829" rpy="1.4673 0 ${-PI}"/>
<axis xyz="0 0 1"/>
<limit lower="0.0" upper="0.0" effort="1e10" velocity="0.0"/>
</joint>
```
- The plugin need a sun entity in the world. The sun needs to be a `light` entity of type `directional` with the name `sun`. The element `<pose>` and `<direction>` of the sun are used by the plugin and need to be set properly. Example below:
```XML
<light type="directional" name="sun">
<cast_shadows>true</cast_shadows>
<pose>-2000 2000 100 0 0 0</pose>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.2 0.2 0.2 1</specular>
<intensity>1.5</intensity>
<attenuation>
<range>100000000</range>
<constant>1.0</constant>
<linear>0.0</linear>
<quadratic>0.001</quadratic>
</attenuation>
<direction>0.9 -0.9 -0.2</direction>
</light>
```
- **LOS (Line-Of-Sight)**: If the sun is occulted, no power is supplied by the solar panel plugin. To know if the panel is occulted, the plugin checks the line of sight between the `sun` (by using the `<pose>` element) and the link visual children. The panel solar link needs to have at least one visual element for the plugin to work.
- **Power computation**: The plugin computes the power generated by the panel by checking the angle between the Z-axis of the solar panel link and the `direction` vector of the sun.

### RadioisotopeThermalGeneratorPlugin
The radioisotope thermal generator plugin allows to simulate an RTG power output. It provides a constant power supply.

* Required elements
* **link_name** (`str`) -- The RTG link in the model
* **nominal_power** (`float`) -- The constant power in watt generated by the RTG.

* Publications
* **/model/<model_name>/<link_name>/radioisotope_thermal_generator_output** (`std_msgs::msg::Float`) -- Publishes the current solar panel output in watt.

#### How to setup the plugin
The plugin needs to be attached to a model. Example below:

```XML
<plugin filename="libRadioisotopeThermalGeneratorPlugin.so" name="simulation::RadioisotopeThermalGeneratorPlugin">
<link_name>chassis</link_name>
<nominal_power>100.0</nominal_power>
</plugin>
```

### RechargeableBatteryPlugin
The rechargeable battery plugin is a modified version of the stock LinearBatteryPlugin to allow recharge at a variable rate. It can be charged by any plugin providing a power output in watts on a Gazebo topic. In addition, by default, if no start draining topic is defined, the battery starts to drain as soon as the robot starts to move.

* Required elements
* **battery_name** (`str`) -- Unique name for the battery (required)
* **voltage** (`double`) -- Initial voltage of the battery (required)
* **open_circuit_voltage** (`double`) --
* **open_circuit_voltage_constant_coef** (`double`) -- Voltage at full charge
* **open_circuit_voltage_linear_coef** (`double`) -- Amount of voltage decrease when no charge
* **initial_charge** (`double`) -- Initial charge of the battery in Ah
* **capacity** (`double`) -- Total charge that the battery in Ah
* **resistance** (`double`) -- Internal resistance in Ohm
* **smooth_current_tau** (`double`) -- Coefficient for smoothing current [0, 1]
* **power_source** (`array[str]`) -- List of topic of power sources.
* **start_draining** (`boolean`) -- Whether to start draining the battery
* **power_draining_topic** (`str`) -- This is the topic to start draining the battery
* **stop_power_draining_topic** (`str`) -- This is to stop draining the battery
* **power_load** (`double`) -- Idle power load

* Publications
* **/model/lunar_pole_exploration_rover/battery/rechargeable_battery/state** (`ìgnition_msgs::msg::BaterrySate`) -- Publishes the current state of the battery **rechargeable_battery**

#### How to setup the plugin
The plugin needs to be attached to a model. Example below:

```XML
<plugin filename="libRechargeableBatteryPlugin.so" name="simulation::RechargeableBatteryPlugin">
<battery_name>rechargeable_battery</battery_name>
<voltage>30.0</voltage>
<open_circuit_voltage>30.0</open_circuit_voltage>
<open_circuit_voltage_constant_coef>30.0</open_circuit_voltage_constant_coef>
<open_circuit_voltage_linear_coef>-3.0</open_circuit_voltage_linear_coef>
<initial_charge>9.0</initial_charge>
<capacity>10.0</capacity>
<resistance>0.1</resistance>
<smooth_current_tau>1.0</smooth_current_tau>

<!-- power source -->
<power_source>left_solar_panel/solar_panel_output</power_source>
<power_source>right_solar_panel/solar_panel_output</power_source>
<power_source>rtg_body/radioisotope_thermal_generator_output</power_source>

<power_load>11.0</power_load>
<power_draining_topic>/battery/discharge</power_draining_topic>
</plugin>
```

* The power source topic needs to be on the format `<link_name>/<plugin_power_output_name>`. As of now, the following plugins can provide power to charge the battery:
* **SolarPanelPlugin**: with topic `<link_name>/solar_panel_output`
* **RadioisotopeThermalGeneratorPlugin**: with topic `<link_name>/radioisotope_thermal_generator_output`

### SensorPowerSystemPlugin
The sensor power system plugin pairs with the RechargeableBatteryPlugin allowing one to define for each sensor the power load it consumes from any battery in the model. Sensors can be deactivated to save power (as it is often the case on real space missions). When the battery is too low, the sensors managed by the plugin will also be deactivated. In addition, topics are exposed to disable the power load of each sensor consumption on demand. The topic uses the following format.

* **/model/lunar_pole_exploration_rover/sensor/`<sensor-name>`/activate** (`ìgnition_msgs::msg::Boolean`) -- Topic available to activate/deactivate the power consumption of sensor.

The model can have multiple batteries and each sensor consumes from any of those batteries.

#### How to setup the plugin
The plugin needs to be attached to a model. Example below:

```XML
<plugin filename="libSensorPowerSystemPlugin.so" name="simulation::SensorPowerSystemPlugin">
</plugin>
```

In addition, you need to include in each of the sensors, the power load and the battery they consume from. Example below:

```XML
<gazebo reference="nav_camera_link_left">
<sensor type="camera" name="NavCam_left">
<visualize>1</visualize>
<update_rate>10.0</update_rate>
<power_load>11.0</power_load>
<battery_name>rechargeable_battery</battery_name>
<camera>
<pose>1.0 0 0 0 0 0</pose>
<horizontal_fov>1.22173</horizontal_fov>
<image>
<width>2048</width>
<height>2048</height>
<format>L16</format>
</image>
<clip>
<near>0.01</near>
<far>100</far>
</clip>
<noise>
<type>gaussian</type>
<stddev>0.007</stddev>
</noise>
</camera>
<always_on>1</always_on>
<topic>navcam_left/image_raw</topic>
</sensor>
</gazebo>
```


## Models

### lunar_pole_exploration_rover
The lunar pole exploration rover is a lunar rover heavily inspired by the VIPER rover. The model can be loaded in Gazebo to fully simulate the rover. information on the rover was obtained from https://ntrs.nasa.gov/api/citations/20210015009/downloads/20210015009%20-%20Colaprete-VIPER%20PIP%20final.pdf.


#### Simulated power
The rover model includes a battery simulated by the RechargeableBatteryPlugin.
The battery is recharged by three solar panels of 150W each. The solar panels are simulated by the SolarPanelPlugin.

#### Control
The model has four steerable powered wheels. Each wheels is attached to the rover body with a passive suspension.
In addition, the navigation cameras are mounted on a mast and can pan and tilt.

#### Sensors
It features a similar sensor suit of the real VIPER rover:
- A pair of monochrome cameras for navigation, NavCam, mounted on the rover mast
- A pair of monochrome cameras for the aft blind spots, AftCam, facing back
- An IMU
- Odometry plugin

#### Published Topics
* **/model/lunar_pole_exploration_rover/left_solar_panel/solar_panel_output** (`ignition_msgs::msg::Float32`) -- Publishes the current output of the left solar panel in watt
* **/model/lunar_pole_exploration_rover/right_solar_panel/solar_panel_output** (`ignition_msgs::msg::Float32`) -- Publishes the current output of the right solar panel in watt
* **/model/lunar_pole_exploration_rover/rear_solar_panel/solar_panel_output** (`ignition_msgs::msg::Float32`) -- Publishes the current output of the rear solar panel in watt
* **/model/lunar_pole_exploration_rover/odometry** (`ignition_msgs::msg::Odometry`) -- Robot odometry
* **/model/lunar_pole_exploration_rover/odometry_with_covariance**(`ignition_msgs::msg::OdometryWithCovariance`) -- Robot odometry
* **/model/lunar_pole_exploration_rover/pose**(`ignition_msgs::msg::Pose`) -- Robot estimated pose from odometry
* **/model/lunar_pole_exploration_rover/battery/rechargeable_battery/state** (`ìgnition_msgs::msg::BaterrySate`) -- Publishes the current state of the battery **rechargeable_battery**
* **aft_cam_left/camera_info** (`ignition_msgs::msg::CameraInfo`) -- AftCam left camera info
* **aft_cam_right/camera_info** (`ignition_msgs::msg::CameraInfo`) -- AftCam right camera info
* **nav_cam_left/camera_info** (`ignition_msgs::msg::CameraInfo`) -- NavCam left camera info
* **nav_cam_right/camera_info** (`ignition_msgs::msg::CameraInfo`) -- NavCam right camera info
* **aft_cam_left/image_raw** (`ignition_msgs::msg::Image`) -- AftCam left camera image
* **aft_cam_right/image_raw** (`ignition_msgs::msg::Image`) -- AftCam right camera image
* **nav_cam_left/image_raw** (`ignition_msgs::msg::Image`) -- NavCam left camera image
* **nav_cam_right/image_raw** (`ignition_msgs::msg::Image`) -- NavCam right camera image

#### Controllable Joint Interfaces
* mast_head_pivot_joint (`revolute`) -- NavCam pan joint
* mast_camera_joint (`revolute`) -- NavCam tilt joint
* front_left_wheel_joint (`revolute`) -- front left wheel rotation joint
* rear_left_wheel_joint (`revolute`) -- rear left wheel rotation joint
* front_right_wheel_joint (`revolute`) -- front right wheel rotation joint
* rear_right_wheel_joint (`revolute`) -- rear right wheel rotation joint
* front_left_wheel_axle_joint (`revolute`) -- front left wheel steer joint
* rear_left_wheel_axle_joint (`revolute`) -- rear left wheel steer joint
* front_right_wheel_axle_joint (`revolute`) -- front right wheel steer joint
* rear_right_wheel_axle_joint (`revolute`) -- rear right wheel steer joint

### moon_mons_mouton
A model for the terrain of the Mons Mouton mountain located near the lunar south pole (also formaly refered to as Liebnitz Beta). This model was generated by using DEM data (site20) from the NASA LRO mission: https://pgda.gsfc.nasa.gov/products/78 (Barker, M.K., et al. (2021), Improved LOLA Elevation Maps for South Pole Landing Sites: Error Estimates and Their Impact on Illumination Conditions, Planetary & Space Science, Volume 203, 1 September 2021, 105119, doi:10.1016/j.pss.2020.105119.).
29 changes: 29 additions & 0 deletions models/curiosity_path/urdf/curiosity_mars_rover.gazebo
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,35 @@
<render_engine>ogre2</render_engine>
<background_color>0.9 0.753 0.66 1</background_color>
</plugin>

<plugin filename="libSolarPanelPlugin.so" name="simulation::SolarPanelPlugin">
<link_name>arm_tools</link_name>
<nominal_power>100.0</nominal_power>
</plugin>
<plugin filename="libRadioisotopeThermalGeneratorPlugin.so" name="simulation::RadioisotopeThermalGeneratorPlugin">
<link_name>chassis</link_name>
<nominal_power>100.0</nominal_power>
<plugin filename="libRechargeableBatteryPlugin.so" name="simulation::RechargeableBatteryPlugin">
<!-- https://ntrs.nasa.gov/api/citations/20080015793/downloads/20080015793.pdf -->
<battery_name>rechargeable_battery</battery_name>
<voltage>30.0</voltage>
<open_circuit_voltage>30.0</open_circuit_voltage>
<open_circuit_voltage_constant_coef>30.0</open_circuit_voltage_constant_coef>
<open_circuit_voltage_linear_coef>-3.0</open_circuit_voltage_linear_coef>
<initial_charge>9.0</initial_charge>
<capacity>10.0</capacity>
<resistance>0.1</resistance>
<smooth_current_tau>1.0</smooth_current_tau>

<!-- power source -->
<power_source>chassis/radioisotope_thermal_generator_output</power_source>

<!-- Power load without movement -->
<!-- this needs to revised with the actual power consumption of the robot -->
<power_load>11.0</power_load>


</plugin>
</gazebo>

<gazebo reference="lidar_link">
Expand Down
Loading

0 comments on commit 3b11546

Please sign in to comment.