@@ -165,7 +165,8 @@ def self.gazebo_models(sdf_version = nil)
165165 #
166166 # @param [String] model_name the target name in the cache
167167 # @param [REXML::Document,REXML::Element,String] xml_doc the XML model representation
168- def self . register_in_memory_model ( model_name , xml_doc , sdf_version : nil )
168+ # @param [Hash,nil] metadata the pre-resolved include metadata
169+ def self . register_in_memory_model ( model_name , xml_doc , sdf_version : nil , metadata : nil )
169170 xml = case xml_doc
170171 when REXML ::Document
171172 xml_doc
@@ -186,19 +187,24 @@ def self.register_in_memory_model(model_name, xml_doc, sdf_version: nil)
186187 end
187188 end
188189
190+ virtual_path = "virtual://#{ model_name } "
191+ metadata ||= { }
192+ metadata [ "includes" ] ||= { }
193+ metadata [ "path" ] ||= virtual_path
194+
189195 @gazebo_models [ sdf_version ] ||= { }
190196 cache = ( @gazebo_models [ sdf_version ] [ model_name ] ||= ModelCacheEntry . new )
191- cache . path = "virtual:// #{ model_name } "
192- cache . xml = xml
193- cache . metadata = { "includes" => { } , "path" => cache . path }
197+ cache . path = metadata [ "path" ]
198+ cache . xml = xml
199+ cache . metadata = metadata
194200
195201 # Also register under nil as a generic fallback
196202 if sdf_version
197203 @gazebo_models [ nil ] ||= { }
198204 cache_nil = ( @gazebo_models [ nil ] [ model_name ] ||= ModelCacheEntry . new )
199- cache_nil . path = "virtual:// #{ model_name } "
200- cache_nil . xml = xml
201- cache_nil . metadata = { "includes" => { } , "path" => cache_nil . path }
205+ cache_nil . path = cache . path
206+ cache_nil . xml = xml
207+ cache_nil . metadata = metadata
202208 end
203209 end
204210
@@ -231,6 +237,14 @@ def self.model_path_from_name(model_name, model_path: @model_path, sdf_version:
231237 cache = ( @gazebo_models [ sdf_version ] [ model_name ] ||= ModelCacheEntry . new )
232238 return cache . path if cache . path
233239
240+ # Fallback to the nil cache for virtual in-memory models
241+ if sdf_version && ( nil_cache = @gazebo_models . dig ( nil , model_name ) ) && nil_cache . path && nil_cache . path . start_with? ( "virtual://" )
242+ cache . path = nil_cache . path
243+ cache . xml = nil_cache . xml if nil_cache . xml
244+ cache . metadata = nil_cache . metadata if nil_cache . metadata
245+ return cache . path
246+ end
247+
234248 model_path . each do |p |
235249 model_dir = File . join ( p , model_name )
236250 if File . file? ( File . join ( model_dir , "model.config" ) )
@@ -508,16 +522,23 @@ def self.sdf_version_of(sdf)
508522 # @raise [NotSDF] if the file is not a SDF file
509523 # @raise [InvalidXML] if the file is not a valid XML file
510524 # @return [REXML::Element]
511- def self . load_sdf ( sdf_file , flatten : true , metadata : false )
512- sdf = load_sdf_raw ( sdf_file )
525+ # Processes an in-memory SDF XML tree, resolving its include tags and relative URIs
526+ #
527+ # @param [REXML::Document] sdf the XML tree
528+ # @param [Boolean] flatten flattens the XML model or not
529+ # @param [Boolean] metadata returns a metadata hash or not
530+ # @param [String,nil] path the file path or virtual path representing the SDF
531+ # @return [REXML::Element, [REXML::Element, Hash]]
532+ def self . resolve_sdf_xml ( sdf , flatten : true , metadata : false , path : nil )
513533 sdf_version = sdf_version_of ( sdf )
534+ base_path = path ? File . dirname ( path ) : nil
514535
515- sdf_metadata = Hash [ "includes" => { } , "path" => sdf_file ]
516- includes = add_include_tags ( sdf . root , sdf_version , File . dirname ( sdf_file ) )
536+ sdf_metadata = Hash [ "includes" => { } , "path" => path ]
537+ includes = add_include_tags ( sdf . root , sdf_version , base_path )
517538 sdf_metadata [ "includes" ] . merge! ( includes ) do |_ , old , new |
518539 old + new
519540 end
520- resolve_relative_uris ( sdf . root , sdf_version , File . dirname ( sdf_file ) )
541+ resolve_relative_uris ( sdf . root , sdf_version , base_path )
521542
522543 sdf = deep_copy_xml ( sdf )
523544 flatten_model_tree ( sdf . root ) if flatten
@@ -527,6 +548,15 @@ def self.load_sdf(sdf_file, flatten: true, metadata: false)
527548 else
528549 sdf
529550 end
551+ end
552+
553+ # Loads a SDF file and returns the XML representation
554+ #
555+ # Unlike {.load_sdf_raw}, this resolves the include tags in the XML representation
556+ def self . load_sdf ( sdf_file , flatten : true , metadata : false )
557+ sdf = load_sdf_raw ( sdf_file )
558+ sdf = deep_copy_xml ( sdf )
559+ resolve_sdf_xml ( sdf , flatten : flatten , metadata : metadata , path : sdf_file )
530560 rescue Exception => e
531561 raise e , "while loading #{ sdf_file } : #{ e . message } " , e . backtrace
532562 end
0 commit comments