module URUA
Public Class Methods
add_axis_concept(context, item)
click to toggle source
# File lib/urua.rb, line 13 def self::add_axis_concept(context, item) #{{{ context.add_variables item, :Axis1, :Axis2, :Axis3, :Axis4, :Axis5, :Axis6 end
download_program(opts,name)
click to toggle source
# File lib/urua.rb, line 87 def self::download_program(opts,name) #{{{ counter = 0 begin opts['ssh'].scp.download! File.join(opts['url'],name) rescue => e counter += 1 URUA::ssh_start opts retry if counter < 3 end end
get_robot_programs(opts)
click to toggle source
# File lib/urua.rb, line 110 def self::get_robot_programs(opts) #{{{ progs = [] begin progs = opts['ssh'].exec!('ls ' + File.join(opts['url'],'*.urp') + ' 2>/dev/null').split("\n") progs.shift if progs[0] =~ /^bash:/ rescue => e URUA::ssh_start opts end progs end
implementation_exit()
click to toggle source
# File lib/urua.rb, line 471 def self::implementation_exit #{{{ Proc.new do on exit do # reserved for important stuff p 'bye' end end end
implementation_run()
click to toggle source
# File lib/urua.rb, line 372 def self::implementation_run #{{{ Proc.new do run do |opts| opts['server'].run if Time.now.to_i - 1 > opts['doit_state'] opts['doit_state'] = Time.now.to_i opts['cp'].value = opts['dash'].get_loaded_program opts['rs'].value = opts['dash'].get_program_state # update remote control state from dashboard server opts['mo'].value = opts['dash'].is_in_remote_control opts['op'].value = opts['dash'].get_operational_mode end if Time.now.to_i - 10 > opts['doit_progs'] opts['doit_progs'] = Time.now.to_i Thread.new do opts['semaphore'].synchronize do # Content of thread # check every 10 seconds for new programs progs = URUA::get_robot_programs(opts) delete = opts['progs'] - progs delete.each do |d| d = d[0..-5] opts['prognodes'][d].delete! opts['prognodes'].delete(d) end add = progs - opts['progs'] add.each do |a| a = a[0..-5] opts['prognodes'][a] = opts['programs'].manifest(a, opts['pf']) end opts['progs'] = progs.dup opts['programs'].find(:Programs).value = opts['progs'] end unless opts['semaphore'].locked? end end data = opts['rtde'].receive if data # robot object opts['mv'].value = data['actual_main_voltage'] opts['rv'].value = data['actual_robot_voltage'] opts['rc'].value = data['actual_robot_current'] opts['ss'].value = data['speed_scaling'] # State objects opts['rm'].value = UR::Rtde::ROBOTMODE[data['robot_mode']] opts['sm'].value = UR::Rtde::SAFETYMODE[data['safety_mode']] opts['jm'].value = UR::Rtde::JOINTMODE[data['joint_mode']] opts['tm'].value = UR::Rtde::TOOLMODE[data['tool_mode']] opts['ps'].value = UR::Rtde::PROGRAMSTATE[data['runtime_state']] # Axes object URUA::split_vector6_data(data['actual_q'],opts['aap'], opts['aapa']) # actual jont positions URUA::split_vector6_data(data['actual_qd'],opts['avel'], opts['avela']) # actual joint velocities URUA::split_vector6_data(data['actual_joint_voltage'],opts['avol'], opts['avola']) # actual joint voltage URUA::split_vector6_data(data['actual_current'],opts['acur'], opts['acura']) # actual current opts['amom'].value = data['actual_momentum'].to_s # actual_momentum # TCP object URUA::split_vector6_data(data['actual_qd'],opts['ap'], opts['apa']) # Actual TCP Pose URUA::split_vector6_data(data['actual_qd'],opts['as'], opts['asa']) # Actual TCP Speed URUA::split_vector6_data(data['actual_qd'],opts['af'], opts['afa']) # Actual TCP Force ######TODO Fix Write Values that opc ua does not overwrite the speed slider mask of manual changes # Write values if opts['rtde_config_recipe_speed'] #if opts['ov'] != opts['ovold'] # if opts['ov'] == data['target_speed_fraction'] #opts['speed']['speed_slider_fraction'] = opts['ov'].value / 100.0 #opts['rtde'].send(opts['speed']) opts['ovold'] = data['target_speed_fraction'] end else if Time.now.to_i - 10 > opts['doit_rtde'] opts['doit_rtde'] = Time.now.to_i URUA::start_rtde opts end end rescue Errno::ECONNREFUSED => e print 'ECONNREFUSED: ' puts e.message rescue UR::Dash::Reconnect => e URUA::start_dash opts puts e.message puts e.backtrace rescue UR::Psi::Reconnect => e URUA::start_psi opts puts e.message puts e.backtrace rescue => e puts e.message puts e.backtrace raise end end end
implementation_startup(opts)
click to toggle source
# File lib/urua.rb, line 125 def self::implementation_startup(opts) #{{{ opts['rtde_config'] ||= File.join(__dir__,'rtde.conf.xml') opts['rtde_config_recipe_base'] ||= 'out' opts['rtde_config_recipe_speed'] ||= 'speed' Proc.new do on startup do |opts| opts['server'] = OPCUA::Server.new opts['server'].add_namespace opts['namespace'] opts['dash'] = nil opts['rtde'] = nil opts['programs'] = nil opts['psi'] = nil # ProgramFile opts['pf'] = opts['server'].types.add_object_type(:ProgramFile).tap{ |p| p.add_method :SelectProgram do |node| a = node.id.to_s.split('/') URUA::protect_reconnect_run(opts) do opts['dash'].load_program(a[-2]) end end p.add_method :StartProgram do |node| unless URUA::robotprogram_running?(opts) a = node.id.to_s.split('/') URUA::protect_reconnect_run(opts) do opts['dash'].load_program(a[-2]) opts['dash'].start_program end end end p.add_method :StartAsUrScript do |node| unless URUA::robotprogram_running?(opts) a = node.id.to_s.split('/') URUA::protect_reconnect_run(opts) do opts['psi'].execute_ur_script(URUA::download_program(opts, a[-2]+".script")) end end end } # TCP ObjectType tcp = opts['server'].types.add_object_type(:Tcp).tap{ |t| t.add_object(:ActualPose, opts['server'].types.folder).tap { |p| URUA::add_axis_concept p, :TCPPose } t.add_object(:ActualSpeed, opts['server'].types.folder).tap{ |p| URUA::add_axis_concept p, :TCPSpeed } t.add_object(:ActualForce, opts['server'].types.folder).tap{ |p| URUA::add_axis_concept p, :TCPForce } } # AxisObjectType ax = opts['server'].types.add_object_type(:AxisType).tap { |a| a.add_object(:ActualPositions, opts['server'].types.folder).tap { |p| URUA::add_axis_concept p, :AxisPositions } a.add_object(:ActualVelocities, opts['server'].types.folder).tap{ |p| URUA::add_axis_concept p, :AxisVelocities } a.add_object(:ActualCurrents, opts['server'].types.folder).tap { |p| URUA::add_axis_concept p, :AxisCurrents } a.add_object(:ActualVoltage, opts['server'].types.folder).tap { |p| URUA::add_axis_concept p, :AxisVoltage } a.add_object(:ActualMomentum, opts['server'].types.folder).tap { |p| p.add_variable :AxisMomentum } } # RobotObjectType rt = opts['server'].types.add_object_type(:RobotType).tap { |r| r.add_variables :SerialNumber, :RobotModel r.add_object(:State, opts['server'].types.folder).tap{ |s| s.add_variables :CurrentProgram, :RobotMode, :RobotState, :JointMode, :SafetyMode, :ToolMode, :ProgramState, :SpeedScaling, :Remote, :OperationalMode s.add_variable_rw :Override } r.add_object(:SafetyBoard, opts['server'].types.folder).tap{ |r| r.add_variables :MainVoltage, :RobotVoltage, :RobotCurrent } r.add_object(:Programs, opts['server'].types.folder).tap{ |p| p.add_object :Program, opts['pf'], OPCUA::OPTIONAL p.add_variable :Programs opts['file'] = p.add_variable :File p.add_method :UploadProgram, name: OPCUA::TYPES::STRING, program: OPCUA::TYPES::STRING do |node, name, program| URUA::upload_program opts, name, program end p.add_method :DownloadProgram, name: OPCUA::TYPES::STRING, return: OPCUA::TYPES::STRING do |node,name| URUA::download_program opts, name end } r.add_method :SelectProgram, name: OPCUA::TYPES::STRING do |node, name| URUA::protect_reconnect_run(opts) do opts['dash'].load_program(name) end end r.add_method :StartProgram do unless URUA::robotprogram_running?(opts) URUA::protect_reconnect_run(opts) do nil unless opts['dash'].start_program end end end r.add_method :StopProgram do URUA::protect_reconnect_run(opts) do opts['dash'].stop_program end end r.add_method :PauseProgram do URUA::protect_reconnect_run(opts) do opts['dash'].pause_program end end r.add_method :RunUrScript, content: OPCUA::TYPES::STRING do |node, content| unless URUA::robotprogram_running?(opts) URUA::protect_reconnect_run(opts) do opts['psi'].execute_ur_script(content) end end end r.add_method :PowerOn do if opts['rm'].value.to_s != 'Running' Thread.new do sleep 0.5 until opts['rm'].value.to_s == 'Idle' URUA::protect_reconnect_run(opts) do puts 'break released' if opts['dash'].break_release end end end end r.add_method :PowerOff do URUA::protect_reconnect_run(opts) do opts['dash'].power_off end end r.add_object(:RobotMode, opts['server'].types.folder).tap{ |r| r.add_method :AutomaticMode do opts['dash'].set_operation_mode_auto end r.add_method :ManualMode do opts['dash'].set_operation_mode_manual end r.add_method :ClearMode do opts['dash'].clear_operation_mode end } r.add_object(:Messaging, opts['server'].types.folder).tap{ |r| r.add_method :PopupMessage, message: OPCUA::TYPES::STRING do |node, message| opts['dash'].open_popupmessage(message) end r.add_method :ClosePopupMessage do opts['dash'].close_popupmessage end r.add_method :AddToLog, message: OPCUA::TYPES::STRING do |node, message| opts['dash'].add_to_log(message) end r.add_method :CloseSafetyPopup do URUA::protect_reconnect_run(opts) do opts['dash'].close_safety_popup end end } } ### populating the adress space ### Robot object robot = opts['server'].objects.manifest(File.basename(opts['namespace']), rt) opts['sn'] = robot.find(:SerialNumber) opts['model'] = robot.find(:RobotModel) ### SafetyBoard sb = robot.find(:SafetyBoard) opts['mv'] = sb.find(:MainVoltage) opts['rv'] = sb.find(:RobotVoltage) opts['rc'] = sb.find(:RobotCurrent) ### StateObject st = robot.find(:State) opts['rm'] = st.find(:RobotMode) opts['sm'] = st.find(:SafetyMode) opts['jm'] = st.find(:JointMode) opts['tm'] = st.find(:ToolMode) opts['ps'] = st.find(:ProgramState) opts['rs'] = st.find(:RobotState) opts['cp'] = st.find(:CurrentProgram) opts['ov'] = st.find(:Override) opts['ss'] = st.find(:SpeedScaling) opts['mo'] = st.find(:Remote) opts['op'] = st.find(:OperationalMode) ### Axes axes = robot.manifest(:Axes, ax) aapf, avelf, acurf, avolf, amomf = axes.find :ActualPositions, :ActualVelocities, :ActualCurrents, :ActualVoltage, :ActualMomentum ### Positions opts['aap'] = aapf.find :AxisPositions opts['aapa'] = aapf.find :Axis1, :Axis2, :Axis3, :Axis4, :Axis5, :Axis6 ### Velocities opts['avel'] = avelf.find :AxisVelocities opts['avela'] = avelf.find :Axis1, :Axis2, :Axis3, :Axis4, :Axis5, :Axis6 ### Currents opts['acur'] = acurf.find :AxisCurrents opts['acura'] = acurf.find :Axis1, :Axis2, :Axis3, :Axis4, :Axis5, :Axis6 ### Voltage opts['avol'] = avolf.find :AxisVoltage opts['avola'] = avolf.find :Axis1, :Axis2, :Axis3, :Axis4, :Axis5, :Axis6 ### Momentum opts['amom'] = amomf.find :AxisMomentum ### TCP tcp = robot.manifest(:Tcp, tcp) apf, asf, aff = tcp.find :ActualPose, :ActualSpeed, :ActualForce ### TCP Pose opts['ap'] = apf.find :TCPPose opts['apa'] = apf.find :Axis1, :Axis2, :Axis3, :Axis4, :Axis5, :Axis6 ### TCP Speed opts['as'] = asf.find :TCPSpeed opts['asa'] = asf.find :Axis1, :Axis2, :Axis3, :Axis4, :Axis5, :Axis6 ### TCP Force opts['af'] = aff.find :TCPForce opts['afa'] = aff.find :Axis1, :Axis2, :Axis3, :Axis4, :Axis5, :Axis6 ### Connecting to universal robot URUA::start_rtde opts URUA::start_dash opts URUA::start_psi opts ### Manifest programs opts['programs'] = robot.find(:Programs) opts['prognodes'] = {} opts['progs'] = [] opts['semaphore'] = Mutex.new ### check if interfaces are ok raise if !opts['dash'] || !opts['rtde'] || !opts['psi'] # Functionality for threading in loop opts['doit_state'] = Time.now.to_i opts['doit_progs'] = Time.now.to_i opts['doit_rtde'] = Time.now.to_i # Serious comment (we do the obvious stuff) opts['sn'].value = opts['dash'].get_serial_number opts['model'].value = opts['dash'].get_robot_model rescue Errno::ECONNREFUSED => e print 'ECONNREFUSED: ' puts e.message rescue UR::Dash::Reconnect => e URUA::start_dash opts puts e.message puts e.backtrace rescue UR::Psi::Reconnect => e URUA::start_psi opts puts e.message puts e.backtrace rescue => e puts e.message puts e.backtrace raise end end end
protect_reconnect_run(opts) { || ... }
click to toggle source
# File lib/urua.rb, line 58 def self::protect_reconnect_run(opts) #{{{ tries = 0 begin yield rescue UR::Dash::Reconnect => e puts e.message tries += 1 if tries < 2 URUA::start_dash opts retry end rescue UR::Psi::Reconnect => e puts e.message tries += 1 if tries < 2 URUA::start_psi opts retry end end end
robotprogram_running?(opts)
click to toggle source
# File lib/urua.rb, line 121 def self::robotprogram_running?(opts) opts['ps'].value == 'Playing' end
split_vector6_data(vector, item, nodes)
click to toggle source
# File lib/urua.rb, line 17 def self::split_vector6_data(vector, item, nodes) #{{{ # aqd = data['actual_qd'].to_s item.value = vector.to_s va = vector.to_s[1..-2].split(',') nodes.each_with_index do |a, i| a.value = vector[i].to_f end [vector.to_s, va] end
ssh_start(opts)
click to toggle source
# File lib/urua.rb, line 79 def self::ssh_start(opts) #{{{ if opts['certificate'] opts['ssh'] = Net::SSH.start(opts['ipadress'], opts['username'], :keys => [ opts['certificate'] ]) else opts['ssh'] = opts['password'] ? Net::SSH.start(opts['ipadress'], opts['username'], password: opts['password']) : Net::SSH.start(opts['ipadress'], opts['username']) end end
start_dash(opts)
click to toggle source
# File lib/urua.rb, line 27 def self::start_dash(opts) #{{{ opts['dash'] = UR::Dash.new(opts['ipadress']).connect rescue nil end
start_psi(opts)
click to toggle source
# File lib/urua.rb, line 31 def self::start_psi(opts) opts['psi'] = UR::Psi.new(opts['ipadress']).connect rescue nil end
start_rtde(opts)
click to toggle source
# File lib/urua.rb, line 35 def self::start_rtde(opts) #{{{ ### Loading config file conf = UR::XMLConfigFile.new opts['rtde_config'] output_names, output_types = conf.get_recipe opts['rtde_config_recipe_base'] opts['rtde'] = UR::Rtde.new(opts['ipadress']).connect ### Set Speed if opts['rtde_config_recipe_speed'] speed_names, speed_types = conf.get_recipe opts['rtde_config_recipe_speed'] opts['speed'] = opts['rtde'].send_input_setup(speed_names, speed_types) opts['speed']['speed_slider_mask'] = 1 opts['ov'].value = opts['speed']['speed_slider_fraction'].to_i end ### Setup output if not opts['rtde'].send_output_setup(output_names, output_types,10) puts 'Unable to configure output' end if not opts['rtde'].send_start puts 'Unable to start synchronization' end end
upload_program(opts,name,program)
click to toggle source
# File lib/urua.rb, line 98 def self::upload_program(opts,name,program) #{{{ counter = 0 begin opts['ssh'].scp.upload StringIO.new(program), File.join(opts['url'],name) rescue => e counter += 1 URUA::ssh_start opts retry if counter < 3 end nil end