59from . inputs
import AppSource, BagSource, LiveSource, Source
60from . outputs
import AppSink, BagSink, ConsoleSink, LiveSink, MultiSink, Sink
70def grep(args=None, **kwargs):
72 Yields matching messages from specified source.
74 Initializes grepros if not already initialized.
76 Read from bagfiles: `grep(file="2022-10-*.bag", pattern="cpu")`.
78 Read from live topics: `grep(live=True, pattern="cpu")`.
81 @param args arguments as namespace or dictionary, case-insensitive;
82 or a single path as the ROS bagfile to read,
83 or one or more {@link grepros.api.Bag Bag} instances,
84 or a {@link grepros.inputs.Source Source} instance
85 @param kwargs any and all arguments as keyword overrides, case-insensitive
89 @param args.file names of ROS bagfiles to read if not all in directory
90 @param args.path paths to scan if not current directory
91 @param args.recurse recurse into subdirectories when looking for bagfiles
92 @param args.decompress decompress archived bags to file directory
93 @param args.reindex make a copy of unindexed bags and reindex them (ROS1 only)
94 @param args.orderby "topic" or "type" if any to group results by
95 @param args.timescale emit messages on original timeline from first message
96 at given rate, 0 disables
97 @param args.timescale_emission start timeline from first matched message not first in bag
98 @param args.bag one or more {@link grepros.api.Bag Bag} instances
102 @param args.live whether reading messages from live ROS topics
103 @param args.queue_size_in subscriber queue size (default 10)
104 @param args.ros_time_in stamp messages with ROS time instead of wall time
108 @param args.app whether reading messages from iterable or pushed data;
109 may contain the iterable itself
110 @param args.iterable iterable yielding (topic, msg, stamp) or (topic, msg);
111 yielding `None` signals end of content
113 @param args.topic ROS topics to read if not all
114 @param args.type ROS message types to read if not all
115 @param args.skip_topic ROS topics to skip
116 @param args.skip_type ROS message types to skip
117 @param args.start_time earliest timestamp of messages to read
118 @param args.end_time latest timestamp of messages to read
119 @param args.start_index message index within topic to start from
120 @param args.end_index message index within topic to stop at
122 @param args.nth_message read every Nth message in topic, starting from first
123 @param args.nth_interval minimum time interval between messages in topic,
124 as seconds or ROS duration
126 @param args.select_field message fields to use in matching if not all
127 @param args.noselect_field message fields to skip in matching
129 @param args.unique emit messages that are unique in topic
130 (select_field and noselect_field apply if specified)
131 @param args.condition Python expressions that must evaluate as true
132 for message to be processable, see ConditionMixin
136 @param args.pattern pattern(s) to find in message field values
137 @param args.fixed_string pattern contains ordinary strings, not regular expressions
138 @param args.case use case-sensitive matching in pattern
139 @param args.invert select messages not matching pattern
140 @param args.expression pattern(s) are a logical expression
141 like 'this AND (this2 OR NOT "skip this")',
142 with elements as patterns to find in message fields
144 @param args.nth_match emit every Nth match in topic, starting from first
145 @param args.max_count number of matched messages to emit (per file if bag input)
146 @param args.max_per_topic number of matched messages to emit from each topic
147 @param args.max_topics number of topics to print matches from
149 @param args.before number of messages of leading context to emit before match
150 @param args.after number of messages of trailing context to emit after match
151 @param args.context number of messages of leading and trailing context
154 @param args.highlight highlight matched values
155 @param args.match_wrapper string to wrap around matched values,
156 both sides if one value, start and end if more than one,
157 or no wrapping if zero values
159 @return {@link grepros.Scanner.GrepMessage GrepMessage} namedtuples
160 of (topic, message, timestamp, match, index)
162 DEFAULT_ARGS = dict(FILE=[], LIVE=
False, APP=
False, ITERABLE=
None,
163 COLOR=
"never", HIGHLIGHT=
False)
166 is_bag = isinstance(args, Bag)
or \
167 common.is_iterable(args)
and all(isinstance(x, Bag)
for x
in args)
168 args = {
"FILE": str(args)}
if isinstance(args, common.PATH_TYPES)
else \
169 {}
if is_bag
or isinstance(args, Source)
else args
170 args = common.ArgumentUtil.validate(common.ensure_namespace(args, DEFAULT_ARGS, **kwargs))
171 if not _inited:
init(args)
173 if common.is_iterable(args.APP)
and not common.is_iterable(args.ITERABLE):
174 args.APP, args.ITERABLE =
True, args.APP
175 src = args0
if isinstance(args0, Source)
else \
179 if args
and isinstance(args0, Source): src.configure(**kwargs)
183 for x
in Scanner(args).find(src):
yield x
185 if not isinstance(args0, (Bag, Source)): src.close()
190 Convenience for creating a {@link grepros.inputs.Source Source} instance from arguments.
192 Initializes grepros if not already initialized.
194 @param args arguments as namespace or dictionary, case-insensitive;
195 or a single path as the ROS bagfile to read
196 @param kwargs any and all arguments as keyword overrides, case-insensitive
197 @param args.file one or more names of ROS bagfiles to read from
198 @param args.live read messages from live ROS topics instead
199 @param args.app read messages from iterable or pushed data instead;
200 may contain the iterable itself
204 @param args.file names of ROS bagfiles to read if not all in directory
205 @param args.path paths to scan if not current directory
206 @param args.recurse recurse into subdirectories when looking for bagfiles
207 @param args.orderby "topic" or "type" if any to group results by
208 @param args.decompress decompress archived bags to file directory
209 @param args.reindex make a copy of unindexed bags and reindex them (ROS1 only)
210 @param args.timescale emit messages on original timeline from first message
211 at given rate, 0 disables
212 @param args.timescale_emission start timeline from first matched message not first in bag
213 @param args.progress whether to print progress bar
217 @param args.queue_size_in subscriber queue size (default 10)
218 @param args.ros_time_in stamp messages with ROS time instead of wall time
219 @param args.progress whether to print progress bar
223 @param args.iterable iterable yielding (topic, msg, stamp) or (topic, msg);
224 yielding `None` signals end of content
228 @param args.topic ROS topics to read if not all
229 @param args.type ROS message types to read if not all
230 @param args.skip_topic ROS topics to skip
231 @param args.skip_type ROS message types to skip
232 @param args.start_time earliest timestamp of messages to read
233 @param args.end_time latest timestamp of messages to read
234 @param args.start_index message index within topic to start from
235 @param args.end_index message index within topic to stop at
236 @param args.unique emit messages that are unique in topic
237 @param args.select_field message fields to use for uniqueness if not all
238 @param args.noselect_field message fields to skip for uniqueness
239 @param args.nth_message read every Nth message in topic, starting from first
240 @param args.nth_interval minimum time interval between messages in topic,
241 as seconds or ROS duration
242 @param args.condition Python expressions that must evaluate as true
243 for message to be processable, see ConditionMixin
245 DEFAULT_ARGS = dict(FILE=[], LIVE=
False, APP=
False, ITERABLE=
None)
246 args = {
"FILE": str(args)}
if isinstance(args, common.PATH_TYPES)
else args
247 args = common.ensure_namespace(args, DEFAULT_ARGS, **kwargs)
248 if not _inited:
init(args)
250 if common.is_iterable(args.APP)
and not common.is_iterable(args.ITERABLE):
251 args.APP, args.ITERABLE =
True, args.APP
252 result = (LiveSource
if args.LIVE
else AppSource
if args.APP
else BagSource)(args)
259 Convenience for creating a {@link grepros.outputs.Sink Sink} instance from arguments,
260 {@link grepros.outputs.MultiSink MultiSink} if several outputs.
262 Initializes grepros if not already initialized.
264 @param args arguments as namespace or dictionary, case-insensitive;
265 or a single item as sink target like bag filename
266 @param kwargs any and all arguments as keyword overrides, case-insensitive
267 @param args.app provide messages to given callback function
268 @param args.console print matches to console
269 @param args.publish publish matches to live topics
270 @param args.write file or other target like Postgres database to write,
271 as "target", or ["target", dict(format="format", ..)]
272 or [[..target1..], [..target2..], ..]
273 @param args.write_options format-specific options like
274 {"overwrite": whether to overwrite existing file
279 @param args.line_prefix print source prefix like bag filename on each message line
280 @param args.max_field_lines maximum number of lines to print per field
281 @param args.start_line message line number to start output from
282 @param args.end_line message line number to stop output at
283 @param args.max_message_lines maximum number of lines to output per message
284 @param args.lines_around_match number of message lines around matched fields to output
285 @param args.matched_fields_only output only the fields where match was found
286 @param args.wrap_width character width to wrap message YAML output at
287 @param args.match_wrapper string to wrap around matched values,
288 both sides if one value, start and end if more than one,
289 or no wrapping if zero values
293 @param args.color False or "never" for not using colors in replacements
294 @param args.highlight highlight matched values (default true)
295 @param args.emit_field message fields to emit if not all
296 @param args.noemit_field message fields to skip in output
297 @param args.max_field_lines maximum number of lines to output per field
298 @param args.start_line message line number to start output from
299 @param args.end_line message line number to stop output at
300 @param args.max_message_lines maximum number of lines to output per message
301 @param args.lines_around_match number of message lines around matched fields to output
302 @param args.matched_fields_only output only the fields where match was found
303 @param args.wrap_width character width to wrap message YAML output at
304 @param args.match_wrapper string to wrap around matched values,
305 both sides if one value, start and end if more than one,
306 or no wrapping if zero values
310 @param args.queue_size_out publisher queue size (default 10)
311 @param args.publish_prefix output topic prefix, prepended to input topic
312 @param args.publish_suffix output topic suffix, appended to output topic
313 @param args.publish_fixname single output topic name to publish to,
314 overrides prefix and suffix if given
318 @param args.emit callback(topic, msg, stamp, highlighted msg, index in topic)
320 @param args.metaemit callback(metadata dict) if any,
321 invoked before first emit from source batch
325 @param args.meta whether to print metainfo
326 @param args.verbose whether to print debug information
328 DEFAULT_ARGS = dict(CONSOLE=
False, PUBLISH=
False, WRITE=[], APP=
False, EMIT=
None, METAEMIT=
None)
331 args = {
"WRITE": str(args)}
if isinstance(args, common.PATH_TYPES)
else args
332 args = common.ensure_namespace(args, DEFAULT_ARGS, **kwargs)
333 if not _inited:
init(args)
336 if isinstance(args.WRITE, common.PATH_TYPES):
337 args.WRITE = [[args.WRITE]]
338 elif isinstance(args.WRITE, (list, tuple))
and isinstance(args.WRITE[0], common.PATH_TYPES):
339 args.WRITE = [args.WRITE]
340 if callable(args.APP)
and not callable(args.EMIT): args.APP, args.EMIT =
True, args.APP
344 result = multisink.sinks[0]
if len(multisink.sinks) == 1
else multisink
350 Initializes ROS version bindings, loads all built-in plugins if dependencies available.
353 @param args.plugin one or more extra plugins to load,
354 as full names or instances of Python module/class
355 @param kwargs any and all arguments as keyword overrides, case-insensitive
358 args = common.ensure_namespace(args, {
"PLUGIN": []}, **kwargs)
360 if args: plugins.configure(args)
363 common.ConsolePrinter.configure(color=
None, apimode=
True)
366 for x
in (plugins.mcap, plugins.parquet, plugins.sql):
367 try: plugins.configure(PLUGIN=x)
368 except Exception:
pass
369 Bag.READER_CLASSES.add(McapBag)
370 Bag.WRITER_CLASSES.add(McapBag)
371 if args.PLUGIN: plugins.configure(args)
373 api.TypeMeta.LIFETIME, api.TypeMeta.POPULATION = 0, 100