From 3e6cd48fd7858dc9af1b5b6814b51cbfe8368e66 Mon Sep 17 00:00:00 2001 From: Franco Cipollone Date: Tue, 23 Apr 2024 16:52:58 +0000 Subject: [PATCH] Adds ResourceManager and offer malidrive resources. Signed-off-by: Franco Cipollone --- maliput-sdk/BUILD.bazel | 3 + maliput-sdk/build.rs | 10 ++ maliput-sdk/src/lib.rs | 8 ++ .../examples/maliput_malidrive_resources.rs | 62 ++++++++++ maliput/src/lib.rs | 115 ++++++++++++++++++ 5 files changed, 198 insertions(+) create mode 100644 maliput/examples/maliput_malidrive_resources.rs diff --git a/maliput-sdk/BUILD.bazel b/maliput-sdk/BUILD.bazel index 2940a27..b2065de 100644 --- a/maliput-sdk/BUILD.bazel +++ b/maliput-sdk/BUILD.bazel @@ -22,6 +22,9 @@ cc_binary( "@maliput//:utility", "@maliput_malidrive//:maliput_plugins/libmaliput_malidrive_road_network.so", ], + data = [ + "@maliput_malidrive//resources:all" + ], linkshared = True, linkstatic = False ) diff --git a/maliput-sdk/build.rs b/maliput-sdk/build.rs index faff576..2e5ae81 100644 --- a/maliput-sdk/build.rs +++ b/maliput-sdk/build.rs @@ -88,6 +88,12 @@ fn main() -> Result<(), Box> { // ************* maliput_malidrive header files ************* // // TODO(francocipollone): For consistency we should also add include paths for maliput_malidrive. + // ************* maliput_malidrive resource files ************* // + let maliput_malidrive_resource_path = bazel_bin_dir + .join("libmaliput_sdk.so.runfiles") + .join(String::from("maliput_malidrive~") + maliput_malidrive_version) + .join("resources"); + // ************* crate output env vars ************* // // Environment variable to pass down to this crate: @@ -100,6 +106,10 @@ fn main() -> Result<(), Box> { "cargo:rustc-env=MALIPUT_MALIDRIVE_PLUGIN_PATH={}", maliput_malidrive_bin_path.join("maliput_plugins").display() ); + println!( + "cargo:rustc-env=MALIPUT_MALIDRIVE_RESOURCE_PATH={}", + maliput_malidrive_resource_path.display() + ); // Environment variable to pass down to dependent crates: // See: https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key diff --git a/maliput-sdk/src/lib.rs b/maliput-sdk/src/lib.rs index be52671..611c31a 100644 --- a/maliput-sdk/src/lib.rs +++ b/maliput-sdk/src/lib.rs @@ -41,6 +41,14 @@ pub fn sdk_libraries() -> Vec<(String, PathBuf)> { ] } +/// Returns a map of resources here vendored and the directories to search for the resources. +pub fn sdk_resources() -> Vec<(String, PathBuf)> { + vec![( + "maliput_malidrive".to_string(), + PathBuf::from(env!("MALIPUT_MALIDRIVE_RESOURCE_PATH")), + )] +} + /// Returns the path to the maliput_malidrive plugin. pub fn get_maliput_malidrive_plugin_path() -> PathBuf { PathBuf::from(env!("MALIPUT_MALIDRIVE_PLUGIN_PATH")) diff --git a/maliput/examples/maliput_malidrive_resources.rs b/maliput/examples/maliput_malidrive_resources.rs new file mode 100644 index 0000000..2383810 --- /dev/null +++ b/maliput/examples/maliput_malidrive_resources.rs @@ -0,0 +1,62 @@ +// BSD 3-Clause License +// +// Copyright (c) 2024, Woven by Toyota. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +fn main() { + use maliput::api::RoadNetwork; + use std::collections::HashMap; + + // The ResourceManager is a convenient method for getting the path to the resources of the backends. + // In this case, we are getting the path to the Town01.xodr file from the maliput_malidrive backend. + // And then using it to create a RoadNetwork. + let rm = maliput::ResourceManager::new(); + let town_xodr_path = rm + .get_resource_path_by_name("maliput_malidrive", "Town01.xodr") + .unwrap(); + + let road_network_properties = HashMap::from([ + ("road_geometry_id", "my_rg_from_rust"), + ("opendrive_file", town_xodr_path.to_str().unwrap()), + ]); + + let road_network = RoadNetwork::new("maliput_malidrive", &road_network_properties); + let road_geometry = road_network.road_geometry(); + + // Exercise the RoadGeometry API. + println!("linear_tolerance: {}", road_geometry.linear_tolerance()); + println!("angular_tolerance: {}", road_geometry.angular_tolerance()); + println!("num_junctions: {}", road_geometry.num_junctions()); + + let lanes = road_geometry.get_lanes(); + println!("num_lanes: {}", lanes.len()); + println!("lanes: "); + for lane in lanes { + println!("\tlane id: {}", lane.id()); + } +} diff --git a/maliput/src/lib.rs b/maliput/src/lib.rs index e896cda..f613d89 100644 --- a/maliput/src/lib.rs +++ b/maliput/src/lib.rs @@ -29,3 +29,118 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. pub mod api; pub mod math; + +/// ### ResourceManager +/// +/// Convenient method for getting the path to the resources of the backends. +/// +/// ### Backends +/// - maliput_malidrive: Resources from maliput_malidrive are brought by maliput-sdk package. +/// All the maliput_malidrive resources are stored in the same directory: +/// (See https://github.com/maliput/maliput_malidrive/tree/main/resources) +/// ### Example +/// +/// How to get all the resources from the maliput_malidrive backend: +/// +/// ```rust, no_run +/// let resource_manager = maliput::ResourceManager::new(); +/// let all_resources_in_malidrive = resource_manager.get_all_resources_by_backend("maliput_malidrive"); +/// ``` +/// +/// How to get the path to the TShapeRoad.xodr file from the maliput_malidrive backend: +/// ```rust, no_run +/// let resource_manager = maliput::ResourceManager::new(); +/// let t_shape_road_xodr_path = resource_manager.get_resource_path_by_name("maliput_malidrive", "TShapeRoad.xodr"); +/// assert!(t_shape_road_xodr_path.is_some()); +/// assert!(t_shape_road_xodr_path.unwrap().exists()); +/// ``` +pub struct ResourceManager { + resource_paths: std::collections::HashMap>, +} + +impl Default for ResourceManager { + fn default() -> Self { + Self::new() + } +} + +impl ResourceManager { + /// Creates a new ResourceManager. + pub fn new() -> ResourceManager { + let mut resource_paths = std::collections::HashMap::new(); + maliput_sdk::sdk_resources() + .iter() + .for_each(|(backend_name, resource_path)| { + // All the files in the path are added to the resource manager + let files = std::fs::read_dir(resource_path).unwrap(); + let mut paths = vec![]; + files.filter(|file| file.is_ok()).for_each(|file| { + paths.push(file.unwrap().path()); + }); + resource_paths.insert(backend_name.clone(), paths); + }); + ResourceManager { resource_paths } + } + + /// Obtains the path to a resource by its name. + /// ### Arguments + /// + /// * `backend_name` - The name of the backend. + /// * `resource_name` - The name of the resource. + /// + /// ### Returns + /// The path to the resource if it exists, otherwise None. + pub fn get_resource_path_by_name(&self, backend_name: &str, resource_name: &str) -> Option { + let paths = self.resource_paths.get(backend_name).unwrap(); + for path in paths { + if path.to_str().unwrap().contains(resource_name) { + return Some(path.clone()); + } + } + None + } + + /// Obtains all the resources from a backend. + /// ### Arguments + /// + /// * `backend_name` - The name of the backend. + /// + /// ### Returns + /// A vector with all the resources from the backend if it exists, otherwise None. + pub fn get_all_resources_by_backend(&self, backend_name: &str) -> Option<&Vec> { + self.resource_paths.get(backend_name) + } + + /// Get the underlying collection that stores all the resources for each backend. + pub fn get_all_resources(&self) -> &std::collections::HashMap> { + &self.resource_paths + } +} + +// test + +mod tests { + + #[test] + fn test_maliput_malidrive_resources() { + let resource_manager = crate::ResourceManager::new(); + + let t_shape_road_xodr_path = resource_manager.get_resource_path_by_name("maliput_malidrive", "TShapeRoad.xodr"); + assert!(t_shape_road_xodr_path.is_some()); + assert!(t_shape_road_xodr_path.unwrap().exists()); + + let wrong_file_path = resource_manager.get_resource_path_by_name("maliput_malidrive", "wrong_file"); + assert!(wrong_file_path.is_none()); + + let all_resources_in_malidrive = resource_manager.get_all_resources_by_backend("maliput_malidrive"); + assert!(all_resources_in_malidrive.is_some()); + assert!(all_resources_in_malidrive.unwrap().len() > 10); + + let all_resources_in_wrong_backend = resource_manager.get_all_resources_by_backend("wrong_backend"); + assert!(all_resources_in_wrong_backend.is_none()); + + let all_resources = resource_manager.get_all_resources(); + // There is only one backend supported at the moment. + assert_eq!(all_resources.len(), 1); + } +}