diff --git a/lib/sdf/element.rb b/lib/sdf/element.rb
index 7d70baa..efb1bba 100644
--- a/lib/sdf/element.rb
+++ b/lib/sdf/element.rb
@@ -93,7 +93,8 @@ def self.wrap(xml, parent = nil)
"model" => Model,
"sdf" => Root,
"link" => Link,
- "joint" => Joint]
+ "joint" => Joint,
+ "plugin" => Plugin]
if (klass = xml_to_class[xml.name])
return klass.new(xml, parent)
diff --git a/lib/sdf/model.rb b/lib/sdf/model.rb
index d1b0aee..d123b8e 100644
--- a/lib/sdf/model.rb
+++ b/lib/sdf/model.rb
@@ -87,6 +87,10 @@ def initialize(xml = REXML::Element.new("model"), parent = nil)
# The link that is used to represent the pose of the model itself
attr_accessor :canonical_link
+ def find_model_by_name(name)
+ @models[name]
+ end
+
# (see Element#find_by_name)
def find_by_name(name)
@models[name] || @links[name] || @joints[name]
diff --git a/lib/sdf/sensor.rb b/lib/sdf/sensor.rb
index 034117b..139e808 100644
--- a/lib/sdf/sensor.rb
+++ b/lib/sdf/sensor.rb
@@ -18,6 +18,16 @@ def initialize(xml, parent = nil)
@sensor_info = xml.elements[type]
end
+ def each_direct_plugin(&block)
+ each_plugin(&block)
+ end
+
+ def each_plugin
+ xml.elements.each do |plugin_xml|
+ yield(Plugin.new(plugin_xml, self))
+ end
+ end
+
# The sensor type
def type
xml.attributes["type"]
diff --git a/lib/sdf/world.rb b/lib/sdf/world.rb
index c5ea331..5e8b55e 100644
--- a/lib/sdf/world.rb
+++ b/lib/sdf/world.rb
@@ -16,10 +16,19 @@ def self.empty(name: "world", version: nil)
xml_tag_name "world"
+ def find_model_by_name(name)
+ each_model.find { |m| m.name == name }
+ end
+
+ # @deprecated use {#each_direct_model} instead
+ def each_model(&block)
+ each_direct_model(&block)
+ end
+
# Enumerates the models from this world
#
# @yieldparam [Model] model
- def each_model
+ def each_direct_model
return enum_for(__method__) unless block_given?
xml.elements.each do |element|
@@ -38,8 +47,15 @@ def spherical_coordinates
)
end
+ # @deprecated use {#each_direct_plugin} instead
+ def each_plugin(&block)
+ each_direct_plugin(&block)
+ end
+
# Enumerate the world-level plugins
- def each_plugin
+ #
+ # @yieldparam [Plugin]
+ def each_direct_plugin
return enum_for(__method__) unless block_given?
xml.elements.each do |element|
diff --git a/test/test_model.rb b/test/test_model.rb
index 473c343..83b560f 100644
--- a/test/test_model.rb
+++ b/test/test_model.rb
@@ -61,6 +61,32 @@ def models_dir
end
end
+ describe "#find_model_by_name" do
+ before do
+ xml_s = <<~XML
+
+
+
+
+ XML
+ @xml = REXML::Document.new(xml_s).root
+ @root = SDF::Model.new(@xml)
+ end
+ it "returns nil if the model has no " do
+ assert_nil @root.find_model_by_name("does_not_exist")
+ end
+ it "returns a direct model" do
+ model = @root.find_model_by_name("1")
+ assert_kind_of SDF::Model, model
+ assert_equal @xml.elements["model[@name=\"1\"]"], model.xml
+ end
+ it "returns models recursively" do
+ model = @root.find_model_by_name("0::a")
+ assert_kind_of SDF::Model, model
+ assert_equal @xml.elements["//model[@name=\"a\"]"], model.xml
+ end
+ end
+
describe "#each_model" do
it "does not yield anything if the model has no models" do
root = SDF::Model.new(REXML::Document.new("").root)
diff --git a/test/test_sensor.rb b/test/test_sensor.rb
index 13b1e18..d22ff02 100644
--- a/test/test_sensor.rb
+++ b/test/test_sensor.rb
@@ -28,5 +28,23 @@ module SDF
assert_nil sensor.update_period
end
end
+
+ describe "#each_plugin" do
+ it "does not yield anything if the sensor has no plugin" do
+ root = SDF::Sensor.new(REXML::Document.new("").root)
+ assert root.enum_for(:each_plugin).to_a.empty?
+ end
+ it "yields the plugins otherwise" do
+ root = SDF::Sensor.new(REXML::Document.new("").root)
+
+ plugin = root.enum_for(:each_plugin).to_a
+ assert_equal 2, plugin.size
+ plugin.each do |l|
+ assert_kind_of SDF::Plugin, l
+ assert_same root, l.parent
+ assert_equal root.xml.elements.to_a("plugin[@name=\"#{l.name}\"]"), [l.xml]
+ end
+ end
+ end
end
end
diff --git a/test/test_world.rb b/test/test_world.rb
index 7327cfb..464ce0a 100644
--- a/test/test_world.rb
+++ b/test/test_world.rb
@@ -20,6 +20,17 @@ module SDF
end
end
end
+ describe "#find_model_by_name" do
+ it "returns nil if the model does not exist" do
+ root = SDF::World.new(REXML::Document.new("").root)
+ assert_nil root.find_model_by_name("does_not_exist")
+ end
+ it "yields the models otherwise" do
+ xml = REXML::Document.new("").root
+ world = SDF::World.new(xml)
+ assert_equal xml.elements["model[@name=\"1\"]"], world.find_model_by_name("1").xml
+ end
+ end
describe ".empty" do
it "creates a world with no models" do
world = World.empty(name: "test")