From c315f6570605b846cf5f4c628fb58c979537a750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pe=C5=82ka?= Date: Fri, 24 May 2024 16:16:42 +0200 Subject: [PATCH] Added support for loading CSV with WGS84 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Pełka --- Gems/RobotecSplineTools/Code/CMakeLists.txt | 1 + .../Tools/SplineToolsEditorComponent.cpp | 273 ++++++++++-------- .../Source/Tools/SplineToolsEditorComponent.h | 2 +- Gems/RobotecSplineTools/gem.json | 2 +- 4 files changed, 159 insertions(+), 119 deletions(-) diff --git a/Gems/RobotecSplineTools/Code/CMakeLists.txt b/Gems/RobotecSplineTools/Code/CMakeLists.txt index f52b278..aa54f12 100644 --- a/Gems/RobotecSplineTools/Code/CMakeLists.txt +++ b/Gems/RobotecSplineTools/Code/CMakeLists.txt @@ -126,6 +126,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) AZ::AzToolsFramework $ Gem::AtomLyIntegration_CommonFeatures.Static + Gem::ROS2.Editor.Static ) ly_add_target( diff --git a/Gems/RobotecSplineTools/Code/Source/Tools/SplineToolsEditorComponent.cpp b/Gems/RobotecSplineTools/Code/Source/Tools/SplineToolsEditorComponent.cpp index fdf4253..0189d4d 100644 --- a/Gems/RobotecSplineTools/Code/Source/Tools/SplineToolsEditorComponent.cpp +++ b/Gems/RobotecSplineTools/Code/Source/Tools/SplineToolsEditorComponent.cpp @@ -8,63 +8,58 @@ #include #include #include +#include +#include +#include +#include +#include -namespace SplineTools -{ +namespace SplineTools { - void SplineToolsEditorComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) - { + void SplineToolsEditorComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType &required) { required.push_back(AZ_CRC_CE("TransformService")); required.push_back(AZ_CRC_CE("SplineService")); } - void SplineToolsEditorComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { + void SplineToolsEditorComponent::Reflect(AZ::ReflectContext *context) { + AZ::SerializeContext *serializeContext = azrtti_cast(context); + if (serializeContext) { serializeContext->Class() - ->Version(2) - ->Field("CsvAssetId", &SplineToolsEditorComponent::m_csvAssetId) - ->Field("IsLocalCoordinates", &SplineToolsEditorComponent::m_isLocalCoordinates); - - AZ::EditContext* editContext = serializeContext->GetEditContext(); - if (editContext) - { - editContext->Class("SplineToolsEditorComponent", "SplineToolsEditorComponent") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "SplineToolsEditorComponent") - ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) - ->Attribute(AZ::Edit::Attributes::Category, "RobotecTools") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement( - AZ::Edit::UIHandlers::CheckBox, - &SplineToolsEditorComponent::m_isLocalCoordinates, - "Local coordinates", - "Local coordinates") - ->DataElement(AZ::Edit::UIHandlers::Default, &SplineToolsEditorComponent::m_csvAssetId, "CSV Asset", "CSV asset") - ->Attribute(AZ::Edit::Attributes::SourceAssetFilterPattern, "*.csv") - ->UIElement(AZ::Edit::UIHandlers::Button, "Reload spline", "Reload spline") - ->Attribute(AZ::Edit::Attributes::ButtonText, "Load") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &SplineToolsEditorComponent::ReloadCSVAsset) - ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") - ->UIElement(AZ::Edit::UIHandlers::Button, "Save spline", "Save spline") - ->Attribute(AZ::Edit::Attributes::ButtonText, "Save") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &SplineToolsEditorComponent::SaveCsvAsset) - ->Attribute(AZ::Edit::Attributes::NameLabelOverride, ""); + ->Version(2) + ->Field("IsLocalCoordinates", &SplineToolsEditorComponent::m_isLocalCoordinates); + + AZ::EditContext *editContext = serializeContext->GetEditContext(); + if (editContext) { + editContext->Class("SplineToolsEditorComponent", + "SplineToolsEditorComponent") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "SplineToolsEditorComponent") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) + ->Attribute(AZ::Edit::Attributes::Category, "RobotecTools") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement( + AZ::Edit::UIHandlers::CheckBox, + &SplineToolsEditorComponent::m_isLocalCoordinates, + "Local coordinates", + "Local coordinates") + ->UIElement(AZ::Edit::UIHandlers::Button, "Load spline", "Load spline") + ->Attribute(AZ::Edit::Attributes::ButtonText, "Load") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &SplineToolsEditorComponent::ReloadCSVAsset) + ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") + ->UIElement(AZ::Edit::UIHandlers::Button, "Save spline", "Save spline") + ->Attribute(AZ::Edit::Attributes::ButtonText, "Save") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &SplineToolsEditorComponent::SaveCsvAsset) + ->Attribute(AZ::Edit::Attributes::NameLabelOverride, ""); } } } - void SplineToolsEditorComponent::Activate() - { + void SplineToolsEditorComponent::Activate() { } - void SplineToolsEditorComponent::Deactivate() - { + void SplineToolsEditorComponent::Deactivate() { } - void SplineToolsEditorComponent::BuildGameEntity([[maybe_unused]] AZ::Entity* gameEntity) - { + void SplineToolsEditorComponent::BuildGameEntity([[maybe_unused]] AZ::Entity *gameEntity) { ReloadCSVAsset(); } @@ -74,20 +69,24 @@ namespace SplineTools LmbrCentral::SplineComponentRequestBus::EventResult( splinePtr, GetEntityId(), &LmbrCentral::SplineComponentRequestBus::Events::GetSpline); auto vertices = splinePtr->GetVertices(); - using AssetSysReqBus = AzToolsFramework::AssetSystemRequestBus; - AZ::Data::AssetInfo sourceAssetInfo; - bool ok{ false }; - AZStd::string watchFolder; - AZStd::vector productsAssetInfo; - - AssetSysReqBus::BroadcastResult( - ok, &AssetSysReqBus::Events::GetSourceInfoBySourceUUID, m_csvAssetId.m_guid, sourceAssetInfo, watchFolder); - if (!ok) - { - AZ_Error("SplineToolsEditorComponent", false, "Failed to get source info for referenced CSV asset. Saving aborted"); + + + QString fileName = QFileDialog::getSaveFileName( + AzToolsFramework::GetActiveWindow(), + "Open CSV File", + "", + "CSV Files (*.csv)" + ); + + if (fileName.isEmpty()) { + QMessageBox::warning( + AzToolsFramework::GetActiveWindow(), "Error", + "Please specify file", QMessageBox::Ok); return; } - const AZ::IO::Path sourcePath = AZ::IO::Path(watchFolder) / AZ::IO::Path(sourceAssetInfo.m_relativePath); + + + const AZ::IO::Path sourcePath = AZ::IO::Path(fileName.toUtf8().constData()); if (!m_isLocalCoordinates) { @@ -95,91 +94,104 @@ namespace SplineTools AZ::TransformBus::EventResult(worldTm, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); AZStd::transform( - vertices.begin(), - vertices.end(), - vertices.begin(), - [worldTm](auto point) - { - return worldTm.TransformPoint(point); - }); + vertices.begin(), + vertices.end(), + vertices.begin(), + [worldTm](auto point) { + return worldTm.TransformPoint(point); + }); } - AZ_Printf("SplineToolsEditorComponent", "Save CSV asset to %s", sourceAssetInfo.m_relativePath.c_str()); + AZ_Printf("SplineToolsEditorComponent", "Save CSV asset to %s", sourcePath.c_str()); SavePointsToCsv(sourcePath.c_str(), vertices); } - void SplineToolsEditorComponent::ReloadCSVAsset() - { - using AssetSysReqBus = AzToolsFramework::AssetSystemRequestBus; - AZ::Data::AssetInfo sourceAssetInfo; - bool ok{ false }; - AZStd::string watchFolder; - AZStd::vector productsAssetInfo; + void SplineToolsEditorComponent::ReloadCSVAsset() { - AssetSysReqBus::BroadcastResult( - ok, &AssetSysReqBus::Events::GetSourceInfoBySourceUUID, m_csvAssetId.m_guid, sourceAssetInfo, watchFolder); - const AZ::IO::Path sourcePath = AZ::IO::Path(watchFolder) / AZ::IO::Path(sourceAssetInfo.m_relativePath); + QString fileName = QFileDialog::getOpenFileName( + AzToolsFramework::GetActiveWindow(), + "Open CSV File", + "", + "CSV Files (*.csv)" + ); + if (fileName.isEmpty()) { + QMessageBox::warning( + AzToolsFramework::GetActiveWindow(), "Error", + "Please specify file", QMessageBox::Ok); + return; + } + AZStd::string sourcePath = AZStd::string(fileName.toUtf8().constData()); AZ_Printf("SplineToolsEditorComponent", "Reload csv asset from %s", sourcePath.c_str()); auto points = GetSplinePointsFromCsv(sourcePath.c_str()); - if (points.empty()) - { + if (points.empty()) { AZ_Error("SplineToolsEditorComponent", false, "No points found in CSV file"); + QMessageBox::warning( + AzToolsFramework::GetActiveWindow(), "Error", + "No points found in CSV file", QMessageBox::Ok); return; } + AZ::Transform worldInvTm(AZ::Transform::Identity()); - if (!m_isLocalCoordinates) - { + if (m_isLocalCoordinates && m_isLatLonAlt) { + AZ_Error("SplineToolsEditorComponent", false, "Cannot use lat, lon, alt coordinates in local coordinates"); + QMessageBox::warning( + AzToolsFramework::GetActiveWindow(), "Error", + "Cannot use lat, lon, alt coordinates in local coordinates", QMessageBox::Ok); + return; + } + + if (!m_isLocalCoordinates) { AZ::TransformBus::EventResult(worldInvTm, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); worldInvTm.Invert(); } - LmbrCentral::SplineComponentRequestBus::Event(GetEntityId(), &LmbrCentral::SplineComponentRequestBus::Events::ClearVertices); + + LmbrCentral::SplineComponentRequestBus::Event(GetEntityId(), + &LmbrCentral::SplineComponentRequestBus::Events::ClearVertices); AZ_Printf("SplineToolsEditorComponent", "CSV file has %d points", points.size()); AZStd::transform( - points.begin(), - points.end(), - points.begin(), - [&worldInvTm](AZ::Vector3& p) - { - return worldInvTm.TransformPoint(p); - }); - - LmbrCentral::SplineComponentRequestBus::Event(GetEntityId(), &LmbrCentral::SplineComponentRequestBus::Events::SetVertices, points); + points.begin(), + points.end(), + points.begin(), + [&worldInvTm](AZ::Vector3 &p) { + return worldInvTm.TransformPoint(p); + }); + + LmbrCentral::SplineComponentRequestBus::Event(GetEntityId(), + &LmbrCentral::SplineComponentRequestBus::Events::SetVertices, + points); + + } - void SplineToolsEditorComponent::SavePointsToCsv(const AZStd::string& csvFilePath, const AZStd::vector& vertices) - { - try - { + void SplineToolsEditorComponent::SavePointsToCsv(const AZStd::string &csvFilePath, + const AZStd::vector &vertices) { + try { auto fileStream = std::ofstream(csvFilePath.c_str()); - if (!fileStream.is_open()) - { - AZ_Error("SplineToolsEditorComponent", false, "Could not open file for writing - (%s).", csvFilePath.c_str()); + if (!fileStream.is_open()) { + AZ_Error("SplineToolsEditorComponent", false, "Could not open file for writing - (%s).", + csvFilePath.c_str()); return; } auto writer = csv::make_csv_writer(fileStream); writer << std::make_tuple("x", "y", "z"); - for (auto& vertex : vertices) - { + for (auto &vertex: vertices) { writer << std::make_tuple(vertex.GetX(), vertex.GetY(), vertex.GetZ()); } writer.flush(); AZ_Info("SplineToolsEditorComponent", "Saved %zu points to CSV file", vertices.size()); - } catch (std::runtime_error& exception) - { + } catch (std::runtime_error &exception) { AZ_Error("SplineToolsEditorComponent", false, "Error saving CSV file: %s", exception.what()); } } - AZStd::vector SplineToolsEditorComponent::GetSplinePointsFromCsv(const AZStd::string& csvFilePath) - { - try - { + AZStd::vector SplineToolsEditorComponent::GetSplinePointsFromCsv(const AZStd::string &csvFilePath) { + try { AZStd::vector ret; csv::CSVReader reader(csvFilePath.c_str()); @@ -189,30 +201,57 @@ namespace SplineTools const int index_Y = reader.index_of("y"); const int index_Z = reader.index_of("z"); - const bool isCoordinateCorrect = !(index_X < 0 || index_Y < 0); - if (!isCoordinateCorrect) - { - AZ_Error("SplineToolsEditorComponent", false, "CSV file must have columns named x, y"); + const int index_Lat = reader.index_of("lat"); + const int index_Lon = reader.index_of("lon"); + const int index_Alt = reader.index_of("alt"); + + const bool isCoordinateXY = !(index_X < 0 || index_Y < 0); + const bool isCoordinateLatLon = !(index_Lat < 0 || index_Lon < 0 || index_Alt < 0); + const bool isCoordinateCorrect = isCoordinateXY || isCoordinateLatLon; + + if (!isCoordinateCorrect) { + AZ_Error("SplineToolsEditorComponent", false, "CSV file must have columns named x, y or lat, lon"); + QMessageBox::warning( + AzToolsFramework::GetActiveWindow(), "Error", + "CSV file must have columns named x, y or lat, lon", QMessageBox::Ok); return {}; } - for (csv::CSVRow& row : reader) - { - AZ::Vector3 point = AZ::Vector3(row[index_X].get(), row[index_Y].get(), 0); + if (isCoordinateXY) { + m_isLatLonAlt = false; + for (csv::CSVRow &row: reader) { + AZ::Vector3 point = AZ::Vector3(row[index_X].get(), row[index_Y].get(), 0); - // handle Z column - if (index_Z > 0) - { - point.SetZ(row[index_Z].get()); - } + // handle Z column + if (index_Z > 0) { + point.SetZ(row[index_Z].get()); + } - ret.emplace_back(AZStd::move(point)); + ret.emplace_back(AZStd::move(point)); + } + } else if (isCoordinateLatLon) { + m_isLatLonAlt = true; + for (csv::CSVRow &row: reader) { + + ROS2::WGS::WGS84Coordinate coordinate; + coordinate.m_latitude = row[index_Lat].get(); + coordinate.m_longitude = row[index_Lon].get(); + coordinate.m_altitude = row[index_Alt].get(); + AZ::Vector3 coordinateInLevel = AZ::Vector3(-1); + ROS2::GeoreferenceRequestsBus::BroadcastResult( + coordinateInLevel, &ROS2::GeoreferenceRequests::ConvertFromWSG84ToLevel, coordinate); + + ret.emplace_back(AZStd::move(coordinateInLevel)); + } } + return ret; - } catch (std::runtime_error& exception) - { - AZ_Error("SplineToolsEditorComponent", false, "Error parsing CSV file: %s", exception.what()); + } catch (std::runtime_error &exception) { + AZStd::string error = AZStd::string::format("Error parsing CSV file: %s", exception.what()); + AZ_Error("SplineToolsEditorComponent", false, error.c_str()); + QMessageBox::warning( + AzToolsFramework::GetActiveWindow(), "Error", error.c_str(), QMessageBox::Ok); } return {}; } diff --git a/Gems/RobotecSplineTools/Code/Source/Tools/SplineToolsEditorComponent.h b/Gems/RobotecSplineTools/Code/Source/Tools/SplineToolsEditorComponent.h index b08e9aa..35fecd0 100644 --- a/Gems/RobotecSplineTools/Code/Source/Tools/SplineToolsEditorComponent.h +++ b/Gems/RobotecSplineTools/Code/Source/Tools/SplineToolsEditorComponent.h @@ -38,8 +38,8 @@ namespace SplineTools void BuildGameEntity(AZ::Entity* gameEntity) override; private: - AZ::Data::AssetId m_csvAssetId; //!< Asset ID of the CSV bool m_isLocalCoordinates = true; + bool m_isLatLonAlt = false; void ReloadCSVAsset(); AZStd::vector GetSplinePointsFromCsv(const AZStd::string& csvFilePath); diff --git a/Gems/RobotecSplineTools/gem.json b/Gems/RobotecSplineTools/gem.json index e6ff02b..1bda392 100644 --- a/Gems/RobotecSplineTools/gem.json +++ b/Gems/RobotecSplineTools/gem.json @@ -20,7 +20,7 @@ "icon_path": "preview.png", "requirements": "No requirements", "documentation_url": "", - "dependencies": [], + "dependencies": ["ROS2"], "repo_uri": "", "compatible_engines": [], "engine_api_dependencies": [],