Since 2020, Caesar.jl has native support for ROS via the RobotOS.jl package.
Note that ROS neotic has switched to Python3 exclusively, and at the time of writing this page we were usinng Python2.7. See the ROS Wiki here: https://wiki.ros.org/UsingPython3
See ongoing RobotOS.jl discussion on building a direct C++ interface and skipping PyCall.jl entirely: https://github.com/jdlangs/RobotOS.jl/issues/59
The first thing to ensure is that the ROS environment is loaded in the bash environment before launching Julia, see "1.5 Environment setup at ros.org", something similar to:
RobotOS.jl currently using PyCall.jl to interface through the
rospy system. After launching Julia, make sure that PyCall is using the correct Python binary on your local system. In our local setup, we use (assuming
## Prepare python version using Pkg Distributed.@everywhere using Pkg # ENV["PYTHON"] = "/usr/bin/python3.6" Distributed.@everywhere begin ENV["PYTHON"] = "/usr/bin/python" Pkg.build("PyCall") end using PyCall Distributed.@everywhere using PyCall
Caesar.jl has native by optional package tools relating to RobotOS.jl (leveraging Requires.jl):
using RobotOS, Caesar Distributed.@everywhere using Caesar
Usually a factor graph or detectors, or some more common objects are required. For the example lets just say a basic SLAMWrapper containing a regular
robotslam = SLAMWrapperLocal()
Some function will also be required to consume the ROS traffic on any particular topic, where for the example we assume extraneous data will only be
function myHandler(msgdata, slam_::SLAMWrapperLocal) # show some header information @show "myHandler", msgdata.header.seq # do stuff # addVariable!(slam.dfg, ...) # addFactor!(slam.dfg, ...) #, etc. nothing end
Assuming that you are working from a bagfile, the following code makes it easy to consume the bagfile directly. Alternatively, see RobotOS.jl for wiring up publishers and subscribers for live data. Caesar.jl methods to consuming a bagfile are:
# find the bagfile bagfile = joinpath(ENV["HOME"],"data/somedata.bag") # open the file bagSubscriber = RosbagSubscriber(bagfile) # subscriber callbacks bagSubscriber("/zed/left/image_rect_color", myHandler, robotslam)
When adding Variables and Factors, use
solvable=0 to disable the new fragments until ready for inference, for example
addVariable!(fg, :x45, Pose2, solvable=0) newfct = addFactor!(fg, [:x11,:x12], Pose2Pose2, solvable=0)
These parts of the factor graph can simply be activated for solving:
setSolvable!(fg, :x45, 1) setSolvable!(fg, newfct.label, 1)
See tools such as
ST = manageSolveTree!(robotslam.dfg, robotslam.solveSettings, dbg=false)
manageSolveTree!(dfg, mss; dbg, timinglog, limitfixeddown)
Asynchronous solver manager that can run concurrently while other Tasks are modifying a common distributed factor graph object.
- When adding Variables and Factors, use
solvable=0to disable the new fragments until ready for inference.
addVariable!(fg, :x45, Pose2, solvable=0)
- These parts of the factor graph can simply be activated for solving
setSolvable!(fg, :x45, 1)
for solving a factor graph while the middleware processes are modifying the graph, while documentation is being completed see the code here: https://github.com/JuliaRobotics/RoME.jl/blob/a662d45e22ae4db2b6ee20410b00b75361294545/src/Slam.jl#L175-L288
To stop or trigger a new solve in the SLAM manager you can just use either of these
manageSolveTree! session. Usually up to the user to do so as a SLAM process comes to completion.
Trigger a factor graph
solveTree!(slam.dfg,...) after clearing the solvable buffer
slam.?? (assuming the
manageSolveTree! task is already running).
- Used in combination with
Once everything is set up as you need, it's easy to loop over all the traffic in the bagfile (one message at a time):
maxloops = 1000 rosloops = 0 while loop!(bagSubscriber) # plumbing to limit the number of messages rosloops += 1 if maxloops < rosloops @warn "reached --msgloops limit of $rosloops" break end # delay progress for whatever reason blockProgress(robotslam) # required to prevent duplicate solves occuring at the same time end
using AprilTags using Images, Caesar
Native code for consuming rosbags also includes methods:
RosbagSubscriber, loop!, getROSPyMsgTimestamp, nanosecond2datetime
Additional notes about tricks that came up during development is kept in this wiki.