Skip to content

Commit

Permalink
Add SDFormat importer hooks (o3de#453)
Browse files Browse the repository at this point in the history
Add sensors SDF importer hooks

Signed-off-by: Jan Hanca <jan.hanca@robotec.ai>
Signed-off-by: Michał Pełka <michal.pelka@robotec.ai>
  • Loading branch information
jhanca-robotecai authored and michalpelka committed Sep 25, 2023
1 parent 241958b commit 603f29e
Show file tree
Hide file tree
Showing 12 changed files with 616 additions and 127 deletions.
50 changes: 25 additions & 25 deletions Gems/ROS2/Code/Source/Lidar/LidarTemplateUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,43 +148,43 @@ namespace ROS2
{
/*.m_model = */ Model::Custom2DLidar,
/*.m_name = */ "CustomLidar2D",
/*.m_minHAngle = */ -180.0f,
/*.m_maxHAngle = */ 180.0f,
/*.m_minVAngle = */ 0.f,
/*.m_maxVAngle = */ 0.f,
/*.m_layers = */ 1,
/*.m_numberOfIncrements = */ 924,
/*.m_minRange = */ 0.0f,
/*.m_maxRange = */ 100.0f,
/*.m_noiseParameters = */
{
/*.m_angularNoiseStdDev = */ 0.0f,
/*.m_minHAngle = */ -180.0f,
/*.m_maxHAngle = */ 180.0f,
/*.m_minVAngle = */ 0.f,
/*.m_maxVAngle = */ 0.f,
/*.m_layers = */ 1,
/*.m_numberOfIncrements = */ 924,
/*.m_minRange = */ 0.0f,
/*.m_maxRange = */ 100.0f,
/*.m_noiseParameters = */
{
/*.m_angularNoiseStdDev = */ 0.0f,
/*.m_distanceNoiseStdDevBase = */ 0.02f,
/*.m_distanceNoiseStdDevRisePerMeter = */ 0.001f,
},
}
},
},
{
Model::Slamtec_RPLIDAR_S1,
{
/*.m_model = */ Model::Slamtec_RPLIDAR_S1,
/*.m_name = */ "Slamtec RPLIDAR S1",
/*.m_minHAngle = */ -180.0f,
/*.m_maxHAngle = */ 180.0f,
/*.m_minVAngle = */ 0.f,
/*.m_maxVAngle = */ 0.f,
/*.m_layers = */ 1,
/*.m_numberOfIncrements = */ 921,
/*.m_minRange = */ 0.1f,
/*.m_maxRange = */ 40.0f,
/*.m_noiseParameters = */
{
/*.m_angularNoiseStdDev = */ 0.0f,
/*.m_minHAngle = */ -180.0f,
/*.m_maxHAngle = */ 180.0f,
/*.m_minVAngle = */ 0.f,
/*.m_maxVAngle = */ 0.f,
/*.m_layers = */ 1,
/*.m_numberOfIncrements = */ 921,
/*.m_minRange = */ 0.1f,
/*.m_maxRange = */ 40.0f,
/*.m_noiseParameters = */
{
/*.m_angularNoiseStdDev = */ 0.0f,
/*.m_distanceNoiseStdDevBase = */ 0.02f,
/*.m_distanceNoiseStdDevRisePerMeter = */ 0.001f,
},
}
},
},
}
};

auto it = templates.find(model);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ namespace ROS2
return m_controlConfiguration;
}

const TopicConfiguration& ROS2RobotControlComponent::GetSubscriberConfigration() const
const TopicConfiguration& ROS2RobotControlComponent::GetSubscriberConfiguration() const
{
return m_subscriberConfiguration;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ namespace ROS2

void SetControlConfiguration(const ControlConfiguration& controlConfiguration);

const TopicConfiguration& GetSubscriberConfigration() const;
const TopicConfiguration& GetSubscriberConfiguration() const;

void SetSubscriberConfiguration(const TopicConfiguration& subscriberConfiguration);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,17 @@
*
*/

#include "ROS2SensorHooks.h"

#include <Camera/CameraConstants.h>
#include <Camera/ROS2CameraSensorEditorComponent.h>
#include <GNSS/ROS2GNSSSensorComponent.h>
#include <RobotImporter/Utils/RobotImporterUtils.h>
#include <ROS2/Frame/ROS2FrameComponent.h>
#include <RobotImporter/SDFormat/ROS2SensorHooks.h>
#include <RobotImporter/SDFormat/ROS2SensorHooksUtils.h>

#include <sdf/Camera.hh>
#include <sdf/NavSat.hh>
#include <sdf/Sensor.hh>

namespace ROS2::SDFormat
{
namespace Internal
{
void AddTopicConfiguration(
SensorConfiguration& sensorConfig,
const AZStd::string& topic,
const AZStd::string& messageType,
const AZStd::string& configName)
{
TopicConfiguration config;
config.m_topic = topic;
config.m_type = messageType;
sensorConfig.m_publishersConfigurations.insert(AZStd::make_pair(configName, config));
}
} // namespace Internal

SensorImporterHook ROS2SensorHooks::ROS2CameraSensor()
{
SensorImporterHook importerHook;
Expand All @@ -49,14 +33,22 @@ namespace ROS2::SDFormat
const sdf::Sensor& sdfSensor) -> SensorImporterHook::ConvertSensorOutcome
{
auto* cameraSensor = sdfSensor.CameraSensor();
if (!cameraSensor)
{
return AZ::Failure(AZStd::string("Failed to read parsed SDFormat data of %s camera sensor", sdfSensor.Name().c_str()));
}

CameraSensorConfiguration cameraConfiguration;
cameraConfiguration.m_depthCamera = cameraSensor->HasDepthCamera();
cameraConfiguration.m_colorCamera = (sdfSensor.Type() != sdf::SensorType::DEPTH_CAMERA) ? true : false;
cameraConfiguration.m_width = cameraSensor->ImageWidth();
cameraConfiguration.m_height = cameraSensor->ImageHeight();
cameraConfiguration.m_verticalFieldOfViewDeg =
cameraSensor->HorizontalFov().Degree() * (cameraConfiguration.m_height / cameraConfiguration.m_width);
if (cameraConfiguration.m_width != 0)
{
double aspectRatio = static_cast<double>(cameraConfiguration.m_height) / cameraConfiguration.m_width;
cameraConfiguration.m_verticalFieldOfViewDeg =
2.0 * AZStd::atan(AZStd::tan(cameraSensor->HorizontalFov().Radian() / 2.0) * aspectRatio);
}
if (sdfSensor.Type() != sdf::SensorType::DEPTH_CAMERA)
{
cameraConfiguration.m_nearClipDistance = static_cast<float>(cameraSensor->NearClip());
Expand All @@ -71,21 +63,25 @@ namespace ROS2::SDFormat
SensorConfiguration sensorConfiguration;
sensorConfiguration.m_frequency = sdfSensor.UpdateRate();
if (sdfSensor.Type() != sdf::SensorType::DEPTH_CAMERA)
{
Internal::AddTopicConfiguration(
{ // COLOR_CAMERA and RGBD_CAMERA
Utils::AddTopicConfiguration(
sensorConfiguration, "camera_image_color", CameraConstants::ImageMessageType, CameraConstants::ColorImageConfig);
Internal::AddTopicConfiguration(
Utils::AddTopicConfiguration(
sensorConfiguration, "color_camera_info", CameraConstants::CameraInfoMessageType, CameraConstants::ColorInfoConfig);
}
if (sdfSensor.Type() != sdf::SensorType::CAMERA)
{
Internal::AddTopicConfiguration(
{ // DEPTH_CAMERA and RGBD_CAMERA
Utils::AddTopicConfiguration(
sensorConfiguration, "camera_image_depth", CameraConstants::ImageMessageType, CameraConstants::DepthImageConfig);
Internal::AddTopicConfiguration(
Utils::AddTopicConfiguration(
sensorConfiguration, "depth_camera_info", CameraConstants::CameraInfoMessageType, CameraConstants::DepthInfoConfig);
}

if (entity.CreateComponent<ROS2CameraSensorEditorComponent>(sensorConfiguration, cameraConfiguration))
// Create required components
Utils::CreateComponent<ROS2FrameComponent>(entity);

// Create Camera component
if (Utils::CreateComponent<ROS2CameraSensorEditorComponent>(entity, sensorConfiguration, cameraConfiguration))
{
return AZ::Success();
}
Expand All @@ -97,5 +93,4 @@ namespace ROS2::SDFormat

return importerHook;
}

} // namespace ROS2::SDFormat
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/

#include <GNSS/ROS2GNSSSensorComponent.h>
#include <RobotImporter/SDFormat/ROS2SensorHooks.h>
#include <RobotImporter/SDFormat/ROS2SensorHooksUtils.h>

#include <sdf/NavSat.hh>
#include <sdf/Sensor.hh>

namespace ROS2::SDFormat
{
SensorImporterHook ROS2SensorHooks::ROS2GNSSSensor()
{
SensorImporterHook importerHook;
importerHook.m_sensorTypes = AZStd::unordered_set<sdf::SensorType>{ sdf::SensorType::NAVSAT };
importerHook.m_supportedSensorParams = AZStd::unordered_set<AZStd::string>{ ">update_rate" };
importerHook.m_pluginNames = AZStd::unordered_set<AZStd::string>{ "libgazebo_ros_gps_sensor.so" };
importerHook.m_supportedPluginParams = AZStd::unordered_set<AZStd::string>{};
importerHook.m_sdfSensorToComponentCallback = [](AZ::Entity& entity,
const sdf::Sensor& sdfSensor) -> SensorImporterHook::ConvertSensorOutcome
{
if (!sdfSensor.NavSatSensor())
{
return AZ::Failure(AZStd::string("Failed to read parsed SDFormat data of %s NavSat sensor", sdfSensor.Name().c_str()));
}

SensorConfiguration sensorConfiguration;
sensorConfiguration.m_frequency = sdfSensor.UpdateRate();
const AZStd::string messageType = "sensor_msgs::msg::NavSatFix";
Utils::AddTopicConfiguration(sensorConfiguration, "gnss", messageType, messageType);

if (Utils::CreateComponent<ROS2GNSSSensorComponent>(entity, sensorConfiguration, GNSSSensorConfiguration()))
{
return AZ::Success();
}
else
{
return AZ::Failure(AZStd::string("Failed to create ROS2 GNSS Sensor component"));
}
};

return importerHook;
}
} // namespace ROS2::SDFormat
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/

#include <Imu/ROS2ImuSensorComponent.h>
#include <ROS2/Frame/ROS2FrameComponent.h>
#include <RobotImporter/SDFormat/ROS2SensorHooks.h>
#include <RobotImporter/SDFormat/ROS2SensorHooksUtils.h>
#include <Source/EditorStaticRigidBodyComponent.h>

#include <sdf/Imu.hh>
#include <sdf/Sensor.hh>

namespace ROS2::SDFormat
{
SensorImporterHook ROS2SensorHooks::ROS2ImuSensor()
{
SensorImporterHook importerHook;
importerHook.m_sensorTypes = AZStd::unordered_set<sdf::SensorType>{ sdf::SensorType::IMU };
importerHook.m_supportedSensorParams = AZStd::unordered_set<AZStd::string>{ ">update_rate",
">imu>angular_velocity>x>noise>mean",
">imu>angular_velocity>x>noise>stddev",
">imu>angular_velocity>y>noise>mean",
">imu>angular_velocity>y>noise>stddev",
">imu>angular_velocity>z>noise>mean",
">imu>angular_velocity>z>noise>stddev",
">imu>linear_acceleration>x>noise>mean",
">imu>linear_acceleration>x>noise>stddev",
">imu>linear_acceleration>y>noise>mean",
">imu>linear_acceleration>y>noise>stddev",
">imu>linear_acceleration>z>noise>mean",
">imu>linear_acceleration>z>noise>stddev" };
importerHook.m_pluginNames = AZStd::unordered_set<AZStd::string>{ "libgazebo_ros_imu_sensor.so" };
importerHook.m_supportedPluginParams = AZStd::unordered_set<AZStd::string>{};
importerHook.m_sdfSensorToComponentCallback = [](AZ::Entity& entity,
const sdf::Sensor& sdfSensor) -> SensorImporterHook::ConvertSensorOutcome
{
auto* imuSensor = sdfSensor.ImuSensor();
if (!imuSensor)
{
return AZ::Failure(AZStd::string("Failed to read parsed SDFormat data of %s imu sensor", sdfSensor.Name().c_str()));
}

ImuSensorConfiguration imuConfiguration;
const auto& angVelXNoise = imuSensor->AngularVelocityXNoise();
const auto& angVelYNoise = imuSensor->AngularVelocityYNoise();
const auto& angVelZNoise = imuSensor->AngularVelocityZNoise();
if (angVelXNoise.Type() == sdf::NoiseType::GAUSSIAN && angVelYNoise.Type() == sdf::NoiseType::GAUSSIAN &&
angVelZNoise.Type() == sdf::NoiseType::GAUSSIAN)
{
if (angVelXNoise.Mean() == 0.0 && angVelYNoise.Mean() == 0.0 && angVelZNoise.Mean() == 0.0)
{
imuConfiguration.m_angularVelocityVariance = AZ::Vector3(
static_cast<float>(angVelXNoise.StdDev() * angVelXNoise.StdDev()),
static_cast<float>(angVelYNoise.StdDev() * angVelYNoise.StdDev()),
static_cast<float>(angVelZNoise.StdDev() * angVelZNoise.StdDev()));
}
}

const auto& linAccXNoise = imuSensor->LinearAccelerationXNoise();
const auto& linAccYNoise = imuSensor->LinearAccelerationYNoise();
const auto& linAccZNoise = imuSensor->LinearAccelerationZNoise();
if (linAccXNoise.Type() == sdf::NoiseType::GAUSSIAN && linAccYNoise.Type() == sdf::NoiseType::GAUSSIAN &&
linAccZNoise.Type() == sdf::NoiseType::GAUSSIAN)
{
if (linAccXNoise.Mean() == 0.0 && linAccYNoise.Mean() == 0.0 && linAccZNoise.Mean() == 0.0)
{
imuConfiguration.m_linearAccelerationVariance = AZ::Vector3(
static_cast<float>(linAccXNoise.StdDev() * linAccXNoise.StdDev()),
static_cast<float>(linAccYNoise.StdDev() * linAccYNoise.StdDev()),
static_cast<float>(linAccZNoise.StdDev() * linAccZNoise.StdDev()));
}
}

SensorConfiguration sensorConfiguration;
sensorConfiguration.m_frequency = sdfSensor.UpdateRate();
const AZStd::string messageType = "sensor_msgs::msg::Imu";
Utils::AddTopicConfiguration(sensorConfiguration, "imu", messageType, messageType);

// Create required components
Utils::CreateComponent<ROS2FrameComponent>(entity);
Utils::CreateComponent<PhysX::EditorStaticRigidBodyComponent>(entity);

// Create Imu component
if (Utils::CreateComponent<ROS2ImuSensorComponent>(entity, sensorConfiguration, imuConfiguration))
{
return AZ::Success();
}
else
{
return AZ::Failure(AZStd::string("Failed to create ROS2 Imu Sensor component"));
}
};

return importerHook;
}
} // namespace ROS2::SDFormat
Loading

0 comments on commit 603f29e

Please sign in to comment.