rosruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,256 @@
1
+ # ros/master_proxy.rb
2
+ #
3
+ # License: BSD
4
+ #
5
+ # Copyright (C) 2012 Takashi Ogura <t.ogura@gmail.com>
6
+ #
7
+ #
8
+ # == ROS Master Proxy
9
+ # access to ROS Master
10
+ #
11
+ #
12
+
13
+ require 'xmlrpc/client'
14
+
15
+ module ROS
16
+
17
+ # == ROS Master Proxy
18
+ # access to ROS Master.
19
+ # @see http://ros.org/wiki/ROS/Master_API
20
+ # But there are not documented API.
21
+ #
22
+ class MasterProxy
23
+
24
+ #
25
+ # @param [String] caller_id caller_id of this node
26
+ # @param [String] master_uri URI of ROS Master
27
+ # @param [String] slave_uri slave URI of this node
28
+ def initialize(caller_id, master_uri, slave_uri)
29
+ @caller_id = caller_id
30
+ @master_uri = master_uri
31
+ @slave_uri = slave_uri
32
+ @proxy = XMLRPC::Client.new2(@master_uri).proxy
33
+ end
34
+
35
+ # register a service
36
+ # @param [String] service name of service
37
+ # @param [String] service_api service api uri
38
+ # @return [Boolean] true success
39
+ # @raise RuntimeError
40
+ def register_service(service, service_api)
41
+ code, message, val = @proxy.registerService(@caller_id,
42
+ service,
43
+ service_api,
44
+ @slave_uri)
45
+ if code == 1
46
+ return true
47
+ else
48
+ raise message
49
+ end
50
+ end
51
+
52
+ # unregister a service
53
+ # @param [String] service name of service
54
+ # @param [String] service_api service api uri
55
+ # @return [Boolean] true success
56
+ # @raise RuntimeError
57
+ def unregister_service(service, service_api)
58
+ code, message, val = @proxy.unregisterService(@caller_id,
59
+ service,
60
+ service_api)
61
+ if code == 1
62
+ return true
63
+ elsif code == 0
64
+ puts message
65
+ return true
66
+ else
67
+ raise message
68
+ end
69
+ end
70
+
71
+ # register a subscriber
72
+ # @param [String] topic topic name
73
+ # @param [String] topic_type topic type
74
+ # @return [Array] URI of current publishers
75
+ # @raise [RuntimeError] if error
76
+ def register_subscriber(topic, topic_type)
77
+ code, message,val = @proxy.registerSubscriber(@caller_id,
78
+ topic,
79
+ topic_type,
80
+ @slave_uri)
81
+ if code == 1
82
+ val
83
+ elsif code == 0
84
+ puts message
85
+ val
86
+ else
87
+ raise message
88
+ end
89
+ end
90
+
91
+ # unregister a subscriber
92
+ # @param [String] topic name of topic to unregister
93
+ # @return [Boolean] true
94
+ # @raise RuntimeError
95
+ def unregister_subscriber(topic)
96
+ code, message,val = @proxy.unregisterSubscriber(@caller_id,
97
+ topic,
98
+ @slave_uri)
99
+ if code == 1
100
+ return true
101
+ elsif code == 0
102
+ puts message
103
+ return true
104
+ else
105
+ raise message
106
+ end
107
+ end
108
+
109
+ # register a publisher
110
+ # @param [String] topic topic name of topic
111
+ # @param [String] topic_type type of topic
112
+ # @return [Array] URI of current subscribers
113
+ # @raise RuntimeError
114
+ def register_publisher(topic, topic_type)
115
+ code, message, uris = @proxy.registerPublisher(@caller_id,
116
+ topic,
117
+ topic_type,
118
+ @slave_uri)
119
+ if code == 1
120
+ uris
121
+ else
122
+ raise message
123
+ end
124
+ end
125
+
126
+ # unregister a publisher
127
+ # @param [String] topic name of topic
128
+ # @return [Boolean] true
129
+ # @raise RuntimeError
130
+ def unregister_publisher(topic)
131
+ code, message, val = @proxy.unregisterPublisher(@caller_id,
132
+ topic,
133
+ @slave_uri)
134
+ if code == 1
135
+ return val
136
+ elsif code == 0
137
+ puts message
138
+ return true
139
+ else
140
+ raise message
141
+ end
142
+ return false
143
+ end
144
+
145
+ ##
146
+ # this method is not described in the wiki.
147
+ # subscribe to the parameter key.
148
+ # @param [String] key name of parameter
149
+ # @return [Boolean] true
150
+ # @raise [RuntimeError] if fail
151
+ def subscribe_param(key)
152
+ code, message, uri = @proxy.subscribeParam(@caller_id, @slave_uri, key)
153
+ if code == 1
154
+ return true
155
+ else
156
+ raise message
157
+ end
158
+ end
159
+
160
+ ##
161
+ # unsubscribe to the parameter key.
162
+ # this method is not described in the wiki.
163
+ # @param [String] key name of parameter key
164
+ # @return [Boolean] true
165
+ # @raise [RuntimeError] if failt
166
+ def unsubscribe_param(key)
167
+ code, message, uri = @proxy.unsubscribeParam(@caller_id, @slave_uri, key)
168
+ if code == 1
169
+ return true
170
+ else
171
+ raise message
172
+ end
173
+ end
174
+
175
+ # lookup a node by name.
176
+ # @param [String] node_name
177
+ # @return [String, nil] URI of the node if it is found. nil not found.
178
+ def lookup_node(node_name)
179
+ code, message, uri = @proxy.lookupNode(@caller_id, node_name)
180
+ if code == 1
181
+ uri
182
+ else
183
+ nil
184
+ end
185
+ end
186
+
187
+ # get the all published topics
188
+ # @param [String] subgraph namespace for check
189
+ # @return [Array] topic names.
190
+ # @raise
191
+ def get_published_topics(subgraph='')
192
+ code, message, topics = @proxy.getPublishedTopics(@caller_id, subgraph)
193
+ if code == 1
194
+ return topics
195
+ elsif
196
+ raise message
197
+ end
198
+ end
199
+
200
+ # get system state
201
+ # @return [Array] state
202
+ def get_system_state
203
+ code, message, state = @proxy.getSystemState(@caller_id)
204
+ if code == 1
205
+ return state
206
+ else
207
+ raise message
208
+ end
209
+ end
210
+
211
+ # get the master URI
212
+ # @return [String] uri
213
+ # @raise
214
+ def get_uri
215
+ code, message, uri = @proxy.getUri(@caller_id)
216
+ if code == 1
217
+ return uri
218
+ else
219
+ raise message
220
+ end
221
+ end
222
+
223
+ # look up a service by name
224
+ # @param [String] service name of service
225
+ # @return [String, nil] URI of service if found, nil not found.
226
+ def lookup_service(service)
227
+ code, message, uri = @proxy.lookupService(@caller_id, service)
228
+ if code == 1
229
+ uri
230
+ else
231
+ false
232
+ end
233
+ end
234
+
235
+ # Master URI
236
+ # @return [String]
237
+ attr_reader :master_uri
238
+
239
+ # set the master uri
240
+ # @param [String] uri master uri
241
+ # @return [MasterProxy] self
242
+ def master_uri=(uri)
243
+ @master_uri = uri
244
+ @proxy = XMLRPC::Client.new2(@master_uri).proxy
245
+ self
246
+ end
247
+
248
+ # Slave URI
249
+ # @return [String]
250
+ attr_accessor :slave_uri
251
+
252
+ # caller id of this node
253
+ # @return [String]
254
+ attr_accessor :caller_id
255
+ end
256
+ end
@@ -0,0 +1,65 @@
1
+ # ros/message.rb
2
+ #
3
+ # License: BSD
4
+ #
5
+ # Copyright (C) 2012 Takashi Ogura <t.ogura@gmail.com>
6
+ #
7
+ # == Message file for msg/srv (de)serialization
8
+ #
9
+ #
10
+
11
+ module ROS
12
+
13
+ ##
14
+ # super class of all msg/srv converted class.
15
+ # Currently this is none.
16
+ class Message
17
+ end
18
+
19
+ ##
20
+ # used for serialization (for python like grammar)
21
+ # this is used by msg/srv converted *.rb files
22
+ # it can be removed, if there are more effective genmsg_ruby.
23
+ class Struct
24
+
25
+ # @param [String] format
26
+ def initialize(format)
27
+ @format = format
28
+ end
29
+
30
+ attr_reader :format
31
+
32
+ def self.calc_size(format)
33
+ array = []
34
+ start = 0
35
+ while start < format.length
36
+ re = /(\w)(\d*)/
37
+ re =~ format[start..(format.length-1)]
38
+ number = $2.to_i
39
+ if number == 0
40
+ array.push(0)
41
+ else
42
+ for i in 1..number
43
+ array.push(0)
44
+ end
45
+ end
46
+ start += $&.length
47
+ end
48
+ array.pack(format).length
49
+ end
50
+
51
+ # pack the data
52
+ # @param [Array] args
53
+ def pack(*args)
54
+ args.pack(@format)
55
+ end
56
+
57
+ # unpack from string
58
+ # @param [String] arg
59
+ # @return [Array] unpacked data
60
+ def unpack(arg)
61
+ arg.unpack(@format)
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,88 @@
1
+ # ros/name.rb
2
+ #
3
+ # License: BSD
4
+ #
5
+ # Copyright (C) 2012 Takashi Ogura <t.ogura@gmail.com>
6
+ #
7
+ # == Naming module
8
+ #
9
+ # ROS naming module.
10
+ #
11
+
12
+ require 'socket' # for gethostname
13
+
14
+ module ROS
15
+
16
+ ##
17
+ # this module provides naming functions.
18
+ #
19
+ module Name
20
+
21
+ # name sparation char ('/')
22
+ SEP = '/'
23
+
24
+ ##
25
+ # start with '/' and use single '/' for names
26
+ #
27
+ # @param [String] name input name
28
+ # @return [String] canonicalized name
29
+ def canonicalize_name(name)
30
+ if name == nil or name == SEP
31
+ return name
32
+ elsif name[0] == SEP[0]
33
+ return name.split(/\/+/).join(SEP)
34
+ else
35
+ return SEP + name.split(/\/+/).join(SEP)
36
+ end
37
+ end
38
+
39
+ ##
40
+ # expand ~local_param like names.
41
+ #
42
+ # @param [String] caller_id caller id for replacing ~
43
+ # @param [String] name param name like '~param'
44
+ # @return [String] expanded name
45
+ def expand_local_name(caller_id, name)
46
+ if name[0] == '~'[0]
47
+ caller_id + SEP + name[1..-1]
48
+ else
49
+ name
50
+ end
51
+ end
52
+
53
+ ##
54
+ # generate anonymous name using input id.
55
+ # (arange from roslib)
56
+ # @param [String] id base id (String)
57
+ # @return [String] return generated id
58
+ def anonymous_name(id)
59
+ name = "#{id}_#{Socket.gethostname}_#{Process.pid}_#{rand(1000000)}"
60
+ name = name.gsub('.', '_')
61
+ name = name.gsub('-', '_')
62
+ name.gsub(':', '_')
63
+ end
64
+
65
+
66
+ ##
67
+ # expand local, canonicalize, remappings
68
+ # @param [String] caller_id caller_id
69
+ # @param [String] ns namespace
70
+ # @param [String] name target name
71
+ # @param [Array] remappings name remappings
72
+ # @return [String] resolved name
73
+ def resolve_name_with_call_id(caller_id, ns, name, remappings)
74
+ name = canonicalize_name(expand_local_name(caller_id, name))
75
+ if remappings
76
+ remappings.each_pair do |key, value|
77
+ if name == canonicalize_name(key)
78
+ name = value
79
+ end
80
+ end
81
+ end
82
+ if ns
83
+ name = ns + SEP + name
84
+ end
85
+ return canonicalize_name(name)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,442 @@
1
+ # ros/node.rb
2
+ #
3
+ # License: BSD
4
+ #
5
+ # Copyright (C) 2012 Takashi Ogura <t.ogura@gmail.com>
6
+ #
7
+ # == ROS Node
8
+ #
9
+ # user interface of ROS.
10
+ #
11
+ require 'ros/parameter_manager'
12
+ require 'ros/name'
13
+ require 'ros/graph_manager'
14
+ require 'ros/publisher'
15
+ require 'ros/subscriber'
16
+ require 'ros/parameter_subscriber'
17
+ require 'ros/service_server'
18
+ require 'ros/service_client'
19
+ require 'ros/log'
20
+ require 'ros/time'
21
+ require 'ros/rate'
22
+ require 'ros/duration'
23
+
24
+ module ROS
25
+
26
+ # main interface of rosruby.
27
+ #
28
+ # @example Sample for Publisher
29
+ # node = ROS::Node.new('/rosruby/sample_publisher')
30
+ # publisher = node.advertise('/chatter', Std_msgs::String)
31
+ # sleep(1)
32
+ # msg = Std_msgs::String.new
33
+ # i = 0
34
+ # while node.ok?
35
+ # msg.data = "Hello, rosruby!: #{i}"
36
+ # publisher.publish(msg)
37
+ #
38
+ # @example Sample for Subscriber
39
+ # node = ROS::Node.new('/rosruby/sample_subscriber')
40
+ # node.subscribe('/chatter', Std_msgs::String) do |msg|
41
+ # puts "message come! = \'#{msg.data}\'"
42
+ # end
43
+ #
44
+ # while node.ok?
45
+ # node.spin_once
46
+ # sleep(1)
47
+ # end
48
+ #
49
+ class Node
50
+
51
+ # for node shutdown hook
52
+ @@shutdown_hook = []
53
+
54
+ # Naming functions of ROS
55
+ include Name
56
+
57
+ ##
58
+ # initialization of ROS node
59
+ # get env, parse args, and start slave xmlrpc servers.
60
+ #
61
+ # @param [String] node_name name of this node
62
+ # @param [Hash] options options
63
+ # @option options [Boolean] :anonymous (false) use anonymous name if true. anonymous node generates a unique name
64
+ def initialize(node_name, options={})
65
+ @remappings = {}
66
+ # @host is rewrited by ARGS[ROS_IP] or ARGS[ROS_HOSTNAME]
67
+ @host = Socket.gethostname
68
+ get_env
69
+ if options[:anonymous]
70
+ node_name = anonymous_name(node_name)
71
+ end
72
+ @node_name = resolve_name(node_name)
73
+ @remappings = parse_args(ARGV)
74
+ if not @master_uri
75
+ raise 'ROS_MASTER_URI is nos set. please check environment variables'
76
+ end
77
+
78
+ @manager = GraphManager.new(@node_name, @master_uri, @host)
79
+ @parameter = ParameterManager.new(@master_uri, @node_name, @remappings)
80
+ if not options[:nologger]
81
+ @logger = ::ROS::Log.new(self)
82
+ end
83
+ # because xmlrpc server use signal trap, after serve, it have to trap sig trap_signals
84
+ ObjectSpace.define_finalizer(self, proc {|id| self.shutdown})
85
+ end
86
+
87
+ ##
88
+ # Is this node running? Please use for 'while loop' and so on..
89
+ #
90
+ # @return [Boolean] true if node is running.
91
+ #
92
+ def ok?
93
+ @manager.is_ok?
94
+ end
95
+
96
+ # URI of master
97
+ # @return [String] uri string of master
98
+ attr_reader :master_uri
99
+
100
+ # hostname of this node.
101
+ # @return [String] host name
102
+ attr_reader :host
103
+
104
+ # name of this node (caller_id).
105
+ # @return [String] name of this node (=caller_id)
106
+ attr_reader :node_name
107
+
108
+ ##
109
+ # resolve the name by this node's remapping rule.
110
+ # @param [String] name name for resolved
111
+ # @return [String] resolved name
112
+ #
113
+ def resolve_name(name)
114
+ resolve_name_with_call_id(@node_name, @ns, name, @remappings)
115
+ end
116
+
117
+ ##
118
+ # get the param for key.
119
+ # You can set default value. That is uesed when the key is not set yet.
120
+ # @param [String] key key for search the parameters
121
+ # @param [String, Integer, Float, Boolean] default default value
122
+ # @return [String, Integer, Float, Boolean] parameter value for key
123
+ #
124
+ def get_param(key, default=nil)
125
+ key = expand_local_name(@node_name, key)
126
+ param = @parameter.get_param(key)
127
+ if param
128
+ param
129
+ else
130
+ default
131
+ end
132
+ end
133
+
134
+ ##
135
+ # get all parameters.
136
+ #
137
+ # @return [Array] all parameter list
138
+ #
139
+ def get_param_names
140
+ @parameter.get_param_names
141
+ end
142
+
143
+ ##
144
+ # check if the parameter server has the param for 'key'.
145
+ # @param [String] key key for check
146
+ # @return [Boolean] true if exits
147
+ def has_param(key)
148
+ @parameter.has_param(expand_local_name(@node_name, key))
149
+ end
150
+
151
+ ##
152
+ # delete the parameter for 'key'
153
+ #
154
+ # @param [String] key key for delete
155
+ # @return [Boolean] true if success, false if it is not exist
156
+ def delete_param(key)
157
+ @parameter.delete_param(expand_local_name(@node_name, key))
158
+ end
159
+
160
+ ##
161
+ # set parameter for 'key'.
162
+ # @param [String] key key of parameter
163
+ # @param [String, Integer, Float, Boolean] value value of parameter
164
+ # @return [Boolean] return true if succeed
165
+ def set_param(key, value)
166
+ @parameter.set_param(expand_local_name(@node_name, key), value)
167
+ end
168
+
169
+ ##
170
+ # start publishing the topic.
171
+ #
172
+ # @param [String] topic_name name of topic (string)
173
+ # @param [Class] topic_type topic class
174
+ # @param [Hash] options :latched, :resolve
175
+ # @option options [Boolean] :latched (false) latched topic
176
+ # @option options [Boolean] :resolve (true) resolve topic_name or not. This is for publish /rosout with namespaced node.
177
+ # @return [Publisher] Publisher instance
178
+ def advertise(topic_name, topic_type, options={})
179
+ if options[:no_resolve]
180
+ name = topic_name
181
+ else
182
+ name = resolve_name(topic_name)
183
+ end
184
+ publisher = Publisher.new(@node_name,
185
+ name,
186
+ topic_type,
187
+ options[:latched],
188
+ @manager.host)
189
+ @manager.add_publisher(publisher)
190
+ trap_signals
191
+ publisher
192
+ end
193
+
194
+ ##
195
+ # start service server.
196
+ #
197
+ # @param [String] service_name name of this service (string)
198
+ # @param [Service] service_type service class
199
+ # @param [Proc] callback service definition
200
+ # @return [ServiceServer] ServiceServer instance
201
+ def advertise_service(service_name, service_type, &callback)
202
+ server = ::ROS::ServiceServer.new(@node_name,
203
+ resolve_name(service_name),
204
+ service_type,
205
+ callback)
206
+ @manager.add_service_server(server)
207
+ trap_signals
208
+ server
209
+ end
210
+
211
+ ##
212
+ # wait until start the service.
213
+ # @param [String] service_name name of service for waiting
214
+ # @param [Float] timeout_sec time out seconds. default infinity.
215
+ # @return [Boolean] true if success, false if timeouted
216
+ def wait_for_service(service_name, timeout_sec=nil)
217
+ @manager.wait_for_service(service_name, timeout_sec)
218
+ end
219
+
220
+ ##
221
+ # create service client.
222
+ # @param [String] service_name name of this service (string)
223
+ # @param [Class] service_type service class
224
+ # @return [ServiceClient] created ServiceClient instance
225
+ def service(service_name, service_type)
226
+ ROS::ServiceClient.new(@master_uri,
227
+ @node_name,
228
+ resolve_name(service_name),
229
+ service_type)
230
+ end
231
+
232
+ ##
233
+ # start to subscribe a topic.
234
+ #
235
+ # @param [String] topic_name name of topic (string)
236
+ # @param [Class] topic_type Topic instance
237
+ # @return [Subscriber] created Subscriber instance
238
+ def subscribe(topic_name, topic_type, &callback)
239
+ sub = Subscriber.new(@node_name,
240
+ resolve_name(topic_name),
241
+ topic_type,
242
+ callback)
243
+ @manager.add_subscriber(sub)
244
+ trap_signals
245
+ sub
246
+ end
247
+
248
+ ##
249
+ # subscribe to the parameter.
250
+ #
251
+ # @param [String] param name of parameter to subscribe
252
+ # @param [Proc] callback callback when parameter updated
253
+ # @return [ParameterSubscriber] created ParameterSubscriber instance
254
+ def subscribe_parameter(param, &callback)
255
+ sub = ParameterSubscriber.new(param, callback)
256
+ @manager.add_parameter_subscriber(sub)
257
+ sub
258
+ end
259
+
260
+ ##
261
+ # spin once. This invoke subscription/service_server callbacks
262
+ #
263
+ def spin_once
264
+ @manager.spin_once
265
+ end
266
+
267
+ ##
268
+ # spin forever.
269
+ #
270
+ def spin
271
+ while ok?
272
+ spin_once
273
+ sleep(0.01)
274
+ end
275
+ end
276
+
277
+ ##
278
+ # unregister to master and shutdown all connections.
279
+ # @return [Node] self
280
+ def shutdown
281
+ if ok?
282
+ begin
283
+ @manager.shutdown
284
+ rescue => message
285
+ p message
286
+ puts 'ignoring errors while shutdown'
287
+ end
288
+ end
289
+ self
290
+ end
291
+
292
+ ##
293
+ # outputs log message for INFO (INFORMATION).
294
+ # @param [String] message message for output
295
+ # @return [Node] self
296
+ def loginfo(message)
297
+ file, line, function = caller[0].split(':')
298
+ @logger.log('INFO', message, file, function, line.to_i)
299
+ self
300
+ end
301
+
302
+ ##
303
+ # outputs log message for DEBUG
304
+ # @param [String] message message for output
305
+ # @return [Node] self
306
+ def logdebug(message)
307
+ file, line, function = caller[0].split(':')
308
+ @logger.log('DEBUG', message, file, function, line.to_i)
309
+ self
310
+ end
311
+
312
+ ##
313
+ # outputs log message for WARN (WARING).
314
+ #
315
+ # @param [String] message message for output
316
+ # @return [Node] self
317
+ def logwarn(message)
318
+ file, line, function = caller[0].split(':')
319
+ @logger.log('WARN', message, file, function, line.to_i)
320
+ self
321
+ end
322
+
323
+ ##
324
+ # outputs log message for ERROR.
325
+ #
326
+ # @param [String] message message for output
327
+ # @return [Node] self
328
+ def logerror(message)
329
+ file, line, function = caller[0].split(':')
330
+ @logger.log('ERROR', message, file, function, line.to_i)
331
+ self
332
+ end
333
+
334
+ alias_method :logerr, :logerror
335
+
336
+ ##
337
+ # outputs log message for FATAL.
338
+ #
339
+ # @param [String] message message for output
340
+ # @return [Node] self
341
+ def logfatal(message)
342
+ file, line, function = caller[0].split(':')
343
+ @logger.log('FATAL', message, file, function, line.to_i)
344
+ self
345
+ end
346
+
347
+ ##
348
+ # get all topics by this node.
349
+ #
350
+ # @return [Array] topic names
351
+ def get_published_topics
352
+ @manager.publishers.map do |pub|
353
+ pub.topic_name
354
+ end
355
+ end
356
+
357
+ private
358
+
359
+ ##
360
+ # parse all environment variables.
361
+ #
362
+ def get_env #:nodoc:
363
+ @master_uri = ENV['ROS_MASTER_URI']
364
+ @ns = ENV['ROS_NAMESPACE']
365
+ if ENV['ROS_IP']
366
+ @host = ENV['ROS_IP']
367
+ elsif ENV['ROS_HOSTNAME']
368
+ @host = ENV['ROS_HOSTNAME']
369
+ end
370
+ end
371
+
372
+ ##
373
+ # converts strings if it is float and int numbers.
374
+ # @example
375
+ # convert_if_needed('10') # => 10
376
+ # convert_if_needed('0.1') # => 0.1
377
+ # convert_if_needed('string') # => 'string'
378
+ # @param [String] value string
379
+ # @return [Float, Integer, String] return converted value.
380
+ def convert_if_needed(value) #:nodoc:
381
+ if value =~ /^[+-]?\d+\.?\d*$/ # float
382
+ value = value.to_f
383
+ elsif value =~ /^[+-]?\d+$/ # int
384
+ value = value.to_i
385
+ else
386
+ value
387
+ end
388
+ end
389
+
390
+ ##
391
+ # parse all args.
392
+ # @param [Array] args arguments for parse
393
+ def parse_args(args) #:nodoc:
394
+ remapping = {}
395
+ for arg in args
396
+ splited = arg.split(':=')
397
+ if splited.length == 2
398
+ key, value = splited
399
+ if key == '__name'
400
+ @node_name = resolve_name(value)
401
+ elsif key == '__ip'
402
+ @host = value
403
+ elsif key == '__hostname'
404
+ @host = value
405
+ elsif key == '__master'
406
+ @master_uri = value
407
+ elsif key == '__ns'
408
+ @ns = value
409
+ elsif key[0] == '_'[0]
410
+ # local name remaps
411
+ key[0] = '~'
412
+ remapping[resolve_name(key)] = convert_if_needed(value)
413
+ else
414
+ # remaps
415
+ remapping[key] = convert_if_needed(value)
416
+ end
417
+ end
418
+ end
419
+ remapping
420
+ end
421
+
422
+ # trap signals for safe shutdown.
423
+ def trap_signals #:nodoc:
424
+ ["INT", "TERM", "HUP"].each do |signal|
425
+ Signal.trap(signal) do
426
+ ROS::Node.shutdown_all_nodes
427
+ end
428
+ end
429
+ end
430
+
431
+ def self.add_shutdown_hook(proc)
432
+ @@shutdown_hook.push(proc)
433
+ end
434
+
435
+ # shutdown all nodes.
436
+ def self.shutdown_all_nodes
437
+ GraphManager.shutdown_all
438
+ @@shutdown_hook.each {|obj| obj.call}
439
+ end
440
+
441
+ end
442
+ end