class LogTools::Converter
Attributes
converters[R]
from[RW]
keep_registry[RW]
logger[RW]
output_folder[RW]
post_fix[RW]
pre_fix[RW]
streams[RW]
time_offset[RW]
to[RW]
use_sample_time[RW]
Public Class Methods
new()
click to toggle source
# File lib/log_tools/converter.rb, line 147 def initialize @current_converter = nil @post_fix ="" @pre_fix ="" @from = nil @to = nil @streams = [] @use_sample_time = false @output_folder = "updated" @time_offset = 0 @keep_registry = false reload_converter end
register(*parameter,&block)
click to toggle source
method to register custom converters it is allowed to use #deep_cast insight the converter to convert subfields
# File lib/log_tools/converter.rb, line 142 def self.register(*parameter,&block) @converters << TypeConverter.new(*parameter,&block) @converters.sort!{|a,b| a.time_to <=> b.time_to} end
Public Instance Methods
clear()
click to toggle source
# File lib/log_tools/converter.rb, line 286 def clear @converters.clear end
convert(*logfiles)
click to toggle source
converts logfiles to a new version if the last parameter is a Time object the logfiles are converted to a version which was valid at given time. The current Orocos.registry must have the same type version !!!
# File lib/log_tools/converter.rb, line 188 def convert(*logfiles) if @use_sample_time && !@use_sample_time.respond_to?(:to_sym) @use_sample_time = :time end #create folder if given if output_folder && !File.directory?(output_folder) Dir.mkdir(output_folder) end logfiles.flatten! #check last parameters final_registry = nil if logfiles.last.is_a? Typelib::Registry final_registry = logfiles.pop else final_registry = Orocos.registry end @current_registry = final_registry # this has to be removed later time_to=Time.now if logfiles.last.is_a? Time time_to = logfiles.pop end logfiles.each do |logfile| Converter.info "converting #{logfile}" file = Pocolog::Logfiles.open(logfile) #we have to create the log file manually because we do not want to #use the automatically applied file name logic output = Pocolog::Logfiles.new(Typelib::Registry.new) output.new_file(new_file_path(logfile)) time = Time.now file.streams.each do |stream| if !streams.empty? && !streams.include?(stream.name) #ignore all streams which are not listed if a filter is given Converter.info "ignoring stream #{stream.name} (#{stream.size} samples)" next end Converter.info " converting stream #{stream.name} (#{stream.size} samples)" + (@use_sample_time ? " using :#{@use_sample_time} field as time source" : "") stream_output = nil index = 1 last_ignore = nil wrote_warning = !@use_sample_time final_registry = stream.registry if keep_registry stream.samples.each do |rt,lg,sample| ignore = (from && lg < from) || (to && lg > to) if last_ignore != ignore Converter.info "### ignoring samples enabled ###" if ignore Converter.info "### ignoring samples disabled ###" if !ignore last_ignore = ignore end if (Time.now-time).to_f < 1 Converter.debug " #{stream.name}.sample #{index}/#{stream.size}" else time = Time.now Converter.info " #{stream.name}.sample #{index}/#{stream.size}" end if !ignore # Undo any custom convertions that typelib might have applied sample = Typelib.from_ruby(sample, stream.type) begin new_sample = convert_type(sample,rt,time_to,final_registry) rescue Orocos::TypekitTypeNotFound => e Converter.warn "skipping stream #{stream.name} due to a missing type definition #{sample.class.name} in the orocos registry." break end new_sample_class = new_sample.class #use type_name of the old stream if we have for example a fixnum new_sample_class = stream.type_name unless new_sample_class.respond_to? :registry stream_output ||= output.create_stream(stream.name,new_sample_class,stream.metadata) if(@use_sample_time && (new_sample.respond_to? @use_sample_time)) sample_time = new_sample.get_field(@use_sample_time) stream_output.write(rt,sample_time+@time_offset,new_sample) else if(@use_sample_time && !wrote_warning) Converter.warn "stream #{stream.name} has no field '#{@use_sample_time}' falling back to the logfile time" wrote_warning = true end stream_output.write(rt,lg+@time_offset,new_sample) end end index += 1 end Converter.info "### ignoring samples disabled ###" if last_ignore Converter.info " done!" end output.close end end
convert_type(sample,time_from,time_to=Time.now,final_registry=Orocos.registry)
click to toggle source
convertes sample to a new type which was valid at time_to the final_registry must have a compatible version!!!
# File lib/log_tools/converter.rb, line 292 def convert_type(sample,time_from,time_to=Time.now,final_registry=Orocos.registry) if(sample.is_a?(Fixnum)||sample.is_a?(Float)) return sample end raise 'No time periode is given!!!' unless time_from && time_to _converters = @converters.map{|c|(c.time_to>=time_from && c.time_to <= time_to) ? c : nil } _converters.compact! sample_was_converted = false if !_converters.empty? _converters.each_with_index do |c,index| @current_converter = c #update current_registry if @current_converter.convert?(sample) Converter.debug " Using Converter: #{c.name}" @current_registry = @current_converter.new_registry new_sample = @current_converter.new_sample_for sample deep_cast(new_sample,sample) sample = new_sample sample = Typelib.from_ruby(sample, sample.class) sample_was_converted = true end end end if !sample_was_converted #this can be removed later if typelib is supporting daisy chain @current_registry = nil # we have to convert it via deep_cast end #this is needed to be sure that the version is compatible to the #final registry if @current_registry != final_registry @current_converter = nil @current_registry = final_registry new_sample = nil begin new_sample = @current_registry.get(sample.class.name).new rescue Typelib::NotFound => e Orocos.load_typekit_for sample.class.name, false new_sample = @current_registry.get(sample.class.name).new end deep_cast(new_sample,sample) sample = new_sample end sample end
copy_vector(to,from)
click to toggle source
copies a vector
# File lib/log_tools/converter.rb, line 341 def copy_vector(to,from) if to.respond_to?(:data) from.data.to_a.each_with_index do |data,i| to.data[i] = data end else from.data.to_a.each_with_index do |data,i| to[i] = data end end end
deep_cast(dest,src,*excluded_fields)
click to toggle source
converts src Typelib::Type int dest Typelib::Type uses converters to convert fields and sub fields which have changed
# File lib/log_tools/converter.rb, line 355 def deep_cast(dest,src,*excluded_fields) @@message = false if !defined? @@message excluded_fields.flatten! if !dest.is_a?(Typelib::Type) || !src.is_a?(Typelib::Type) raise "Cannot convert #{src.class.name} into #{dest.class.name}. "+ "Register a converter which does the conversion" end do_not_cast_self = excluded_fields.include?(:self) ? true : false excluded_fields.delete :self if do_not_cast_self src_type = src.class dest_type = dest.class if @current_converter && @current_converter.convert?(src.class.name) && !do_not_cast_self Converter.debug "convert for #{dest_type}" @current_converter.convert(dest,src,nil,self) else if(dest_type.casts_to?(src_type) && !do_not_cast_self &&(!@current_converter||!@current_converter.convert_field_from?(src))) Converter.debug "copy for #{dest_type}" #if @@message Typelib.copy(dest, src) elsif src_type < Typelib::ContainerType Converter.debug "deep cast for #{src_type}" dest.clear element_type = dest_type.deference src.each do |src_element| dst_element = element_type.new if src_element.is_a? Typelib::Type deep_cast(dst_element, src_element) else dst_element = src_element end dest.push dst_element end elsif src_type < Typelib::CompoundType Converter.debug "deep cast2 for #{src_type}" if @@message dest_fields = dest_type.get_fields. map { |field_name, _| field_name }. to_set src_type.each_field do |field_name, src_field_type| next if excluded_fields.include? field_name next if !dest_fields.include?(field_name) dest_field_type = dest_type[field_name] src_value = src.raw_get_field(field_name) if src_value.is_a? NilClass Log.warn "field #{field_name} has an undefined value" next end if src_value.is_a? Typelib::Type if @current_converter && @current_converter.convert?(src_field_type.name) dest.raw_set_field(field_name,@current_converter.new_sample_for(src_field_type.name)) end excluded_fields2 = excluded_fields.map{|field| field.to_s.match("#{field_name}\.(.*)");$1}.compact deep_cast(dest.raw_get_field(field_name), src_value,excluded_fields2) else #check if the value has to be converted if(@current_converter && @current_converter.convert?(src_field_type.name)) Converter.debug "convert2 for #{src_field_type.name}" if @@message #be carefull string, symbol etc are no reference dest_temp = @current_converter.new_sample_for src_field_type.name dest_temp = @current_converter.convert(dest_temp,src.raw_get_field(field_name),src_field_type.name,self) dest.raw_set_field(field_name,dest_temp) else dest.raw_set_field(field_name,src.raw_get_field(field_name)) end end end elsif src.respond_to? :each_with_index src.each_with_index do |sample,index| deep_cast(dest[index],sample) end elsif src.kind_of?(Typelib::NumericType) && dest.kind_of?(Typelib::NumericType) # at the moment typelib cannot handle the conversion therefore # convert to and from ruby to do the conversion Typelib::copy(dest,Typelib::from_ruby(src.to_ruby,dest.class)) else raise ArgumentError, "cannot deep cast #{src_type} into #{dest_type}" end end dest rescue SystemStackError => e Converter.error "Stack level to deep. Have you called deep_cast from your converter #{@current_converter.name} for type #{dest.class.name} and forgot to exclude :self?" exit(1) end
new_file_path(old_file_path)
click to toggle source
creates a file path for a new file based on the old file path
# File lib/log_tools/converter.rb, line 175 def new_file_path(old_file_path) if File.directory?(output_folder) File.join(output_folder,pre_fix+File.basename(old_file_path,".log")+post_fix+".log") else File.join(File.dirname(old_file_path),pre_fix+File.basename(old_file_path,".log")+post_fix+".log") end end
register(*parameter,&block)
click to toggle source
# File lib/log_tools/converter.rb, line 169 def register(*parameter,&block) @converters << TypeConverter.new(*parameter,&block) @converters.sort!{|a,b| a.time_to <=> b.time_to} end
reload_converter()
click to toggle source
# File lib/log_tools/converter.rb, line 161 def reload_converter @converters = Converter.converters.clone end
streams=(streams)
click to toggle source
# File lib/log_tools/converter.rb, line 165 def streams=(streams) @streams = Array(streams) end