JuliaRobotics / BotCoreLCMTypes.jl

LCM type definitions for compatibility with openhumanoids/bot_core_lcmtypes in Julia
Other
2 stars 2 forks source link

How to include const image types into image_t? #4

Open GearsAD opened 6 years ago

GearsAD commented 6 years ago

Hi,

There's a bit of metadata that should be in image_t.jl:

    // these values are to be kept in sync with the CamPixelFormat enumeration
    // in the Camunits library.  See camunits/pixels.h in Camunits
    const int32_t PIXEL_FORMAT_UYVY             = 1498831189;
    const int32_t PIXEL_FORMAT_YUYV             = 1448695129;
    const int32_t PIXEL_FORMAT_IYU1             = 827677001;
    const int32_t PIXEL_FORMAT_IYU2             = 844454217;
    const int32_t PIXEL_FORMAT_YUV420           = 842093913;
    const int32_t PIXEL_FORMAT_YUV411P          = 1345401140;
...

This is from Libbot. How best to include this into src/image_t.jl? Alternatively, we just hack in the specific Int value without reference.

cc @tkoolen , @dehann

dehann commented 6 years ago

Hi, due to difficulties with cross linking image_t into CaesarLCMTypes.jl, I ended up recreating caesar_image_t... Not ideal, but seems much easier and not much different from the original pods.cmake usage of LCM. See JuliaRobotics/CaesarLCMTypes.jl#9

dehann commented 6 years ago

Sorry, I'm not sure the best way to use constant values with LCMCore.LCMType...

rdeits commented 6 years ago

How about something like:

module image_t_constants
  export PIXEL_FORMAT_UYVY, PIXEL_FORMAT_YUYV

  const PIXEL_FORMAT_UYVY = Int32(1498831189)
  const PIXEL_FORMAT_YUYV = Int32(1448695129)
end

included in image_t.jl. Then users can do:

using image_t_constants
@show PIXEL_FORMAT_YUYV
rdeits commented 6 years ago

Also, if that's the right interface, it would be straightforward to create a macro to generate that module definition from something like:

@define_constants(image_t_constants, begin
  PIXEL_FORMAT_UYVY = Int32(1498831189)
  PIXEL_FORMAT_YUYV = Int32(1448695129)
end)
dehann commented 6 years ago

Hi @rdeits , thanks. I think that is a good way to do it -- I'd suggest we leave this issue open for a while and see if someone logs more interest? In the mean time, I'll try get to it if there are spare cycles to implement.

rdeits commented 6 years ago

Here's an example:

using MacroTools

function parse_assignment(assignment::Expr)
    if @capture(assignment, const x_ = y_)
        return x, y
    elseif @capture(assignment, x_ = y_)
        return x, y
    else
        error("Expected an assignment of the form `x = y`")
    end
end

macro define_constants(name, assignment_exprs::Expr...)
    assignments = parse_assignment.(assignment_exprs)
    inner_block = Expr(:block)
    for (x, y) in assignments
        push!(inner_block.args, :(export $(esc(x))))
        push!(inner_block.args, :(const $(esc(x)) = $(esc(y))))
    end
    # We need to put an @eval in the generated expression
    # because module definitions must happen at the top-level
    # whereas a macro could potentially be invoked anywhere
    :(@eval module $(esc(name)) 
        $(inner_block)
    end)
end

Usage:

Main> @define_constants(foo, bar=1, baz=2)
WARNING: replacing module foo
foo

Main> foo.bar
1

Main> foo.baz
2

Main> using foo

Main> bar
1

Main> baz
2
dehann commented 6 years ago

HI, yes - that helps thanks. I think that is the right way to do it. I'll try get to it soon.