module Orocos
The Orocos main class
Constants
- AUTOLOADED_TRANSPORTS
The set of transports that should be automatically loaded. The associated boolean is true if an exception should be raised if the typekit fails to load, and false otherwise
- ConfigError
@deprecated use OroGen::ConfigError instead
- HAS_POCOLOG
- LocalInputPort
- LocalOutputPort
- NEW_DATA
Result value when reading a port which has a new (never read) value
Unlike within RTT, 'NO_DATA' is represented by a false value
@see OLD_DATA
- OLD_DATA
Result value when reading a port whose value has already been read
Unlike within RTT, 'NO_DATA' is represented by a false value
@see NEW_DATA
- OROCOSRB_LIB_DIR
- ProcessClient
- ProcessServer
- RemoteProcess
- RubyDeployment
- RubyProcessServer
- RubyTaskContext
- TRANSPORT_MQ
This is hardcoded here, as we need it to make sure people don't use MQueues on systems where it is not available
The comparison with the actual value from the RTT is done in Orocos::MQueue.available?
- TypekitTypeNotExported
- TypekitTypeNotFound
- VERSION
Attributes
The main configuration manager object
The set of extension names seen so far
Whenever a new extension is encountered, ::task_model_from_name tries to require 'extension_name/runtime', which might no exist. Once it has done that, it registers the extension name in this set to avoid trying loading it again
List of already loaded plugins, as a set of full paths to the shared library
The set of typekits whose shared libraries have been loaded in this process
The name of the orocos logfile for this Ruby process
- RubyTasks::TaskContext
-
the ruby task context that is used to provide a RTT
interface to this Ruby process. Among other things, it manages the data readers and writers
The Pocolog::Logfiles object used by default by ::log_all_configuration. It will automatically be created by Oroocs.configuration_log if ::log_all_configuration is called without an argument
Public Class Methods
Calls a block with the no-blocking-call-in-thread check disabled
This is used in tests, when we know we want to do a remote call, or in places where it is guaranteed that the “remote” is actually co-localized within the same process (e.g. readers, writers, ruby task context)
# File lib/orocos/base.rb, line 326 def self.allow_blocking_calls if block_given? forbidden = Orocos.no_blocking_calls_in_thread if forbidden && (forbidden != Thread.current) raise ThreadError, "cannot call #allow_blocking_calls with a block outside of the forbidden thread" end Orocos.no_blocking_calls_in_thread = nil begin return yield ensure if forbidden Orocos.no_blocking_calls_in_thread = forbidden end end else current_thread = Orocos.no_blocking_calls_in_thread Orocos.no_blocking_calls_in_thread = nil current_thread end end
Applies the configuration stored in path on task.
The selected sections can be listed in names (by default, uses
the default configuration).
overrides controls whether the sections listed in
names can override each other, if a value set in one of them
can be overriden by another one.
path can either be a file or a directory. In the latter case,
the configuration stored in path/model_name.yml will be used
# File lib/orocos/configurations.rb, line 1050 def self.apply_conf(task, path, names = ['default'], overrides = true) if File.directory?(path) path = File.join(path, "#{task.model.name}.yml") if !File.file?(path) return end end conf = TaskConfigurations.new(task.model) conf.load_from_yaml(path) conf.apply(task, names, overrides) task end
@deprecated use ::apply_conf instead
# File lib/orocos/configurations.rb, line 1034 def self.apply_conf_file(task, path, names = ['default'], overrides = true) conf = TaskConfigurations.new(task.model) conf.load_from_yaml(path) conf.apply(task, names, overrides) task end
Removes dangling references from all name services added to the global name service {Orocos.name_service}
# File lib/orocos/name_service.rb, line 60 def self.cleanup name_service.cleanup end
# File lib/orocos/base.rb, line 219 def self.clear if !keep_orocos_logfile? && orocos_logfile FileUtils.rm_f orocos_logfile end @ruby_task.dispose if @ruby_task default_loader.clear known_orogen_extensions.clear @max_sizes.clear Orocos::CORBA.clear @name_service = nil if defined? Orocos::Async Orocos::Async.clear end if Orocos::ROS.enabled? Orocos::ROS.clear end @loaded = false @initialized = false end
If ::configuration_log is not set, it creates a new configuration log file that will be used by default by ::log_all_configuration. The log file is named as ::configuration_log_name ('task_configuration' by default). This log file becomes the new default log file for all following calls to ::log_all_configuration
# File lib/orocos/logging.rb, line 49 def self.configuration_log if !HAS_POCOLOG raise ArgumentError, "the pocolog Ruby library is not available, configuration logging cannot be used" end @configuration_log ||= Pocolog::Logfiles.create(File.expand_path(Orocos.configuration_log_name, Orocos.default_working_directory)) end
# File lib/orocos/typekits.rb, line 228 def self.create_or_get_null_type(type_name) if registry.include?(type_name) type = registry.get type_name if !type.null? return create_or_get_null_type("/orocos#{type_name}") end type else registry.create_null(type_name) end end
# File lib/orocos/base.rb, line 312 def self.create_orogen_deployment_model(name = nil) OroGen::Spec::Deployment.new(default_project, name) end
# File lib/orocos/base.rb, line 309 def self.create_orogen_task_context_model(name = nil) OroGen::Spec::TaskContext.new(default_project, name) end
The default commandline arguments that will be passed by default in ::run
# File lib/orocos/process.rb, line 33 def self.default_cmdline_arguments @default_cmdline_arguments || {} end
Sets the default commandline arguments that will be passed by default in ::run
Use reset_default_arguments to use the default of the underlying oroGen components
# File lib/orocos/process.rb, line 46 def self.default_cmdline_arguments=(value) if not default_cmdline_arguments.kind_of?(Hash) raise ArgumentError, "Orocos::default_cmdline_arguments expects to be set as hash" end @default_cmdline_arguments = value end
The loader object that should be used to register additional oroGen models
@return [OroGen::Loaders::Files]
# File lib/orocos/base.rb, line 115 def self.default_file_loader Orocos.default_loader @default_file_loader ||= OroGen::Loaders::Files.new(default_loader) end
The loader object that should be used to load typekits and projects
@return [OroGen::Loaders::Aggregate] @see ::default_loader
# File lib/orocos/base.rb, line 101 def self.default_loader if !@default_loader @default_loader = DefaultLoader.new # Instanciate all the sub-loaders default_pkgconfig_loader default_file_loader ROS.default_loader end @default_loader end
The loader object that should be used to load installed oroGen typekits and projects
@return [OroGen::Loaders::PkgConfig] @see ::default_loader
# File lib/orocos/base.rb, line 125 def self.default_pkgconfig_loader Orocos.default_loader @default_pkgconfig_loader ||= OroGen::Loaders::PkgConfig.new(orocos_target, default_loader) end
A project that can be used to create models on-the-fly using {Orocos.default_loader}
# File lib/orocos/base.rb, line 67 def default_project @default_project ||= OroGen::Spec::Project.new(Orocos.default_loader) end
The working directory that should be used by default in ::run
# File lib/orocos/process.rb, line 7 def self.default_working_directory @default_working_directory || Dir.pwd end
Sets the working directory that should be used by default in ::run. By default, the current directory at the time where ::run is called is used.
Use reset_working_directory to use the default of using the current directory.
# File lib/orocos/process.rb, line 24 def self.default_working_directory=(value) value = File.expand_path(value) if !File.directory?(value) raise ArgumentError, "#{value} is not an existing directory" end @default_working_directory = value end
static VALUE orocos_typelib_type_for(VALUE mod, VALUE type_name)
{
RTT::types::TypeInfo* ti = get_type_info(static_cast<char const*>(StringValuePtr(type_name)), false);
if (!ti)
rb_raise(rb_eArgError, "the type %s is not registered in the RTT type system, has the typekit been generated by orogen ?",
StringValuePtr(type_name));
if (ti->hasProtocol(orogen_transports::TYPELIB_MARSHALLER_ID))
{
orogen_transports::TypelibMarshallerBase* transport =
dynamic_cast<orogen_transports::TypelibMarshallerBase*>(ti->getProtocol(orogen_transports::TYPELIB_MARSHALLER_ID));
return rb_str_new2(transport->getMarshallingType());
}
else return Qnil;
}
Enumerates the Orocos::Process objects that are currently available in this Ruby instance
# File lib/orocos/process.rb, line 1337 def self.each_process(&block) Process.each(&block) end
Enumerates the tasks that are currently available on this sytem (i.e. registered on the global name service {Orocos.name_service}).
@yield [TaskContext] code block which is called for each TaskContext
# File lib/orocos/name_service.rb, line 54 def self.each_task(&block) Orocos.name_service.each_task(&block) end
@deprecated use {default_loader}.export_types= instead
# File lib/orocos/typekits.rb, line 24 def self.export_types=(value); default_loader.export_types = value end
@deprecated use {default_loader}.export_types? instead
# File lib/orocos/typekits.rb, line 22 def self.export_types?; default_loader.export_types? end
Requires orocos.rb to extend tasks of the given model with the given block.
For instance, the log method that is defined on every logger task is implemented with
Orocos.extend_task 'logger::Logger' do def log(port, buffer_size = 25) # setup the logging component to log the given port end end
# File lib/orocos/task_context_base.rb, line 862 def self.extend_task(model_name, &block) extension_modules[model_name] << Module.new(&block) end
# File lib/orocos/typekits.rb, line 276 def self.find_orocos_type_name_by_type(type) if type.respond_to?(:name) type = type.name end type = default_loader.resolve_type(type) type = default_loader.opaque_type_for(type) type = default_loader.resolve_interface_type(type) if !registered_type?(type.name) load_typekit_for(type.name) end type.name end
Given a pkg-config file and a base name for a shared library, finds the full path to the library
# File lib/orocos/typekits.rb, line 28 def self.find_plugin_library(pkg, libname) libs = pkg.expand_field('Libs', pkg.raw_fields['Libs']) libs = libs.grep(/^-L/).map { |s| s[2..-1] } libs.find do |dir| full_path = File.join(dir, "lib#{libname}.#{Orocos.shared_library_suffix}") if File.file?(full_path) return full_path, libs end end end
Finds the typelib type that maps to the given orocos type name
@param [String] orocos_type_name @option options [Boolean] :fallback_to_null_type (false) if true, a new
null type with the given orocos type name will be added to the registry and returned if the type cannot be found
@raise [Orocos::TypekitTypeNotFound] if the type cannot be found and no
typekit registers it
@return [Model<Typelib::Type>] a subclass of Typelib::Type that
represents the requested type
# File lib/orocos/typekits.rb, line 258 def self.find_type_by_orocos_type_name(orocos_type_name, options = Hash.new) options = Kernel.validate_options options, :fallback_to_null_type => false if !registered_type?(orocos_type_name) load_typekit_for(orocos_type_name) end typelib_type_for(orocos_type_name) rescue Orocos::TypekitTypeNotFound, Typelib::NotFound # Create an opaque type as a placeholder for the unknown # type name if options[:fallback_to_null_type] type_name = '/' + orocos_type_name.gsub(/[^\w]/, '_') create_or_get_null_type(type_name) else raise end end
# File lib/orocos/typekits.rb, line 83 def self.find_typekit_pkg(name) Utilrb::PkgConfig.get("#{name}-typekit-#{Orocos.orocos_target}", minimal: true) rescue Utilrb::PkgConfig::NotFound raise TypekitNotFound, "the '#{name}' typekit is not available to pkgconfig" end
Returns the full path of all the plugin libraries that should be loaded for the given typekit
If given, typekit_pkg is the PkgConfig file for the requested
typekit
@return [Array<(String,Boolean)>] set of found libraries. The string is
the path to the library and the boolean flag indicates whether loading this library is optional (from orocos.rb's point of view), or required to use the typekit-defined types on transports
# File lib/orocos/typekits.rb, line 139 def self.find_typekit_plugin_paths(name, typekit_pkg = nil) plugins = Hash.new libs = Array.new plugin_name = typekit_library_name(name, Orocos.orocos_target) plugins[plugin_name] = [typekit_pkg || find_typekit_pkg(name), true] if OroGen::VERSION >= "0.8" AUTOLOADED_TRANSPORTS.each do |transport_name, required| plugin_name = transport_library_name(name, transport_name, Orocos.orocos_target) begin pkg = Utilrb::PkgConfig.get(plugin_name, minimal: true) if pkg.disabled != "true" plugins[plugin_name] = [pkg, required] elsif required raise NotFound, "the '#{name}' typekit has a #{transport_name} transport installed, but it is disabled" end rescue Utilrb::PkgConfig::NotFound => e if required raise NotFound, "the '#{name}' typekit has no #{transport_name} transport: could not find pkg-config package #{e.name} in #{ENV['PKG_CONFIG_PATH']}" end end end end plugins.each_pair do |file, (pkg, required)| lib, lib_dirs = find_plugin_library(pkg, file) if !lib if required raise NotFound, "cannot find shared library #{file} for #{name} (searched in #{lib_dirs})" else Orocos.warn "plugin #{file} is registered through pkg-config, but the library cannot be found in #{lib_dirs}" end else libs << [lib, required] end end libs end
# File lib/orocos/base.rb, line 348 def self.forbid_blocking_calls Orocos.no_blocking_calls_in_thread = Thread.current end
(see Orocos::NameService#get)
# File lib/orocos/name_service.rb, line 65 def self.get(name, options = Hash.new) Orocos.name_service.get(name, options) end
Evaluates a block, ensuring that a set of processes or tasks are killed when the control flow leaves it
# File lib/orocos/process.rb, line 1343 def self.guard(*processes_or_tasks) yield rescue Interrupt rescue Exception => e Orocos.warn "killing running task contexts and deployments because of unhandled exception" Orocos.warn " #{e.backtrace[0]}: #{e.message}" e.backtrace[1..-1].each do |line| Orocos.warn " #{line}" end raise ensure processes, tasks = processes_or_tasks.partition do |obj| obj.kind_of?(Orocos::Process) end if processes.empty? processes = each_process.to_a end if !tasks.empty? processes.each do |p| tasks -= p.each_task.to_a end end # NOTE: Process#kill stops all the tasks from the process first, so # that's fine. tasks.each do |t| Orocos.info "guard: stopping task #{t.name}" Orocos::Process.try_task_cleanup(t) end processes.each do |p| if p.running? Orocos.info "guard: stopping process #{p.name}" p.kill(false) end end processes.each do |p| if p.running? Orocos.info "guard: joining process #{p.name}" p.join end end end
Initialize the Orocos communication layer and load all the oroGen models that are available.
This method will verify that the pkg-config environment is sane, as it is demanded by the oroGen deployments. If it is not the case, it will raise a RuntimeError exception whose message will describe the particular problem. See the “Error messages” package in the user's guide for more information on how to fix those.
# File lib/orocos/base.rb, line 265 def self.initialize(name = "orocosrb_#{::Process.pid}") if !loaded? self.load(name) end # Install the SIGCHLD handler if it has not been disabled if !disable_sigchld_handler? trap('SIGCHLD') do begin while dead = ::Process.wait(-1, ::Process::WNOHANG) if mod = Orocos::Process.from_pid(dead) mod.dead!($?) end end rescue Errno::ECHILD end end end if !Orocos::CORBA.initialized? Orocos::CORBA.initialize end @initialized = true if Orocos::ROS.enabled? # ROS does not support being teared down and reinitialized. if !Orocos::ROS.initialized? Orocos::ROS.initialize(name) end end # add default name services self.name_service << Orocos::CORBA.name_service if defined?(Orocos::ROS) && Orocos::ROS.enabled? self.name_service << Orocos::ROS.name_service end if defined?(Orocos::Async) Orocos.name_service.name_services.each do |ns| Orocos::Async.name_service.add(ns) end end @ruby_task = RubyTasks::TaskContext.new(name) end
Returns true if ::initialize has been called and completed successfully
# File lib/orocos/base.rb, line 253 def self.initialized? @initialized end
# File lib/orocos/base.rb, line 189 def self.load(name = nil) if @loaded raise AlreadyInitialized, "Orocos is already loaded. Try to call 'clear' before callign load a second time." end if ENV['ORO_LOGFILE'] && orocos_logfile && (ENV['ORO_LOGFILE'] != orocos_logfile) raise "trying to change the path to ORO_LOGFILE from #{orocos_logfile} to #{ENV['ORO_LOGFILE']}. This is not supported" end ENV['ORO_LOGFILE'] ||= File.expand_path("orocos.#{name || 'orocosrb'}-#{::Process.pid}.txt") @orocos_logfile = ENV['ORO_LOGFILE'] @conf = ConfigurationManager.new @loaded_typekit_plugins.clear @max_sizes = Hash.new { |h, k| h[k] = Hash.new } load_typekit 'std' load_standard_typekits if Orocos::ROS.enabled? if !Orocos::ROS.loaded? # Loads all ROS projects that can be found in # Orocos::ROS#spec_search_directories Orocos::ROS.load end end @loaded = true nil end
Loads all typekits that are available on this system
# File lib/orocos/typekits.rb, line 110 def self.load_all_typekits default_pkgconfig_loader.each_available_typekit_name do |typekit_name| load_typekit(typekit_name) end default_pkgconfig_loader.available_typekits.keys end
Loads a directory containing configuration files
See the documentation of Orocos::ConfigurationManager#load_dir for more information
# File lib/orocos/base.rb, line 170 def self.load_config_dir(dir) conf.load_dir(dir) end
# File lib/orocos/base.rb, line 174 def self.load_extension_runtime_library(extension_name) if !known_orogen_extensions.include?(extension_name) begin require "runtime/#{extension_name}" rescue LoadError end known_orogen_extensions << extension_name end end
static VALUE orocos_load_rtt_plugin(VALUE orocos, VALUE path)
{
try
{
return RTT::plugin::PluginLoader::Instance()->loadLibrary(StringValuePtr(path)) ? Qtrue : Qfalse;
}
catch(std::runtime_error e)
{
rb_raise(rb_eArgError, "%s", e.what());
}
}
static VALUE orocos_load_rtt_typekit(VALUE orocos, VALUE path)
{
try
{
return RTT::plugin::PluginLoader::Instance()->loadLibrary(StringValuePtr(path)) ? Qtrue : Qfalse;
}
catch(std::runtime_error e)
{
rb_raise(rb_eArgError, "%s", e.what());
}
}
static VALUE orocos_load_standard_typekits(VALUE mod)
{
// load the default toolkit and the CORBA transport
RTT::types::TypekitRepository::Import(new RTT::types::RealTimeTypekitPlugin);
RTT::types::TypekitRepository::Import(new RTT::corba::CorbaLibPlugin);
#ifdef HAS_MQUEUE
RTT::types::TypekitRepository::Import(new RTT::mqueue::MQLibPlugin);
#endif
//TODO loadCorbaLib();
return Qnil;
}
Load the typekit whose name is given
Typekits are shared libraries that include marshalling/demarshalling code. It gets automatically loaded in orocos.rb whenever you start processes.
# File lib/orocos/typekits.rb, line 76 def self.load_typekit(name) @lock.synchronize do typekit = default_pkgconfig_loader.typekit_model_from_name(name) load_typekit_plugins(name) end end
Looks for and loads the typekit that handles the specified type
If exported is true (the default), the type needs to be both
defined and exported by the typekit.
Raises ArgumentError if this type is registered nowhere, or if
exported is true and the type is not exported.
# File lib/orocos/typekits.rb, line 185 def self.load_typekit_for(typename, exported = true) typekit = default_loader.typekit_for(typename, exported) if !typekit.virtual? load_typekit typekit.name end typekit end
# File lib/orocos/typekits.rb, line 89 def self.load_typekit_plugins(name, typekit_pkg = nil) if @loaded_typekit_plugins.include?(name) return end find_typekit_plugin_paths(name, typekit_pkg).each do |path, required| begin load_plugin_library(path) rescue Exception => e if required raise else Orocos.warn "plugin #{p}, which is registered as an optional transport for the #{name} typekit, cannot be loaded" Orocos.log_pp(:warn, e) end end end @loaded_typekit_plugins << name end
Returns true if ::load has been called
# File lib/orocos/base.rb, line 185 def self.loaded? @loaded end
# File lib/orocos/logging.rb, line 4 def self.log_all log_all_ports log_all_configuration end
# File lib/orocos/logging.rb, line 56 def self.log_all_configuration(logfile = nil) logfile ||= configuration_log each_process do |process| process.each_task do |t| t.log_all_configuration(logfile) end end end
Setup logging on all output ports of the processes started with ::run
This method is designed to be called within an ::run block
@param [nil,#===] exclude_ports an object matching the name of the ports
that should not be logged (typically a regular expression). If nil, all ports are logged.
@param [nil,#===] exclude_types an object matching the name of the types
that should not be logged (typically a regular expression). If nil, all ports are logged.
@param [nil,Array<String>] tasks name of the tasks for which logging
should be set up
@example log all ports whose name does not start with 'io_'
Orocos.log_all_ports(exclude_ports: /^io_/)
@example log all ports whose type name does not contain 'debug'
Orocos.log_all_ports(exclude_types: /debug/)
# File lib/orocos/logging.rb, line 27 def self.log_all_ports(exclude_ports: nil, exclude_types: nil, tasks: nil) each_process do |process| process.log_all_ports(exclude_ports: exclude_ports, exclude_types: exclude_types, tasks: tasks) end end
Common implementation of ::log_all_ports for a single process
This is shared by local and remote processes alike
# File lib/orocos/logging.rb, line 68 def self.log_all_process_ports(process, tasks: nil, exclude_ports: nil, exclude_types: nil, **logger_options) if !(logger = process.default_logger) return Set.new end process.setup_default_logger( logger, **logger_options) logged_ports = Set.new process.task_names.each do |task_name| task = process.task(task_name) next if task == logger next if tasks && !(tasks === task_name) task.each_output_port do |port| next if exclude_ports && exclude_ports === port.name next if exclude_types && exclude_types === port.type.name next if block_given? && !yield(port) Orocos.info "logging % 50s of type %s" % ["#{task.name}:#{port.name}", port.type.name] logged_ports << [task.name, port.name] logger.log(port) end end if logger.pre_operational? logger.configure end if !logger.running? logger.start end logged_ports end
# File lib/orocos/base.rb, line 131 def self.macos? @macos end
Gets or update known maximum size for variable-sized containers in types
This method can only be called after ::load
Size specification is path.to.field => size, where [] is used to get elements of an array or variable-size container.
If type is a container itself, the second form is used, where the first argument is the container size and the rest specifies its element sizes (and must start with [])
For instance, with the types
struct A
{
std::vector<int> values;
};
struct B
{
std::vector<A> field;
};
Then sizes of type B would be given with
max_sizes('/B', 'field' => 10, 'field[].values' => 20)
while the sizes of /std/vector</A> would be given with
max_sizes('/std/vector</A>', 10, '[].values' => 20)
Finally, for /std/vector</std/vector</A>>, one would use
max_sizes('/std/vector</std/vector</A>>, 10, '[]' => 20, '[][].values' => 30)
@overload ::max_sizes => Hash
Gets all known maximum sizes @return [Hash<String,Hash>] a mapping from type names to the size specification for this type. See above for the hash format
@overload ::max_sizes('/namespace/Compound', 'to[].field' => 10, 'other' => 20)
Updates the known maximum sizes for the given type. When updating, any new field value will erase old ones, unless a block is given in which case the block is given the old and new values and should return the value that should be stored
# File lib/orocos/typekits.rb, line 336 def self.max_sizes(typename = nil, *sizes, &block) if !@max_sizes raise ArgumentError, "cannot call Orocos.max_sizes before Orocos.load" end if !typename && sizes.empty? return @max_sizes end type = default_loader.resolve_type(typename) type = default_loader.intermediate_type_for(type) sizes = OroGen::Spec::Port.validate_max_sizes_spec(type, sizes) @max_sizes[type.name].merge!(sizes, &block) end
Returns the max size specification for the given type
@param [String,Typelib::Type] the type or type name @return [Hash] the maximum size specification, see {Orocos.max_sizes} for
details
# File lib/orocos/typekits.rb, line 356 def self.max_sizes_for(type) if type.respond_to?(:name) type = type.name end @max_sizes.fetch(type, Hash.new) end
Returns the global name service abstracting all underlying name services. This should be the default way to acquire an handle to an Orocos Task by its name. If the IOR of the task is already known {TaskContext} should directly be used.
@example getting a remote/local task context.
require 'orocos' Orocos.initialize task = Orocos.name_service.get "task_name"
@example changing the default underlying CORBA name service
Orocos::CORBA.name_service.ip = "host_name" Orocos.initialize task = Orocos.name_service.get 'task_name'
@example adding a second CORBA name service
Orocos.name_service << Orocos::CORBA::NameService.new("192.168.101.12") Orocos.initialize task = Orocos.name_service.get 'task_name'
@example adding a second CORBA name service having a namespace
Orocos.name_service << Orocos::CORBA::NameService.new("192.168.101.12",:namespace => "robot") Orocos.initialize task = Orocos.name_service.get 'robot/task_name'
@example adding an Avahi name service
Orocos.name_service << Orocos::Avahi::NameService.new("_robot._tcp") Orocos.initialize task = Orocos.name_service.get 'task_name'
@return [Orocos::NameService] The name service
# File lib/orocos/name_service.rb, line 33 def self.name_service @name_service ||= NameService.new() end
# File lib/orocos/name_service.rb, line 37 def self.name_service=(name_service) @name_service = name_service end
static VALUE orocos_no_blocking_calls_in_thread_get(VALUE self)
{
return threadInterdiction;
}
static VALUE orocos_no_blocking_calls_in_thread_set(VALUE self, VALUE thread)
{
threadInterdiction = thread;
return thread;
}
# File lib/orocos/typekits.rb, line 364 def self.normalize_typename(typename) load_typekit_for(typename) registry.get(typename).name end
# File lib/orocos/base.rb, line 147 def self.orocos_target if ENV['OROCOS_TARGET'] ENV['OROCOS_TARGET'] else 'gnulinux' end end
Finds the C++ type that maps to the given typelib type name
@param [Typelib::Type,String] typelib_type
# File lib/orocos/typekits.rb, line 243 def self.orocos_type_for(typelib_type) default_loader.opaque_type_for(typelib_type) end
For backward compatibility only. Use find_typekit_plugin_paths instead
# File lib/orocos/typekits.rb, line 126 def self.plugin_libs_for_name(name) find_typekit_plugin_paths(name).map(&:first) end
# File lib/orocos/base.rb, line 41 def self.register_pkgconfig_path(path) base_path = caller(1).first.gsub(/:\d+:.*/, '') ENV['PKG_CONFIG_PATH'] = "#{File.expand_path(path, File.dirname(base_path))}:#{ENV['PKG_CONFIG_PATH']}" end
static VALUE orocos_registered_type_p(VALUE mod, VALUE type_name)
{
RTT::types::TypeInfo* ti = get_type_info(static_cast<char const*>(StringValuePtr(type_name)), false);
return ti ? Qtrue : Qfalse;
}
The registry that is the union of all loaded typekits
@return [Typelib::Registry]
# File lib/orocos/base.rb, line 61 def registry default_loader.registry end
# File lib/orocos/base.rb, line 242 def self.reset clear load end
Resets the default arguments that should be used by default in ::run which is the default setting of the underlying oroGen components
# File lib/orocos/process.rb, line 39 def self.reset_default_cmdline_arguments @default_cmdline_arguments = {} end
Protect access to {#ruby_task} in multithreading contexts
# File lib/orocos/base.rb, line 87 def ruby_task_access(&block) @@ruby_task_sync.synchronize(&block) end
@overload ::run 'mod1', 'mod2'
Starts a list of deployments. The deployment names are as given to the
'deployment' statement in oroGen
@param (see .parse_run_options)
@yield a block that is evaluated, ensuring that all tasks and processes
are killed when the execution flow leaves the block. The block is given
to {Orocos.guard}
@overload ::run 'mod1', 'mod2' => 'prefix'
Starts a list of deployments. The prefix is prepended to all tasks in
the 'mod2' deployment. The deployment names are as given to the
'deployment' statement in oroGen
@param (see .parse_run_options)
@yield a block that is evaluated, ensuring that all tasks and processes
are killed when the execution flow leaves the block. The block is given
to {Orocos.guard}
@overload ::run 'mod1', 'mod2' => 'prefix', 'project::Task' => 'task_name'
Starts a list of deployments. The prefix is prepended to all tasks in
the 'mod2' deployment, and a process is spawned to deploy a single task
of model 'project::Task' (as defined in oroGen). task_name in this case
becomes the task's name, as can be resolved by Orocos.get.
@param (see Process.parse_run_options)
@yield a block that is evaluated, ensuring that all tasks and processes
are killed when the execution flow leaves the block. The block is given
to {Orocos.guard}
Valid options are:
- wait
-
wait that number of seconds (can be floating-point) for the processes to be ready. If it did not start into the provided timeout, an Orocos::NotFound exception raised.
- output
-
redirect the process output to the given file. The %m and %p patterns will be replaced by respectively the name and the PID of each process.
- valgrind
-
start some or all the processes under valgrind. It can either be an array of process names (e.g. valgrind: ['p1', 'p2']) or 'true'. In the first case, the listed processes will be added to the list of processes to start (if they are not already in it) and will be started under valgrind. In the second case, all processes are started under valgrind.
- valgrind_options
-
an array of options that should be passed to valgrind, e.g.
valgrind_options: ["--track-origins=yes"]
- cmdline_args
-
When command line arguments are available to deployments, they can be set using the following option:
cmdline_args: { "sd-domain" => '_robot._tcp', "prefix" => "test" }This will be mapped to '–sd-domain=_robot._tcp –prefix=test'
Existing commandline arguments: –sd-domain
the service discovery domain in which this process should be published This is only supported by deployments and orogen if the service_discovery package has been installed along with orogen The sd domain is of the format: <name>.<suffix> where the suffix has to be one of _tcp or _udp
# File lib/orocos/process.rb, line 135 def self.run(*args, **options, &block) Process.run(*args, **options, &block) end
Deprecated. Use ::run instead.
# File lib/orocos/process.rb, line 140 def self.spawn(*args, &block) STDERR.puts "#{caller(1)}: Orocos.spawn is deprecated, use Orocos.run instead" run(*args, &block) end
@deprecated access default_loader.task_model_from_name directly instead
# File lib/orocos/base.rb, line 317 def self.task_model_from_name(*args, &block) default_loader.task_model_from_name(*args, &block) end
@deprecated
Returns the task names that are registered on CORBA
You should use ::name_service.names
# File lib/orocos/name_service.rb, line 46 def self.task_names name_service.names end
# File lib/orocos/process.rb, line 57 def self.tracing=(flag) @tracing_enabled = flag end
# File lib/orocos/process.rb, line 53 def self.tracing? !!@tracing_enabled end
# File lib/orocos/process.rb, line 61 def self.tracing_library_path File.join(Utilrb::PkgConfig.new("orocos-rtt-#{Orocos.orocos_target}").libdir, "liborocos-rtt-traces-#{Orocos.orocos_target}.so") end
# File lib/orocos/typekits.rb, line 121 def self.transport_library_name(typekit_name, transport_name, target) "#{typekit_name}-transport-#{transport_name}-#{target}" end
@deprecated use {default_loader}.type_export_namespace instead
# File lib/orocos/typekits.rb, line 18 def self.type_export_namespace; default_loader.type_export_namespace end
@deprecated use {default_loader}.type_export_namespace= instead
# File lib/orocos/typekits.rb, line 20 def self.type_export_namespace=(namespace); default_loader.type_export_namespace = namespace end
# File lib/orocos/typekits.rb, line 117 def self.typekit_library_name(typekit_name, target) "#{typekit_name}-typekit-#{target}" end
Returns the type that is used to manipulate t in Typelib
For simple types, it is t itself. For opaque types, it will be
the corresponding marshalling type. The returned value is a subclass of
Typelib::Type
Raises Typelib::NotFound if this type is not registered anywhere.
# File lib/orocos/typekits.rb, line 200 def self.typelib_type_for(t) if t.respond_to?(:name) return t if !t.contains_opaques? t = t.name end begin if typelib_type = do_typelib_type_for(t) return registry.get(typelib_type) end rescue ArgumentError end if registry.include?(t) type = registry.get(t) if type.contains_opaques? default_loader.intermediate_type_for(type) elsif type.null? # 't' is an opaque type and there are no typelib marshallers # to convert it to something we can manipulate, raise raise Typelib::NotFound, "#{t} is a null type and there are no typelib marshallers registered in RTT to convert it to a typelib-compatible type" else type end else raise Typelib::NotFound, "#{t} cannot be found in the currently loaded registries" end end
@deprecated renamed to Orocos::Scripts.watch
# File lib/orocos/scripts.rb, line 5 def self.watch(*objects, &block) options = Hash.new if objects.last.kind_of?(Hash) options = objects.pop end options = Kernel.validate_options options, :sleep => 0.1, :display => true, :main => nil tasks, ports = objects.partition do |obj| obj.kind_of?(TaskContext) end ports, readers = ports.partition do |obj| obj.kind_of?(OutputPort) end tasks = tasks.sort_by { |t| t.name } readers.concat(ports.map { |p| p.reader }) readers = readers.sort_by { |r| r.port.full_name } readers = readers.map do |r| [r, r.new_sample] end dead_processes = Set.new should_quit = false while true updated_tasks = Set.new updated_ports = Set.new needs_display = true while needs_display needs_display = false info = tasks.map do |t| if t.process && !t.process.running? if !dead_processes.include?(t) needs_display = true updated_tasks << t dead_processes << t "#{t.name}=DEAD" end elsif t.state_changed? needs_display = true updated_tasks << t "#{t.name}=#{t.state(false)}" else "#{t.name}=#{t.current_state}" end end if needs_display puts info.join(" | ") end end readers.each do |r, sample| while r.read_new(sample) puts "new data on #{r.port.full_name}" updated_ports << r.port if options[:display] pp = PP.new(STDOUT) pp.nest(2) do pp.breakable sample.pretty_print(pp) end end end end if should_quit break end if block_given? should_quit = yield(updated_tasks, updated_ports) end if options[:main] should_quit = !options[:main].runtime_state?(options[:main].peek_current_state) end sleep options[:sleep] end end
# File lib/orocos/base.rb, line 136 def self.windows? @windows end
Public Instance Methods
# File lib/orocos/extensions.rb, line 124 def add_watches(processes, _threads) watch_op = operation('watch') if _threads.respond_to?(:to_ary) threads = Hash.new _threads.each do |orocos_task| tid = orocos_task.tid if tid == 0 Orocos.warn "taskmon::Task: cannot automatically add a watch on #{orocos_task}: #tid returned zero, which probably means that you are on a system where oroGen does not implement the getTID operation (e.g. non-Linux)" else threads[tid] = orocos_task.name end end else threads = _threads.to_hash.dup end sent_operations = [] if on_localhost? processes.each do |pid, process_name| process_name ||= pid resolve_process_threads(pid, process_name, threads) end end # We can now add watches for threads that are either not watched # yet, or for which we started to know the name threads.each do |tid, thread_name| old_name = watched_tids[tid] if old_name if old_name == thread_name || !_threads[tid] next else Orocos.info "#{name}: renaming OS task statistics for #{tid} from #{old_name} to #{thread_name}" end else Orocos.info "#{name}: watching OS task statistics for #{tid} with name #{thread_name}" end sent_operations << watch_op.sendop(thread_name, tid) watched_tids[tid] = thread_name end sent_operations.each(&:collect) threads end
Create a new log port for the given interface object
@param [Attribute,Property,OutputPort] object the object that is going
to be logged
@param [Hash] options @option options [String] name (#{object.task.name}.#{object.name}) the created port name @option options [Array<{'key' => String, 'value' => String}>] metadata additional metadata to be stored in the log stream @return [String] the stream name, which is also the name of the
created input port
# File lib/orocos/extensions.rb, line 17 def create_log(object, options = Hash.new) options = Kernel.validate_options options, :name => "#{object.task.name}.#{object.name}", :metadata => [] stream_name = options[:name] if !has_port?(stream_name) stream_metadata = object.log_metadata.map do |key, value| Hash['key' => key, 'value' => value] end stream_metadata.concat(options[:metadata]) if !createLoggingPort(stream_name, object.orocos_type_name, stream_metadata) raise ArgumentError, "cannot create log port on log task #{name} for #{stream_name} and type #{object.orocos_type_name}" end Orocos.info "created logging port #{stream_name} of type #{object.orocos_type_name}" end stream_name end
creates a log stream for annotations
# File lib/orocos/extensions.rb, line 58 def create_log_annotations(stream_name,metadata=Hash.new) if !has_port?(stream_name) metadata = {"rock_stream_type" => "annotations"}.merge metadata metadata = metadata.map do |key, value| Hash['key' => key, 'value' => value] end createLoggingPort(stream_name, Types::Logger::Annotations.name, metadata) Orocos.info "created logging port #{stream_name} of type #{Types::Logger::Annotations.name}" end stream_name end
Log the given interface object on self
It creates the log port using {create_log} if needed, or reuses an existing log port with a matching name
@param [Attribute,Property,OutputPort] object the object that should
be logged
@param [Integer] buffer_size the size of the log buffer (only used for
ports)
# File lib/orocos/extensions.rb, line 46 def log(object, buffer_size = Orocos.default_log_buffer_size) stream_name = create_log(object) if object.kind_of?(Port) port(stream_name).connect_to(object, :type => :buffer, :size => buffer_size) else object.log_port = port(stream_name) object.log_current_value end nil end
# File lib/orocos/extensions.rb, line 70 def log_annotations(time,key,value,stream_name = "") stream_name = create_log_annotations("log_annotations") sample = Types::Logger::Annotations.new sample.time = time sample.key = key sample.value = value sample.stream_name = stream_name @log_annotations_writer ||= port(stream_name).writer :type => :buffer, :size => 25 @log_annotations_writer.write sample end
# File lib/orocos/extensions.rb, line 89 def marker_abort(index,comment) log_annotations(Time.now,"log_marker_abort","<#{index}>;#{comment}") end
# File lib/orocos/extensions.rb, line 101 def marker_abort_all(comment) log_annotations(Time.now,"log_marker_abort_all",comment) end
# File lib/orocos/extensions.rb, line 93 def marker_event(comment) log_annotations(Time.now,"log_marker_event",comment) end
# File lib/orocos/extensions.rb, line 81 def marker_start(index,comment) log_annotations(Time.now,"log_marker_start","<#{index}>;#{comment}") end
# File lib/orocos/extensions.rb, line 85 def marker_stop(index,comment) log_annotations(Time.now,"log_marker_stop","<#{index}>;#{comment}") end
# File lib/orocos/extensions.rb, line 97 def marker_stop_all(comment) log_annotations(Time.now,"log_marker_stop_all",comment) end
# File lib/orocos/extensions.rb, line 169 def remove_watch(thread) remove_watches([thread]) end
# File lib/orocos/extensions.rb, line 173 def remove_watches(threads) # Now remove existing watches that are not required anymore remove_watch_op = operation('removeWatchFromPID') sent_operations = [] threads.each do |thread| tid = if thread.kind_of?(Orocos::TaskContext) then thread.tid else thread end sent_operations << remove_watch_op.sendop(tid) watched_tids.delete(tid) end sent_operations.each(&:collect) end
# File lib/orocos/extensions.rb, line 115 def resolve_process_threads(pid, process_name, threads) # First, convert the process IDs into their corresponding threads # (note: we dup'ed the 'threads' hash) Dir.glob("/proc/#{pid}/task/*") do |thread_path| tid = Integer(File.basename(thread_path)) threads[tid] ||= "#{process_name}-#{tid}" end end
indicates that this task belongs to the tooling of rock
# File lib/orocos/extensions.rb, line 106 def tooling? true end
# File lib/orocos/extensions.rb, line 188 def watch(*args) if args.size == 2 # operation call super elsif args.size > 1 raise ArgumentError, "expected one or two arguments, got #{args.size}" elsif args.first.kind_of?(Orocos::TaskContext) watch_task(args.first) elsif args.first.kind_of?(Orocos::Process) watch_process(args.first) else raise ArgumentError, "expected a task or process object, but got #{args.first}" end end
# File lib/orocos/extensions.rb, line 202 def watch_process(process) processes = { process.pid => process.name } threads = Hash.new process.each_task do |task| threads[task.tid] = task.name end add_watches(processes, threads) end
# File lib/orocos/extensions.rb, line 211 def watch_task(task) add_watches([], { task.tid => task.name }) end