Skip to content

Commit

Permalink
Merge pull request #48 from schmrlng/0.7
Browse files Browse the repository at this point in the history
Updates for Julia 0.7, dropping 0.6 support
  • Loading branch information
jdlangs authored Oct 7, 2018
2 parents 3b123e3 + a5cb6ca commit 30bcd49
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 63 deletions.
20 changes: 16 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
language: julia
julia:
- 0.6
- 0.7
- 1.0
- nightly
sudo: required
dist: trusty
env:
global:
- PYTHON=python
before_install:
- sudo apt-add-repository -y "deb http://packages.ros.org/ros/ubuntu trusty main"
- wget https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -O - | sudo apt-key add -
Expand All @@ -19,10 +23,18 @@ before_script:
- python test/echonode.py &
- sleep 5
after_success:
- julia -e 'cd(Pkg.dir("RobotOS")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
- julia -e 'Pkg.add("Documenter");'
- julia -e 'cd(Pkg.dir("RobotOS")); ENV["DOCUMENTER_DEBUG"]="true"; include(joinpath("docs", "make.jl"))'
- julia --project -e 'import Pkg; Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
after_script:
- killall roscore
- killall python
- sleep 5
jobs:
include:
- stage: "Documentation"
julia: 1.0
os: linux
script:
- julia --project=docs/ -e 'using Pkg; Pkg.instantiate();
Pkg.add(PackageSpec(path=pwd()))'
- julia --project=docs/ docs/make.jl
after_success: skip
5 changes: 2 additions & 3 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
julia 0.6
PyCall 1.11.0
Compat 0.34.0
julia 0.7
PyCall 1.17.1
5 changes: 5 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"

[compat]
Documenter = "~0.19"
2 changes: 1 addition & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ deploydocs(
branch = "gh-pages",
latest = "master",
osname="linux",
julia="0.6",
julia="1.0",
deps=Deps.pip("mkdocs"),
)
3 changes: 1 addition & 2 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,12 @@ load-time latency (useful for real-life applications!) by generating the ROS typ
modules inside your package module using an approach similar to the example below:

# MyROSPackage.jl
__precompile__()
module MyROSPackage

using RobotOS

@rosimport geometry_msgs.msg: Pose
rostypegen(current_module())
rostypegen(@__MODULE__)
import .geometry_msgs.msg: Pose
# ...

Expand Down
22 changes: 10 additions & 12 deletions src/RobotOS.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
isdefined(Base, :__precompile__) && __precompile__()

module RobotOS

using PyCall
Expand All @@ -9,14 +7,22 @@ const _py_sys = PyCall.PyNULL()
const _py_ros_callbacks = PyCall.PyNULL()
const __rospy__ = PyCall.PyNULL()

include("debug.jl")
include("time.jl")
include("gentypes.jl")
include("rospy.jl")
include("pubsub.jl")
include("services.jl")
include("callbacks.jl")

function __init__()
#Put julia's ARGS into python's so remappings will work
copy!(_py_sys, pyimport("sys"))
_py_sys["argv"] = ARGS

#Fill in empty PyObjects
if ! (dirname(@__FILE__) in _py_sys["path"])
unshift!(_py_sys["path"], dirname(@__FILE__))
pushfirst!(_py_sys["path"], dirname(@__FILE__))
end
copy!(_py_ros_callbacks, pyimport("ros_callbacks"))

Expand All @@ -32,15 +38,7 @@ function __init__()
end

#Compile the callback notify function, see callbacks.jl
CB_NOTIFY_PTR[] = cfunction(_callback_notify, Cint, Tuple{Ptr{Void}})
CB_NOTIFY_PTR[] = @cfunction(_callback_notify, Cint, (Ptr{Cvoid},))
end

include("debug.jl")
include("time.jl")
include("gentypes.jl")
include("rospy.jl")
include("pubsub.jl")
include("services.jl")
include("callbacks.jl")

end
6 changes: 3 additions & 3 deletions src/callbacks.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#This function will run in a new python thread created by rospy.
#No julia allocation allowed.
function _callback_notify(handle::Ptr{Void})
ccall(:uv_async_send, Cint, (Ptr{Void},), handle)
function _callback_notify(handle::Ptr{Cvoid})
ccall(:uv_async_send, Cint, (Ptr{Cvoid},), handle)
end

#The pointer to the compiled notify function. This can't be precompiled so it gets initialized in
#the module __init__ function.
const CB_NOTIFY_PTR = Ref{Ptr{Void}}()
const CB_NOTIFY_PTR = Ref{Ptr{Cvoid}}()

function _callback_async_loop(rosobj, cond)
@debug("Spinning up callback loop...")
Expand Down
67 changes: 33 additions & 34 deletions src/gentypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ abstract type AbstractMsg end
abstract type AbstractSrv end
abstract type AbstractService end

_is_tuple_expr(input) = input isa Expr && input.head == :tuple
_is_colon_expr(input) = input isa Expr && input.head == :call && input.args[1] == :(:)
_is_dot_expr(input) = input isa Expr && input.head == :(.)

"""
@rosimport
Expand All @@ -81,13 +85,11 @@ macro rosimport(input)
#Rearranges the expression into a RobotOS._rosimport call. Input comes in as a single package
#qualified expression, or as a tuple expression where the first element is the same as the
#single expression case. Most of the code is just error checking that the input takes that form.
@assert input.head in [:tuple, :(.), :(:)] "Improper @rosimport input"
if input.head == :tuple
@assert isa(input.args[1], Expr) "Improper @rosimport input"
@assert input.args[1].head == :(:) "First argument needs ':' following"
types = String[]
@assert _is_tuple_expr(input) || _is_colon_expr(input) || _is_dot_expr(input) "Improper @rosimport input"
if _is_tuple_expr(input)
@assert _is_colon_expr(input.args[1]) "Improper @rosimport input, first argument needs ':' following"
pkg, ismsg, typ = _pkgtype_import(input.args[1])
push!(types, typ)
types = String[typ]
for t in input.args[2:end]
@assert isa(t, Symbol) "Type name ($(string(t))) not a symbol"
push!(types, string(t))
Expand All @@ -98,32 +100,29 @@ macro rosimport(input)
return :(_rosimport($pkg, $ismsg, $typ))
end
end

_get_quote_value(input::QuoteNode) = input.value
_get_quote_value(input::Expr) = (@assert input.head == :quote; input.args[1])

#Return the pkg and types strings for a single expression of form:
# pkg.[msg|srv].type or pkg.[msg|srv]:type
function _pkgtype_import(input::Expr)
@assert input.head in (:(.), :(:)) "Improper @rosimport input"
@assert isa(input.args[1], Expr) "Improper @rosimport input"
@assert input.args[1].head == :(.) "Improper @rosimport input"
p = input.args[1].args[1]
@assert _is_colon_expr(input) || _is_dot_expr(input) "Improper @rosimport input"
p_ms, t = _is_colon_expr(input) ? (input.args[2], input.args[3]) : (input.args[1], input.args[2])
@assert _is_dot_expr(p_ms) "Improper @rosimport input"
p = p_ms.args[1]
@assert isa(p, Symbol) "Package name ($(string(p))) not a symbol"
m_or_s = _get_quote_value(input.args[1].args[2])
@assert isa(p_ms.args[2], QuoteNode) "Improper @rosimport input"
m_or_s = p_ms.args[2].value
@assert m_or_s in (:msg,:srv) "Improper @rosimport input"
ps = string(p)
msb = m_or_s == :msg
ts = ""
if isa(input.args[2], Symbol)
ts = string(input.args[2])
elseif isa(input.args[2], Expr)
@assert length(input.args[2].args) == 1 "Type name not a symbol"
tsym = input.args[2].args[1]
if isa(t, Symbol)
ts = string(t)
elseif isa(t, Expr)
@assert length(t.args) == 1 "Type name ($(t)) not a symbol"
tsym = t.args[1]
@assert isa(tsym, Symbol) "Type name ($(string(tsym))) not a symbol"
ts = string(tsym)
elseif isa(input.args[2], QuoteNode)
tsym = input.args[2].value
elseif isa(t, QuoteNode)
tsym = t.value
@assert isa(tsym, Symbol) "Type name ($(string(tsym))) not a symbol"
ts = string(tsym)
end
Expand Down Expand Up @@ -179,8 +178,8 @@ function addtype!(mod::ROSMsgModule, typ::String)
if !(typ in mod.members)
@debug("Message type import: ", _fullname(mod), ".", typ)
if _nameconflicts(typ)
warn("Message type '$typ' conflicts with Julia builtin, ",
"will be imported as '$(_jl_safe_name(typ,"Msg"))'")
@warn("Message type '$typ' conflicts with Julia builtin, " *
"will be imported as '$(_jl_safe_name(typ,"Msg"))'")
end
pymod, pyobj = _pyvars(_fullname(mod), typ)

Expand Down Expand Up @@ -350,19 +349,19 @@ end

#The imports specific to each module, including dependant packages
function _importexprs(mod::ROSMsgModule, rosrootmod::Module)
imports = Expr[Expr(:import, :RobotOS, :AbstractMsg)]
imports = Expr[:(import RobotOS.AbstractMsg)]
othermods = filter(d -> d != _name(mod), mod.deps)
append!(imports, [Expr(:using,fullname(rosrootmod)...,Symbol(m),:msg) for m in othermods])
append!(imports, [Expr(:using, Expr(:., fullname(rosrootmod)..., Symbol(m), :msg)) for m in othermods])
imports
end
function _importexprs(mod::ROSSrvModule, rosrootmod::Module)
imports = Expr[
Expr(:import, :RobotOS, :AbstractSrv),
Expr(:import, :RobotOS, :AbstractService),
Expr(:import, :RobotOS, :_srv_reqtype),
Expr(:import, :RobotOS, :_srv_resptype),
:(import RobotOS.AbstractSrv),
:(import RobotOS.AbstractService),
:(import RobotOS._srv_reqtype),
:(import RobotOS._srv_resptype)
]
append!(imports, [Expr(:using,fullname(rosrootmod)...,Symbol(m),:msg) for m in mod.deps])
append!(imports, [Expr(:using, Expr(:., fullname(rosrootmod)..., Symbol(m), :msg)) for m in mod.deps])
imports
end

Expand Down Expand Up @@ -513,8 +512,8 @@ function _addtypemember!(exprs, namestr, typestr)
jlconargs = exprs[4].args[2].args

if typestr == "char" || typestr == "byte"
warn("Use of type '$typestr' is deprecated in message definitions, ",
"use '$(lowercase(string(_ros_builtin_types[typestr])))' instead.")
@warn("Use of type '$typestr' is deprecated in message definitions, " *
"use '$(lowercase(string(_ros_builtin_types[typestr])))' instead.")
end

typestr, arraylen = _check_array_type(typestr)
Expand Down Expand Up @@ -609,7 +608,7 @@ function _splittypestr(typestr::String)
end
#Valid ROS type string is all word chars split by a single forward slash, with
#optional square brackets for array types
_isrostype(s::String) = ismatch(r"^\w+/\w+(?:\[\d*\])?$", s)
_isrostype(s::String) = occursin(r"^\w+/\w+(?:\[\d*\])?$", s)

#Sanitize a string by checking for and removing brackets if they are present
#Return the sanitized type and the number inside the brackets if it is a fixed
Expand Down
2 changes: 1 addition & 1 deletion test/pubsub.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ using .geometry_msgs.msg
const Nmsgs = 10
const rate = 20. #Hz
const msgs = PoseStamped[]
const refs = Array{Vector3}(Nmsgs)
const refs = Array{Vector3}(undef, Nmsgs)
const t0 = to_nsec(get_rostime())

for i=1:Nmsgs
Expand Down
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Compat.Test
using Test
using PyCall
using RobotOS
RobotOS.debug(true)
Expand Down
4 changes: 2 additions & 2 deletions test/typegeneration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ rostypegen()
module TestModule
using RobotOS
@rosimport std_msgs.msg: Float32
rostypegen(current_module())
rostypegen(@__MODULE__)
end
@test !isdefined(std_msgs.msg, :Float32Msg)
@test isdefined(TestModule, :std_msgs)
Expand Down Expand Up @@ -84,7 +84,7 @@ path2 = convert(nav_msgs.msg.Path, pypath)

#Issue #6 - Empty message
emptymsg = std_msgs.msg.Empty()
@test length(fieldnames(emptymsg)) == 0
@test length(fieldnames(typeof(emptymsg))) == 0

#Issue #7/8 - Renaming conflicting message types
@test isdefined(std_msgs.msg, :Float64Msg)
Expand Down

0 comments on commit 30bcd49

Please sign in to comment.