JuliaPCL/PCL.jl

Discussing General Use

Closed this issue · 3 comments

Hi,
I just had a few question about general use of the library. If there is a better place to ask questions just let me know.
1.
I used this code and it complained about the types being different. Can you help me understand what I am doing wrong here.

cloud = PointCloud{PointXYZ}("mountain_view.pcd")
cloud = convert(PointCloud{PointXYZRGB}, cloud)
function getMax(cloud::PointCloud{PointXYZRGB})
    max = 0.0
    for i = 0:length(cloud) - 1
        if cloud[i,:z] > max
            max = cloud[i,:z]
        end
    end
    return max
end

max = getMax(cloud)

The error I get is

julia> max = getMax(cloud)
ERROR: MethodError: no method matching getMax(::PCLCommon.PointCloudPtr{Cxx.CxxQualType{Cxx.CppBaseType{Symbol("pcl::PointXYZRGB")},(false,false,false)}})
Closest candidates are:
  getMax(::PCLCommon.PointCloudPtr{Cxx.CppValue{Cxx.CxxQualType{Cxx.CppBaseType{Symbol("pcl::PointXYZRGB")},(false,false,false)},N}}) at REPL[17]:2

It seems to be a difference between CxxQualType and Cpp.Value ?
2. The following code runs pretty slow. I noticed in your test it seems you interact with the point cloud directly with C++ using Cxx. Is this because it is a shared pointer? Is this how you anticipate users of the PCL.jl to interact: a little of Julia and a little of C++ through Cxx?

function add_color(cloud)
    for i = 0:length(cloud) - 1
        z = cloud[i,:z]
        if z > 190.0
            cloud[i,:r] = 255 
            cloud[i,:g] = 0
            cloud[i,:b] = 0
        else 
            cloud[i,:r] = 0 
            cloud[i,:g] = 0
            cloud[i,:b] = 255   
        end
    end
end

EDIT: I rewrote the code in C++ and its ridiculously faster. Why is that?

function add_color_2(cloud)
    icxx"""
    #include<iostream>
    auto cloudp = $(cloud.handle);
    for(int i = 0; i < cloudp->points.size(); i++) {
        float z = cloudp->points[i].z;
        if(z > 190.0) {
            cloudp->points[i].r = 0;
            cloudp->points[i].g = 255;
            cloudp->points[i].b = 0;
        } else {
            cloudp->points[i].r = 0;
            cloudp->points[i].g = 0;
            cloudp->points[i].b = 255;
        } 
    }
    """
end
  1. And the last thing is that when I run spin(viewer) it seems the window comes up but cannot be exited. I cannot not close it, and the only way is by shutting down Julia. When I press the x button the Julia process will have an interrupt, but the window still stays .I figured it out. You press x on the viewer, and it stops the 'spin'. You can then continue coding/modifying and then start spin later.

  2. Also I found this in the source code, but I dont see PointCloudVal exported or defeined anywhere.

If you need a value representation rather than a smart pointer, then use
`XXXVal` (e.g. PointCloudVal) instead:
``julia
cloud = PointCloudVal{PointXYZRGBA}()
``

Thanks again for this Library.

r9y9 commented

Hi, sorry for the late reply.

  1. I'm sorry but I don't have right answer for this. I'm also not sure what happens exactly. It might be technically unrelated, but Cxx.CppValue has size in type parameters and sometimes it would be problematic in dispatching (JuliaInterop/Cxx.jl#212). For now you can loose the type signature to f(x::PointCloud) or use dirty version f(x::typeof(PointCloud{PointXYZ}())).

  2. Directly Interacting with C++ is because of performance. In julia code, it involves many function generations and calls, which could be performance heavy. Wrapping those into a single icxx macro reduces the function calls drastically, especially when the code includes loop. I tend to use C++ directly if performance is crucial.

  3. I use esc or x button, or triggers InteruptException by Ctrl+C.

  4. PointCloudVal isn't exported since I rarely use that. Accessible by PCLCommon.PointCloudVal. Theses are defined by @defpcltype macro https://github.com/JuliaPCL/PCLCommon.jl/blob/7765049b84f1662d3fdb80f18dd2900436a62b90/src/PCLCommon.jl#L208.

julia> :(PCLCommon.@defpcltype PointCloud{T} "pcl::PointCloud") |> macroexpand
quote  # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 200:
    begin  # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 176:
        begin  # docs/Docs.jl, line 480:
            type PointCloudPtr{T} # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 179:
                handle::(Cxx.CxxType)(__current_compiler__,Cxx.CxxTypeName{Symbol("boost::shared_ptr<pcl::PointCloud<__julia::var1>>")}(),Cxx.CodeLoc{Symbol(""),1,1}(),T)
            end # docs/Docs.jl, line 481:
            (Base.Docs.doc!)((Base.Docs.Binding)((current_module)(),:PointCloudPtr),(Base.Docs.docstr)((Core.svec)("Pointer representation for `","pcl::PointCloud<T>","` in C++\n"),(Dict{K,V})((Pair{A,B})(:path,nothing),(Pair{A,B})(:linenumber,0),(Pair{A,B})(:module,(current_module)()),(Pair{A,B})(:fields,(Dict{K,V})()))),Union{})
        end # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 182:
        begin  # docs/Docs.jl, line 480:
            type PointCloudVal{T} # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 185:
                handle::(Cxx.CxxType)(__current_compiler__,Cxx.CxxTypeName{Symbol("pcl::PointCloud<__julia::var1>")}(),Cxx.CodeLoc{Symbol(""),1,1}(),T)
            end # docs/Docs.jl, line 481:
            (Base.Docs.doc!)((Base.Docs.Binding)((current_module)(),:PointCloudVal),(Base.Docs.docstr)((Core.svec)("Value representation for `","pcl::PointCloud<T>","` in C++\n"),(Dict{K,V})((Pair{A,B})(:path,nothing),(Pair{A,B})(:linenumber,0),(Pair{A,B})(:module,(current_module)()),(Pair{A,B})(:fields,(Dict{K,V})()))),Union{})
        end
    end # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 201:
    begin  # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 190:
        begin  # docs/Docs.jl, line 480:
            typealias PointCloud{T} PointCloudPtr{T} # docs/Docs.jl, line 481:
            (Base.Docs.doc!)((Base.Docs.Binding)((current_module)(),:PointCloud),(Base.Docs.docstr)((Core.svec)("Pointer representation for `","pcl::PointCloud<T>","` in C++\n\ntypealias of [`","PointCloudPtr","`](@ref)\n"),(Dict{K,V})((Pair{A,B})(:path,nothing),(Pair{A,B})(:linenumber,0),(Pair{A,B})(:module,(current_module)()))),Union{})
        end # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 195:
        typealias pclPointCloudPtr{T} (Cxx.CxxType)(__current_compiler__,Cxx.CxxTypeName{Symbol("boost::shared_ptr<pcl::PointCloud<__julia::var1>>")}(),Cxx.CodeLoc{Symbol(""),1,1}(),T) # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 196:
        typealias pclPointCloudVal{T} (Cxx.CxxType)(__current_compiler__,Cxx.CxxTypeName{Symbol("pcl::PointCloud<__julia::var1>")}(),Cxx.CodeLoc{Symbol(""),1,1}(),T)
    end # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 202:
    handle(x::PointCloudPtr) = begin 
            $(Expr(:meta, :inline)) # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 202:
            x.handle
        end # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 203:
    handle(x::PointCloudVal) = begin 
            $(Expr(:meta, :inline)) # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 203:
            x.handle
        end # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 204:
    use_count(x::PointCloudPtr) = begin  # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 204:
            begin 
                (Cxx.cxxstr_impl)(__current_compiler__,Cxx.SourceBuf{224}(),Cxx.cppconvert(x.handle))
            end
        end # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 205:
    Base.pointer(x::PointCloudPtr) = begin  # /home/ryuichi/.julia/v0.5/PCLCommon/src/macros.jl, line 205:
            convert(Ptr{Void},begin 
                    (Cxx.cxxstr_impl)(__current_compiler__,Cxx.SourceBuf{225}(),Cxx.cppconvert(x.handle))
                end)
        end
end

Awesome, thanks for the quick responses. I don't understand macros yet so I will have to study that up a bit more. Especially because I'm struggling with the typing in this project.

One last thing I noticed from an example online is that

cloud = PointCloud{PointXYZRGB}("your_pcd_file.pcd")
cloud_filtered = PointCloud{PointXYZRGB}()

pass = PassThrough{PointXYZRGB}()
setInputCloud(pass, cloud)

Does not seem to work. It complains about a type error. I think it was looking for PCLCommonBase or something.

Part of me is thinking about writing most of the code in straight C++ code (i.e. compute the normal all in c++) and only exiting to Julia when necessary. I'm going to give that a try and hopefully getting the data out (with the right type) shouldn't be too hard. Thanks again!

r9y9 commented

Does not seem to work. It complains about a type error. I think it was looking for PCLCommonBase or something.

That should work. I guess you forgot using PCLIO? Without this, it'll raise an error. Thank you for your all feedback!