Skip to content

Commit e6acfb2

Browse files
authored
Merge pull request #37 from JuliaRobotics/feature/tagsonls
ls getVarIds now search tags too
2 parents 8878102 + 41fd5ea commit e6acfb2

File tree

3 files changed

+101
-4
lines changed

3 files changed

+101
-4
lines changed

src/Common.jl

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
2+
export sortVarNested
3+
4+
"""
5+
$(SIGNATURES)
6+
Test if all elements of the string is a number: Ex, "123" is true, "1_2" is false.
7+
"""
8+
allnums(str::S) where {S <: AbstractString} = occursin(Regex(string(["[0-9]" for j in 1:length(str)]...)), str)
9+
# occursin(r"_+|,+|-+", node_idx)
10+
11+
isnestednum(str::S; delim='_') where {S <: AbstractString} = occursin(Regex("[0-9]+$(delim)[0-9]+"), str)
12+
13+
function sortnestedperm(strs::Vector{<:AbstractString}; delim='_')
14+
str12 = split.(strs, delim)
15+
sp1 = sortperm(parse.(Int,getindex.(str12,2)))
16+
sp2 = sortperm(parse.(Int,getindex.(str12,1)[sp1]))
17+
return sp1[sp2]
18+
end
19+
20+
function getFirstNumericalOffset(st::AS) where AS <: AbstractString
21+
i = 1
22+
while !allnums(st[i:i]) i+=1; end
23+
return i
24+
end
25+
26+
"""
27+
$SIGNATURES
28+
29+
Sort a variable list which may have nested structure such as `:x1_2` -- does not sort for alphabetic characters.
30+
"""
31+
function sortVarNested(vars::Vector{Symbol})::Vector{Symbol}
32+
# whos nested and first numeric character offset
33+
sv = string.(vars)
34+
offsets = getFirstNumericalOffset.(sv)
35+
masknested = isnestednum.(sv)
36+
masknotnested = true .⊻ masknested
37+
38+
# strip alphabetic characters from front
39+
msv = sv[masknotnested]
40+
msvO = offsets[masknotnested]
41+
nsv = sv[masknested]
42+
nsvO = offsets[masknested]
43+
44+
# do nonnested list separately
45+
nnreducelist = map((s,o) -> s[o:end], msv, msvO)
46+
nnintlist = parse.(Int, nnreducelist)
47+
nnp = sortperm(nnintlist)
48+
nnNums = nnintlist[nnp] # used in mixing later
49+
nonnested = msv[nnp]
50+
smsv = vars[masknotnested][nnp]
51+
52+
# do nested list separately
53+
nestedreducelist = map((s,o) -> s[o:end], nsv, nsvO)
54+
nestedp = sortnestedperm(nestedreducelist)
55+
nesNums = parse.(Int, getindex.(split.(nestedreducelist[nestedp], '_'),1)) # used in mixing later
56+
nested = nsv[nestedp]
57+
snsv = vars[masknested][nestedp]
58+
59+
# mix back together, pick next sorted item from either pile
60+
retvars = Vector{Symbol}(undef, length(vars))
61+
nni = 1
62+
nesi = 1
63+
lsmsv = length(smsv)
64+
lsnsv = length(snsv)
65+
MAXMAX = 999999999999
66+
for i in 1:length(vars)
67+
# inner ifs to ensure bounds and correct sorting at end of each list
68+
if (nni<=lsmsv ? nnNums[nni] : MAXMAX) <= (nesi<=lsnsv ? nesNums[nesi] : MAXMAX)
69+
retvars[i] = smsv[nni]
70+
nni += 1
71+
else
72+
retvars[i] = snsv[nesi]
73+
nesi += 1
74+
end
75+
end
76+
return retvars
77+
end

src/DistributedFactorGraphs.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ include("services/AbstractDFG.jl")
3232
include("services/DFGVariable.jl")
3333

3434
# not sure where to put
35+
include("Common.jl")
3536
include("NeedsAHome.jl")
3637

3738
end

src/services/GraphsDFG.jl

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,16 @@ deleteFactor!(dfg::GraphsDFG, factor::DFGFactor)::DFGFactor = deleteFactor!(dfg,
273273
List the DFGVariables in the DFG.
274274
Optionally specify a label regular expression to retrieves a subset of the variables.
275275
"""
276-
function ls(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing)::Vector{DFGVariable}
276+
function ls(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{DFGVariable}
277277
variables = map(v -> v.dfgNode, filter(n -> n.dfgNode isa DFGVariable, vertices(dfg.g)))
278278
if regexFilter != nothing
279279
variables = filter(v -> occursin(regexFilter, String(v.label)), variables)
280280
end
281-
return variables
281+
if length(tags) > 0
282+
mask = map(v -> length(intersect(v.tags, tags)) > 0, variables )
283+
return variables[mask]
284+
end
285+
return variables
282286
end
283287

284288
# Alias
@@ -287,14 +291,28 @@ end
287291
List the DFGVariables in the DFG.
288292
Optionally specify a label regular expression to retrieves a subset of the variables.
289293
"""
290-
getVariables(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing)::Vector{DFGVariable} = ls(dfg, regexFilter)
294+
getVariables(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{DFGVariable} = ls(dfg, regexFilter, tags=tags)
291295

292296
"""
293297
$(SIGNATURES)
294298
Get a list of IDs of the DFGVariables in the DFG.
295299
Optionally specify a label regular expression to retrieves a subset of the variables.
300+
301+
Example
302+
```julia
303+
getVariableIds(dfg, r"l", tags=[:APRILTAG;])
304+
```
305+
306+
Related
307+
308+
ls
296309
"""
297-
getVariableIds(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing)::Vector{Symbol} = map(v -> v.label, ls(dfg, regexFilter))
310+
function getVariableIds(dfg::GraphsDFG, regexFilter::Union{Nothing, Regex}=nothing; tags::Vector{Symbol}=Symbol[])::Vector{Symbol}
311+
vars = ls(dfg, regexFilter, tags=tags)
312+
# mask = map(v -> length(intersect(v.tags, tags)) > 0, vars )
313+
map(v -> v.label, vars)
314+
end
315+
298316

299317
"""
300318
$(SIGNATURES)
@@ -342,6 +360,7 @@ Checks if the graph is not fully connected, returns true if it is not contiguous
342360
"""
343361
hasOrphans(dfg::GraphsDFG)::Bool = !isFullyConnected(dfg)
344362

363+
345364
"""
346365
$(SIGNATURES)
347366
Retrieve a list of labels of the immediate neighbors around a given variable or factor.

0 commit comments

Comments
 (0)