rosruby 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. data/bin/rubyroscore +5 -0
  2. data/lib/ros.rb +25 -0
  3. data/lib/ros/duration.rb +63 -0
  4. data/lib/ros/graph_manager.rb +408 -0
  5. data/lib/ros/log.rb +72 -0
  6. data/lib/ros/master.rb +408 -0
  7. data/lib/ros/master_proxy.rb +256 -0
  8. data/lib/ros/message.rb +65 -0
  9. data/lib/ros/name.rb +88 -0
  10. data/lib/ros/node.rb +442 -0
  11. data/lib/ros/package.rb +144 -0
  12. data/lib/ros/parameter_manager.rb +127 -0
  13. data/lib/ros/parameter_subscriber.rb +47 -0
  14. data/lib/ros/publisher.rb +96 -0
  15. data/lib/ros/rate.rb +41 -0
  16. data/lib/ros/ros.rb +10 -0
  17. data/lib/ros/roscore.rb +29 -0
  18. data/lib/ros/service.rb +37 -0
  19. data/lib/ros/service_client.rb +83 -0
  20. data/lib/ros/service_server.rb +92 -0
  21. data/lib/ros/slave_proxy.rb +153 -0
  22. data/lib/ros/subscriber.rb +119 -0
  23. data/lib/ros/tcpros/client.rb +108 -0
  24. data/lib/ros/tcpros/header.rb +89 -0
  25. data/lib/ros/tcpros/message.rb +74 -0
  26. data/lib/ros/tcpros/server.rb +137 -0
  27. data/lib/ros/tcpros/service_client.rb +104 -0
  28. data/lib/ros/tcpros/service_server.rb +132 -0
  29. data/lib/ros/time.rb +109 -0
  30. data/lib/ros/topic.rb +47 -0
  31. data/lib/ros/xmlrpcserver.rb +40 -0
  32. data/samples/add_two_ints_client.rb +25 -0
  33. data/samples/add_two_ints_server.rb +20 -0
  34. data/samples/gui.rb +126 -0
  35. data/samples/sample_log.rb +16 -0
  36. data/samples/sample_param.rb +20 -0
  37. data/samples/sample_publisher.rb +20 -0
  38. data/samples/sample_subscriber.rb +19 -0
  39. data/scripts/genmsg_ruby.py +1135 -0
  40. data/scripts/genmsg_ruby.pyc +0 -0
  41. data/scripts/gensrv_ruby.py +105 -0
  42. data/scripts/gensrv_ruby.pyc +0 -0
  43. data/scripts/rosruby_genmsg.py +67 -0
  44. data/scripts/run-test.rb +21 -0
  45. data/test/test_header.rb +36 -0
  46. data/test/test_log.rb +45 -0
  47. data/test/test_master_proxy.rb +73 -0
  48. data/test/test_message.rb +13 -0
  49. data/test/test_node.rb +166 -0
  50. data/test/test_package.rb +10 -0
  51. data/test/test_param.rb +27 -0
  52. data/test/test_pubsub.rb +154 -0
  53. data/test/test_rate.rb +16 -0
  54. data/test/test_service.rb +34 -0
  55. data/test/test_slave_proxy.rb +49 -0
  56. data/test/test_time.rb +39 -0
  57. metadata +170 -0
@@ -0,0 +1,144 @@
1
+ # ros/package.rb
2
+ #
3
+ # License: BSD
4
+ #
5
+ # Copyright (C) 2012 Takashi Ogura <t.ogura@gmail.com>
6
+ #
7
+ # == ROS Package manager
8
+ #
9
+ # This is used for adding RUBYLIB path.
10
+ # This file will provide rospack functions, in the future
11
+ #
12
+
13
+ require 'rexml/document'
14
+
15
+ module ROS
16
+
17
+ # This is used for adding RUBYLIB path.
18
+ #
19
+ class Package
20
+
21
+ ##
22
+ # at first check the rospack's cache, if found use it.
23
+ # if not found, check all package path.
24
+ # @param [String] cache_file cache file of rospack
25
+ # @return [Array] fullpath list of all packages
26
+ def self.read_cache_or_find_all(cache_file="#{ENV['HOME']}/.ros/rospack_cache")
27
+ if File.exists?(cache_file)
28
+ f = File.open(cache_file)
29
+ root_line = f.gets.chop
30
+ package_path_line = f.gets.chop
31
+ if root_line == "#ROS_ROOT=#{ENV['ROS_ROOT']}" and
32
+ package_path_line == "#ROS_PACKAGE_PATH=#{ENV['ROS_PACKAGE_PATH']}"
33
+ packages = {}
34
+ while line = f.gets
35
+ packages[File.basename(line.chop)] = line.chop
36
+ end
37
+ packages
38
+ else
39
+ self.find_all_packages
40
+ end
41
+ else
42
+ self.find_all_packages
43
+ end
44
+ end
45
+
46
+ ##
47
+ # search all packages that has manifest.xml
48
+ # @param [Hash] packages current found packages
49
+ # @param [Array] roots root directories for searching
50
+ # @return [Array] fullpath list of all packages
51
+ def self.find_all_packages(packages={}, roots=ENV['ROS_PACKAGE_PATH'].split(':').push(ENV['ROS_ROOT']))
52
+ roots.each do |root|
53
+ if File.exists?("#{root}/manifest.xml")
54
+ packages[File.basename(root)] = root
55
+ else
56
+ if File.exists?(root)
57
+ Dir.foreach(root) do |path|
58
+ if path != "." and path != ".."
59
+ full_path = "#{root}/#{path}"
60
+ if File.directory?(full_path)
61
+ self.find_all_packages(packages, [full_path])
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ packages
69
+ end
70
+
71
+ ##
72
+ # all package path hash
73
+ #
74
+ @@all_packages = self.read_cache_or_find_all
75
+
76
+
77
+ ##
78
+ # get the depend packages of the arg
79
+ # @param [String] package find depends packages of this package
80
+ # @param [Array] packages current found depends
81
+ # @return [Array] packages
82
+ def self.depends(package, packages=[])
83
+ file = File.open("#{@@all_packages[package]}/manifest.xml")
84
+ doc = REXML::Document.new(file)
85
+ doc.elements.each('/package/depend') do |element|
86
+ depend_package = element.attributes['package']
87
+ if not packages.include?(depend_package)
88
+ packages.push(depend_package)
89
+ self.depends(depend_package, packages)
90
+ end
91
+ end
92
+ packages
93
+ end
94
+
95
+
96
+ ##
97
+ # get the current program's package
98
+ # @return [String] name of running programs's package
99
+ def self.find_this_package
100
+ path = File::dirname(File.expand_path($PROGRAM_NAME))
101
+ while path != '/'
102
+ if File.exists?("#{path}/manifest.xml")
103
+ return File::basename(path)
104
+ end
105
+ path = File::dirname(path)
106
+ end
107
+ nil
108
+ end
109
+
110
+ ##
111
+ # add package's [lib/, msg_gen/ruby, srv_gen/ruby] to '$:'.
112
+ # this enables load ruby files easily
113
+ # @param [String] package name of package
114
+ def self.add_path_of_package(package)
115
+ path = @@all_packages[package]
116
+ ["#{path}/msg_gen/ruby", "#{path}/srv_gen/ruby", "#{path}/lib"].each do |path|
117
+ if File.exists?(path)
118
+ if not $:.include?(path)
119
+ $:.push(path)
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ ##
126
+ # add [lib/, msg_gen/ruby, srv_gen/ruby] dirs of all depend packages
127
+ # to RUBYLIB, if the directory exists
128
+ # @param [String] package name of package
129
+ def self.add_path_with_depend_packages(package)
130
+ add_path_of_package(package)
131
+ Package::depends(package).each do |pack|
132
+ add_path_of_package(pack)
133
+ end
134
+ end
135
+
136
+ end
137
+
138
+ ##
139
+ # load manifest and add all dependencies
140
+ # @param [String] package name of package
141
+ def self.load_manifest(package)
142
+ ROS::Package.add_path_with_depend_packages(package)
143
+ end
144
+ end
@@ -0,0 +1,127 @@
1
+ # ros/parameter_manager.rb
2
+ #
3
+ # License: BSD
4
+ #
5
+ # Copyright (C) 2012 Takashi Ogura <t.ogura@gmail.com>
6
+ #
7
+ # == Control Parameter Server Interface
8
+ #
9
+ # ROS parameter sever inteface.
10
+ # API document is here http://ros.org/wiki/ROS/Parameter%20Server%20API
11
+ #
12
+ require "xmlrpc/client"
13
+
14
+ module ROS
15
+
16
+ # ROS parameter sever inteface.
17
+ # API document is here http://ros.org/wiki/ROS/Parameter%20Server%20API
18
+ class ParameterManager
19
+
20
+ # @param [String] master_uri URI of ROS Master (parameter server)
21
+ # @param [String] caller_id caller_id of this node
22
+ # @param [Array] remappings remapps to use for local remappings
23
+ def initialize(master_uri, caller_id, remappings)
24
+ @caller_id = caller_id
25
+ @master_uri = master_uri
26
+ @remappings = remappings
27
+ @server = XMLRPC::Client.new2(@master_uri)
28
+ end
29
+
30
+ ##
31
+ # get parameter named 'key'
32
+ # @param [String] key name of parameter
33
+ # @return [String] parameter value
34
+ def get_param(key)
35
+ if @remappings[key]
36
+ return @remappings[key]
37
+ end
38
+ code, message, value = @server.call("getParam", @caller_id, key)
39
+ case code
40
+ when 1
41
+ return value
42
+ else
43
+ return nil
44
+ end
45
+ end
46
+
47
+ ##
48
+ # set parameter for 'key'
49
+ # @param [String] key key of parameter
50
+ # @param [String, Integer, Float, Boolean] value value of parameter
51
+ # @return [Boolean] true if succeed
52
+ # @raise
53
+ def set_param(key, value)
54
+ code, message, value = @server.call("setParam", @caller_id, key, value)
55
+ case code
56
+ when 1
57
+ return true
58
+ when -1
59
+ raise message
60
+ else
61
+ return false
62
+ end
63
+ end
64
+
65
+ ##
66
+ # delete parameter 'key'
67
+ # @param [String] key key for remove
68
+ # @return [Boolean] return true if success, false if it is not exist
69
+ def delete_param(key)
70
+ code, message, value = @server.call("deleteParam", @caller_id, key)
71
+ case code
72
+ when 1
73
+ return true
74
+ else
75
+ return false
76
+ end
77
+ end
78
+
79
+ ##
80
+ # search the all namespace for key
81
+ # @param [String] key key for search
82
+ # @return [Array] values
83
+ def search_param(key)
84
+ code, message, value = @server.call("searchParam", @caller_id, key)
85
+ case code
86
+ when 1
87
+ return value
88
+ when -1
89
+ raise message
90
+ else
91
+ return false
92
+ end
93
+ end
94
+
95
+ ##
96
+ # check if the master has the key
97
+ # @param [String] key key for check
98
+ # @return [String, Integer, Float, Boolean] value of key
99
+ def has_param(key)
100
+ code, message, value = @server.call("hasParam", @caller_id, key)
101
+ case code
102
+ when 1
103
+ return value
104
+ when -1
105
+ raise message
106
+ else
107
+ return false
108
+ end
109
+ end
110
+
111
+ ##
112
+ # get the all keys of parameters
113
+ # @return [Array] all keys
114
+ #
115
+ def get_param_names
116
+ code, message, value = @server.call("getParamNames", @caller_id)
117
+ case code
118
+ when 1
119
+ return value
120
+ when -1
121
+ raise message
122
+ else
123
+ return false
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,47 @@
1
+ # ros/parameter_subscriber.rb
2
+ #
3
+ # License: BSD
4
+ #
5
+ # Copyright (C) 2012 Takashi Ogura <t.ogura@gmail.com>
6
+ #
7
+ #
8
+ # == Parameter Subscriber
9
+ # callback object for paramUpdate
10
+ #
11
+ #
12
+
13
+ module ROS
14
+
15
+ # callback object for paramUpdate
16
+ #
17
+ class ParameterSubscriber
18
+ # do not make instance directory. Plese use Node#subscribe_parameter.
19
+ # @param [String] key param key to subscribe
20
+ # @param [Proc] callback callback when parameter updated
21
+ def initialize(key, callback)
22
+ @key = key
23
+ @callback = callback
24
+ end
25
+
26
+ # callback with param value
27
+ # @param [String] value value of updated parameter
28
+ def call(value)
29
+ @callback.call(value)
30
+ end
31
+
32
+ # set GraphManager for management
33
+ # @param [GraphManager] manager GraphManager
34
+ def set_manager(manager) #:nodoc
35
+ @manager = manager
36
+ end
37
+
38
+ # shutdown this subscription
39
+ def shutdown
40
+ @manager.shutdown_parameter_subscriber(self)
41
+ end
42
+
43
+ # key of parameter for subscription
44
+ attr_accessor :key
45
+
46
+ end
47
+ end
@@ -0,0 +1,96 @@
1
+ # ros/publisher.rb
2
+ #
3
+ # License: BSD
4
+ #
5
+ # Copyright (C) 2012 Takashi Ogura <t.ogura@gmail.com>
6
+ #
7
+
8
+ require 'ros/topic'
9
+ require 'ros/tcpros/server'
10
+
11
+ module ROS
12
+ # Publisher interface of ROS.
13
+ # A publisher contains multi connection with subscribers.
14
+ # TCPROS protocol implementation is in ROS::TCPROS::Server.
15
+ # Here is sample code. You can shutdown publisher by using this
16
+ # instance (ROS::Publisher#shutdown)
17
+ # node = ROS::Node.new('/rosruby/sample_publisher')
18
+ # publisher = node.advertise('/chatter', Std_msgs::String)
19
+ # sleep(1)
20
+ # msg = Std_msgs::String.new
21
+ # i = 0
22
+ # while node.ok?
23
+ # msg.data = "Hello, rosruby!: #{i}"
24
+ # publisher.publish(msg)
25
+ # i += 1
26
+ # end
27
+ class Publisher < Topic
28
+
29
+ # @param [String] caller_id caller_id of this node
30
+ # @param [String] topic_name name of topic to publish (String)
31
+ # @param [Class] topic_type class of topic
32
+ # @param [Boolean] is_latched latched topic?
33
+ # @param [String] host host name of this node
34
+ def initialize(caller_id, topic_name, topic_type, is_latched, host)
35
+ super(caller_id, topic_name, topic_type)
36
+ @host = host
37
+ @is_latched = is_latched
38
+ @seq = 0
39
+ end
40
+
41
+ ##
42
+ # publish msg object
43
+ # @param [Class] message instance of topic_type class
44
+ # @return [Publisher] self
45
+ def publish(message)
46
+ @seq += 1
47
+ @last_published_msg = message
48
+ if message.has_header?
49
+ message.header.seq = @seq
50
+ end
51
+ @connections.each do |connection|
52
+ connection.msg_queue.push(message)
53
+ end
54
+ self
55
+ end
56
+
57
+ ##
58
+ # add tcpros connection as server
59
+ # @param [String] caller_id caller_id of subscriber
60
+ # @return [TCPROS::Server] connection object
61
+ def add_connection(caller_id) #:nodoc:
62
+ connection = TCPROS::Server.new(@caller_id, @topic_name, @topic_type,
63
+ :host=>@host,
64
+ :latched=>@is_latched,
65
+ :last_published_msg=>@last_published_msg)
66
+ connection.start
67
+ connection.id = "#{@topic_name}_out_#{@connection_id_number}"
68
+ @connection_id_number += 1
69
+ @connections.push(connection)
70
+ return connection
71
+ end
72
+
73
+ # @return [Array] connection data for slave api
74
+ def get_connection_data
75
+ @connections.map do |connection|
76
+ [connection.id, connection.byte_sent, connection.num_sent, 1]
77
+ end
78
+ end
79
+
80
+ # @return [array] connection info for slave api
81
+ def get_connection_info
82
+ info = []
83
+ @connections.each do |connection|
84
+ info.push([connection.id, connection.caller_id, 'o', connection.protocol, @topic_name])
85
+ end
86
+ info
87
+ end
88
+
89
+ ##
90
+ # user interface of shutdown this publisher
91
+ # @return [nil] nil
92
+ def shutdown
93
+ @manager.shutdown_publisher(self)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,41 @@
1
+ # ros/rate.rb
2
+ #
3
+ # License: BSD
4
+ #
5
+ # Copyright (C) 2012 Takashi Ogura <t.ogura@gmail.com>
6
+ #
7
+ #
8
+
9
+ module ROS
10
+
11
+ ##
12
+ # sleep in a Hz timing.
13
+ # @example
14
+ # r = ROS::Rate.new(10)
15
+ # r.sleep
16
+ #
17
+ class Rate
18
+
19
+ # @param [Float] hz Hz
20
+ def initialize(hz)
21
+ @sleep_duration = 1.0 / hz
22
+ @last_time = ::Time.now
23
+ end
24
+
25
+ ##
26
+ # sleep for preset rate [Hz]
27
+ #
28
+ def sleep
29
+ current_time = ::Time.now
30
+ elapsed = current_time - @last_time
31
+ Kernel.sleep(@sleep_duration - elapsed)
32
+ @last_time = @last_time + @sleep_duration
33
+
34
+ # detect time jumping forwards, as well as loops that are
35
+ # inherently too slow
36
+ if current_time - @last_time > @sleep_duration * 2
37
+ @last_time = current_time
38
+ end
39
+ end
40
+ end
41
+ end