[PATCH] Added support of Dynamic Propertys to Orogen

Matthias Goldhoorn matthias.goldhoorn at dfki.de
Mon Apr 15 14:46:14 CEST 2013


on spec (.orogen side):

property("name","type").
	dynamic

Added support of dynamic propertys to orogen

on spec (.orogen side):

property("name","type").
	dynamic

internal the propertys are handled by operations.
Orocos.rb searches automatically for this operation if an dynamic property should be written

On the cpp implementation orogen created an

setNAME(type value){} function that should be implemented.internal the propertys are handled by operations.
Orocos.rb searches automaticalty for this operation if an dynamic property should be written

On the cpp implementation orogen created an

setNAME(type value){} function that should be implemented.
---
 lib/orogen/gen/tasks.rb                 |   30 ++++++++++++++++++------------
 lib/orogen/spec/configuration_object.rb |   23 ++++++++++++++++++++++-
 lib/orogen/spec/operation.rb            |    9 ++++++++-
 lib/orogen/spec/task_context.rb         |    2 +-
 lib/orogen/templates/tasks/Task.cpp     |    2 +-
 lib/orogen/templates/tasks/Task.hpp     |    2 +-
 6 files changed, 51 insertions(+), 17 deletions(-)

diff --git a/lib/orogen/gen/tasks.rb b/lib/orogen/gen/tasks.rb
index df23dd1..3bb9cb2 100644
--- a/lib/orogen/gen/tasks.rb
+++ b/lib/orogen/gen/tasks.rb
@@ -24,6 +24,7 @@ def register_for_generation
                     "RTT::Property< #{type.cxx_name} >").
                     initializer("_#{name}(\"#{name}\", \"#{doc}\")").
                     constructor(constructor.join("\n"))
+
             end
         end
 
@@ -157,6 +158,7 @@ def argument_signature(with_names = true)
 	    end
 
             attr_accessor :body
+            attr_accessor :base_body
 
 	    # call-seq:
 	    #	method_name new_name -> self
@@ -180,7 +182,7 @@ def register_for_generation
                     constructor += "\n" + arguments.map { |n, _, d| "    .arg(\"#{n}\", \"#{d}\")" }.join("\n")
                 end
 
-                if hidden? && !self.body
+                if hidden? && !self.base_body
                     raise InternalError, "a hidden operation must have a body"
                 end
 
@@ -192,17 +194,19 @@ def register_for_generation
                     else ""
                     end
 
-                add = if hidden? then "add_base_method"
-                      else "add_user_method"
-                      end
-
                 task.add_base_member("operation", "_#{name}", "RTT::Operation< #{signature(false)} >").
                     initializer("_#{name}(\"#{name}\", &#{task.basename}Base::#{method_name}, this, #{thread_flag})").
                     constructor("#{constructor};")
 
-                m = task.send(add, return_type[1], method_name, argument_signature).
-                    doc("Handler for the #{method_name} operation").
-                    body(body)
+                m = nil
+                if hidden?
+                    m = task.add_base_method(return_type[1], method_name, argument_signature, base_body)
+                else
+                    m = task.add_user_method(return_type[1], method_name, argument_signature, base_body)
+                    m.body(body)
+                end
+                m.doc(doc!="" ? doc : "Handler for the #{method_name} operation")
+
             end
         end
 
@@ -781,8 +785,9 @@ def add_method(kind, return_type, name, signature)
             #
             # It returns an instance of GeneratedMethod that can be used to
             # setup the method further
-            def add_base_method(return_type, name, signature = "")
+            def add_base_method(return_type, name, signature = "", body = nil)
                 m = add_method("base_methods", return_type, name, signature)
+                m.body(body) if body
                 m.in_base = true
                 m
             end
@@ -801,12 +806,13 @@ def has_base_method?(name)
             #
             # It returns an instance of GeneratedMethod that can be used to
             # setup the method further
-            def add_user_method(return_type, name, signature = "")
+            def add_user_method(return_type, name, signature = "", base_body = nil)
                 if !has_base_method?(name)
                     # Add a pure virtual method to remind the user that he
                     # should add it to its implementation
-                    add_base_method(return_type, name, signature).
-                        doc "If the compiler issues an error at this point, it is probably that",
+                    m = add_base_method(return_type, name, signature)
+                    m.body(base_body)
+                    m.doc "If the compiler issues an error at this point, it is probably that",
                             "you forgot to add the corresponding method to the #{self.name} class."
                 end
                 add_method("user_methods", return_type, name, signature)
diff --git a/lib/orogen/spec/configuration_object.rb b/lib/orogen/spec/configuration_object.rb
index 0f2efd8..cea6d72 100644
--- a/lib/orogen/spec/configuration_object.rb
+++ b/lib/orogen/spec/configuration_object.rb
@@ -14,6 +14,11 @@ class ConfigurationObject
 	    # component's type registry
 	    attr_reader :type
 
+            #If this property coudl be set Dynamic this returns true
+            def dynamic?
+                @dynamic
+            end
+
             # The name of the type this property is using, for consistency with
             # the +type+ attribute
             def type_name; type.name end
@@ -42,10 +47,26 @@ def initialize(task, name, type, default_value)
 
                 type = task.project.find_interface_type(type)
                 Orocos.validate_toplevel_type(type)
-
+                @dynamic = false
 		@task, @name, @type, @default_value = task, name, type, default_value
 	    end
 
+            def dynamic
+                if task.find_operation("set#{name.capitalize}")
+                    raise ArgumentError, "an operation of name set#{name.capitalize} already Exists, this means you cannot register and dynamic peoperty with the name #{name}"
+                end
+                op = task.operation("set#{name.capitalize}").
+                    returns("bool").
+                    argument("value", type_name).
+                    doc("Dynamic Property setter of #{name}")
+
+
+                op.base_body = "\t_#{name}.set(value); //Updates the classical value of this Property"
+                op.body = "\t#{task.name}Base::set#{name.capitalize}(value);//Call the base function, DO-NOT Remove\n\n\treturn true;"
+                @dynamic = true
+                self
+            end
+
             def pretty_print(pp)
                 default = if value = self.default_value
                               ", default: #{value}"
diff --git a/lib/orogen/spec/operation.rb b/lib/orogen/spec/operation.rb
index 9cbc23c..02bb698 100644
--- a/lib/orogen/spec/operation.rb
+++ b/lib/orogen/spec/operation.rb
@@ -42,6 +42,12 @@ class Operation
             # See also #runs_in_caller_thread and #runs_in_callee_thread
             attr_reader :in_caller_thread
 
+            #Accessor for the body implementation of the user-Task
+            attr_accessor :body
+            #Accessor for the TaskBase body implementation
+            attr_accessor :base_body
+
+
 	    def initialize(task, name)
                 name = name.to_s
 		if name !~ /^\w+$/
@@ -54,7 +60,8 @@ def initialize(task, name)
 		@arguments = []
                 @in_caller_thread = false
                 @doc = ""
-
+                @base_body = nil 
+                @body = nil
                 super if defined? super
 	    end
 
diff --git a/lib/orogen/spec/task_context.rb b/lib/orogen/spec/task_context.rb
index fa69cf9..0e8dc08 100644
--- a/lib/orogen/spec/task_context.rb
+++ b/lib/orogen/spec/task_context.rb
@@ -724,7 +724,7 @@ def operation(name)
             def hidden_operation(name, body)
                 op = operation(name)
                 op.hidden = true
-                op.body = body
+                op.base_body = body
                 op
             end
 
diff --git a/lib/orogen/templates/tasks/Task.cpp b/lib/orogen/templates/tasks/Task.cpp
index 2f57ba4..c494057 100644
--- a/lib/orogen/templates/tasks/Task.cpp
+++ b/lib/orogen/templates/tasks/Task.cpp
@@ -20,7 +20,7 @@ using namespace <%= task.component.name %>;
 
 <%= task.self_user_methods.sort_by(&:name).
     map { |m| m.with_indent(0, :definition) }.
-    compact.join("\n") %>
+    compact.join("\n\n") %>
 
 /// The following lines are template definitions for the various state machine
 // hooks defined by Orocos::RTT. See <%= task.basename %>.hpp for more detailed
diff --git a/lib/orogen/templates/tasks/Task.hpp b/lib/orogen/templates/tasks/Task.hpp
index fe4c1c1..6d6c735 100644
--- a/lib/orogen/templates/tasks/Task.hpp
+++ b/lib/orogen/templates/tasks/Task.hpp
@@ -28,7 +28,7 @@ namespace <%= component.name %> {
 
 <%= task.self_user_methods.sort_by(&:name).
     map { |m| m.with_indent(8, :declaration) }.
-    compact.join("\n") %>
+    compact.join("\n\n") %>
 
     public:
         /** TaskContext constructor for <%= task.basename %>
-- 
1.7.10.4


--------------050802090700040005080300
Content-Type: text/x-patch;
 name="0001-Added-handling-for-Dynamic-Properties.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="0001-Added-handling-for-Dynamic-Properties.patch"



More information about the Rock-dev mailing list