Lua Scripting (lua.mo)

Started by dmilligan, March 29, 2015, 04:44:07 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Walter Schulz

7D with Canon EF 50/1.8 II, EF 100/2.8 Macro USM, EF 100/2.8 L Macro USM.
Focus stacking:

Num. pics in front > 0
->"Focus: Unknown error (2400)"
No pics taken. Abort.

Num. pics in front = 0
Num. pics behind > 1
-> Takes one pic. "Focus: Unknown error (2400)"

Not happening mounting Sigma 18-125. Not happening with 650D.
7D with EF-S 55-250/4-5.6 IS II gives "Focus: Unkown error (402400)

a1ex


garry23

a1ex

Sorry to bother you so soon, but I've just tried the latest nightly to see if how the new Lua modules works.

Here is the script I used, which worked fine before on my 5D3. The only change I made below is to account for the focus_distance change you made.

--[[
Still photography toggler script
Version 1.0 (should work on all ML enabled cameras with the Lua module)
Garry George March 2016
http://photography.grayheron.net/
Workflow toggler script to help with focus and exposure setting.
Toggle through your workflow using the selected option ie a button or the top of the main dial or toggle switch.
For focus feedback yellow means move more towards the infinity end, Red means move more towards macro end,
Green means at the sweet spot. If Green not seen, move to just being in the yellow from being in the Red.
--]]
factor = 0.2
b1 = lens.dof_far
fp = lens.focus_distance
c1 = b1 - (b1 - fp)*factor
inf = 1000000
started = false
current_tv = 0
play = 0
toggler = 0
-- Change toggler value to your choice of button, eg KEY.RATE, KEY.UP, KEY.INFO or KEY.PLAY.
-- See http://davidmilligan.github.io/ml-lua/modules/constants.html for key constants
-- Default is KEY.RATE for non-EOSM cameras. EOSM self selects upper toggle on main dial as the EOSM doesn't have many buttons!
if camera.model_short == "EOSM" then toggler = KEY.UP else toggler = KEY.RATE end

event.keypress = function(key)
if keymenu.submenu["Turn On/Off"].value == "Off" then
started = false
return true
elseif key == toggler 
then
play = play + 1
if play == 7 then play = 0 end
return false
elseif key == KEY.FULLSHUTTER and play ~= 6
then
b1 = lens.dof_far -- in mm
fp = lens.focus_distance -- in mm
c1 = b1 - (b1 - fp)*factor
started = true
return true
elseif key == KEY.HALFSHUTTER and play == 6
then
b1 = lens.dof_far -- in mm
fp = lens.focus_distance -- in mm
c1 = b1 - (b1 - fp)*factor
started = true
return true
end
end

lv.info
{
    name = "Info 1",
    value = "",
    priority = 100,
    update = function(this)
    this.value = ""
    if keymenu.submenu["Turn On/Off"].value == "On" and started and fp ~= 0
    then
this.foreground = COLOR.BLACK
a2 = lens.dof_near
if a2 > b1 then
this.background = COLOR.RED
elseif a2 < c1 then
this.background = COLOR.YELLOW
else
this.background = COLOR.GREEN1
end
if lens.dof_far >= inf then
this.value = "INF"
else
this.value = "   "
end
else
this.value = ""
end
end
}

lv.info
{
    name = "Info 2",
    priority = 100,
    value = "",
    update = function(this)
    if keymenu.submenu["Turn On/Off"].value == "On" then
    i = menu.set("Shoot","Advanced Bracket",0)
i = menu.set("Expo","Auto ETTR",0)
i = menu.set("Expo","Dual ISO",0)
i = menu.set("Shoot","Silent Picture",0)
this.foreground = COLOR.YELLOW
this.background = COLOR.BLUE
if play == 0 then
current_tv = camera.shutter.ms
this.value = " Off"
elseif play == 1 then
this.value = " BE "
camera.shutter.ms = 1
i = menu.set("Shoot","Advanced Bracket",0)
elseif play == 2 then
this.value = " Off"
camera.shutter.ms = current_tv
elseif play == 3 then
this.value = "ETTR"
i = menu.set("Expo","Auto ETTR",1)
i = menu.set("Auto ETTR","Trigger mode",3)
elseif play == 4 then
this.value = "Auto"
i = menu.set("Shoot","Advanced Bracket",1)
elseif play == 5 then
this.value = "Dual"
i = menu.set("Expo","Dual ISO",1)
elseif play == 6 then
this.value = "FRSP"
i = menu.set("Shoot","Silent Picture",1)
else
this.value = ""
end
end
end
}

keymenu = menu.new
{
parent = "Shoot",
name = "Landscape Helper",
help = "Toggle through workflow",
help2 = "Grab exposure or take picture as required",
submenu =
{
{
name = "Turn On/Off",
help = "Switches the script on/off",
help2 = "Provides access to ML functionality",
choices = {"On","Off"},
},
{
name = "Bracket to bracket overlap",
help = "Amount to overlap each bracket",
help2 = "% of FP-2-DoF(far) distance",
choices = {"20","10", "5"},
update = function(this)
factor = tonumber(keymenu.submenu["Bracket to bracket overlap"].value)/100
end,
}
}
}


The first issue I'm having is that the script does appear to load, ie it doesn't register on the console screen, as does the ony other script I have in the scripts folder, ie CALC.lua.

The script above should just load into the Shoot menu.

Do I need to do anything differently now?

Cheers

Garry

a1ex

What's the file name of the script? Can you see it in the file manager module?

garry23

File is TOGGLER.LUA and it shows up in the ML File Manager.

Strange.

a1ex

The script loads fine here, and appears in the Shoot menu.

garry23

Well that's good news. but a mystery for me. ???

garry23

OK it looks like the new lua module is going to require me to rewrite my script.

I get lots of errors regarding undeclared variables, that I never got before :-(

I try and get my toggler script running before moving on to other projects.

BTW will some kind person me tweaking the lua help pages to flag up the changes in functionality and syntax etc?

Cheers

Garry

dmilligan

Quote from: garry23 on April 21, 2016, 08:14:45 PM
OK it looks like the new lua module is going to require me to rewrite my script.

I get lots of errors regarding undeclared variables, that I never got before :-(
This is just the strict.lua stuff (first thing a1ex mentions in this post). It's a little checker script that requires that you declare global variables in the global scope before using them (It's actually nothing specific to ML or the ML API). This is good b/c you might not have realized that a variable you were only using locally was getting promoted to the global scope, which can have unintended consequences if you reuse the same variable names. For the most part all you need to do is add a local declaration if it's intended to be a local variable, or initialize it to something at the beginning of your script if its intended to be a global variable.

The only one I see in your script is the variable "i" in the "Info 2" update function. It looks like you don't even use "i", you only set it (a lot of compilers now-a-days actually issue warnings for this sort of thing), so you can just get rid of it altogether (just get rid of all the "i = "). Or you can just declare i as a local variable before you start using it (however, I would recommend the former for "correctness").

garry23

@dmilligan

Many, many thanks. I really appreciate your help.

I'll review the script and get it running :-)

Cheers

Garry

garry23

@A1ex/@dmilligan/@all

First of all, thanks to those of you that have supported the latest Lua nightly update.

For those of you that are still photographers you may be interested in the attached script, which is a fully auto landscape focus bracketing script.

I have tried it on my 5D3 and I'm pleased with it. YOU MUST HAVE THE LATEST NIGHTLY FROM AT LEAST 22 APRIL 2016.

Please read the text at the start of the script :-)

As usual I welcome feedback (on the coding or enhancements) to make the script better...and my programming skills ;-)

BTW I use Helicon Focus to merge the focus brackets directly from within LR, but you can use any post processing software you like.

Cheers

Garry

--[[
Simple landscape auto bracketing script
This version has no error detection so the user must be aware of certain things:
* Check the correct DoF diffraction options are set in ML, eg diffraction aware is on
* Must use a lens that reports focus distance and DoF can be calculated
* Lens must be in AF mode
* Switch stabalisation off as you will not be hand holding ;-)
* Must be in LV mode
* Assumes lens is focused at nearest point to start, ie script moves to infinity
* Script takes last bracket with focus point at infinity
--]]

function albs()
-- Get DoF info, delay as requested & take first bracket
menu.close()
-- Declare a few variables for the script
local a1 = 0
local b1 = 0
local a2 = 0
local b2 = 0
local fp = 0
local inf = 100000
local delay = 0
local base_tv = 0
local delay = tonumber(keymenu.submenu["Delay"].value)*1000
msleep(delay)
a2 = lens.dof_near
b2 = lens.dof_far
-- Add start dark frame bookend if requested
if keymenu.submenu["Bookends?"].value == "yes"
then
base_tv = camera.shutter.apex
camera.shutter.apex = 100
camera.shoot(64, false)
camera.shutter.apex = base_tv
end
camera.shoot(64, false)
-- take remaining brackets to macro end
repeat
a1=a2
b1=b2
repeat
lens.focus(-1,1)
b2 = lens.dof_far
a2 = lens.dof_near
fp = lens.focus_distance
until a2 > b1 or fp >= inf
lens.focus(1,1)
msleep(50)
camera.shoot(64,false)
until fp >= inf
-- Adds end dark frame bookend if requested
if keymenu.submenu["Bookends?"].value == "yes"
then
base_tv = camera.shutter.apex
camera.shutter.apex = 100
camera.shoot(64, false)
camera.shutter.apex = base_tv
end
end

keymenu = menu.new
{
    parent = "Shoot",
    name = "Auto Focus Bracketing",
    help = "Remember: LV, DoF & AF on + focus at nearest point",
depends_on = DEPENDS_ON.LIVEVIEW,
    submenu =
{
{
name = "Run Script",
help = "Does what it says after pressing SET",
select = function(this) task.create(albs) end,
},
{
name = "Delay",
help = "Delays script start by stated number of secs",
choices = {"2","5","0"},
},
{
name = "Bookends?",
help = "Places a dark frame at start and end of focus bracket set",
choices = {"no","yes"},
}
}
}

garry23

David/A1ex

Just noted some Lua 'strangeness' that I can't understand, but as it occurs in several sub menu calls in my script, I think it could be a bug?

Here is the part of the script that is 'playing up'

{
name = "Shadow Ev",
help = "As measured by shadow Ev from ML RAW (Ev) Spotmeter",
help2 = "only  integer value in (Ev)stops from 100% highlights", -- simply the ML spotmeter reading
min = -4,
           max = -20,
value = -5,
},


In the above, and another submenu that uses negatives, when I toggle through the values the max that is allowed is always the max I request less 2. In other words in the above I can only access between -4 and -18.

This does not occur if min and max are positive.

I've just noticed this as I've always used positive min and max until now.

dmilligan

Does it work correctly if you make max larger than min?

garry23

 :) Yes!

Thank you.

Is it still a bug or now a feature  ;)

dmilligan

I'd say it's probably a bug that it doesn't generate an error. Having max < min should probably technically be invalid.

Licaon_Kter

dm-spy-experiments branch says it can't load LUA on EOS-M:
Will NOT load on:
    EOSM (console_clear)

BBA

I have been trying to write some lua scripts. I worked on lens focusing to test "best focus infinity setting" and "focus stacking" scripts (cf. garry23's work in Lua).
I hope I will be able to share but first, I need advices of more experimented people.

As newb, I want to thank you very much for the hard but rewarding work that has been done and fully support the ML team way of thinking about this project http://www.magiclantern.fm/forum/index.php?topic=13335.0
Please forgive my english; always think I don't want to harm anyone!

1) the event message "software limit reached" appears on the Lv screen when moving lens, at some point, in both directions,
As said in this forum : to command the stepping motor for fast, accurate lens positioning can be a bit tricky/impossible b/c things change from one experiment to the other (there is always the temperature effect, but not alone; it can become very slow to get the infos/feedback from the lens).
Could someone tell me more about how this event message is generated and if it can be thought of as more "accurate" ?
Would it be difficult to be able to handle it in Lua scripting ?

2) are there "dummy libraries" to work with on a Lua sdk ? Not for timings nor multithreading questions, but to avoid syntax errors detected when script is running and to debug as many cases as possible (tree of possibilities).



garry23

@BBA

I experienced the soft limit 'problem' and worked around it in my scripts. The problem occurs if you drive the lens to the lens soft limits, ie at infinity or 'macro' end.

The way I worked around this is that I drive the lens, in my script towards the infinity end, and stop when the lens.focus_distance has reached a defined infinity, ie a large number, which happens before the infinity soft limit is reached.

Another way to achieve this would be to stop when lens.dof_far is reached at the infinity end or lens.dof_near at the macro end.

If you look at my landscape stacking code photography.grayheron.net (latest version is in the top right link on the home page), you will see that is how I handle the soft limit reached issue.

As to debugging and error detection, I'm afraid my experience is limited. My development approach is slow, as 'all' I can do is code things up, transfer to my 5D3 and read any errors that are reported and correct them.

As you will see in my code, I do try and account for user errors, but as I'm developing scripts for myself and sharing on that basis, I'm fairly relaxed regarding 'error detection'. Having said this, I do try and place comments in my scripts to help others.

I hope the above is of some help to you.

Cheers

Garry

garry23

@BBA

Another thing I thought about, and would love to see, is a Lua error module, ie some way we can detect an 'error event' and take action, eg the soft limit error.

But for this we are in the hands of others who know how to do such things: 'all' I can do is basic Lua scripting, ie not C-based ML coding.

Cheers

Garry

BBA

@garry23

Thank you for your messages !

QuoteAnother thing I thought about, and would love to see, is a Lua error module, ie some way we can detect an 'error event' and take action, eg the soft limit error.
I would love too. You have understood what I meant in my first question. Forgive my "clumsy" english... I think too it would be useful to be able to "trap" this error message in Lua. I "cross my fingers" and hope others will be interested too. Maybe I can help...but I have to learn too !

I have followed your work in Lua as I wasn't member of the community. I think you have made a lot of progress. I wondered why you did things like that: the test with a big number,... So I tried to study from scratch how things work with stepping motor and lens focusing. I will share what I did. I am not so experienced in photography, so I have to be careful because things can change a lot with other body/lens systems (I have a 5DmIII; I tested with EF 35mm f/2 IS II and EF 24mm f/1.4 L which both report distance). Imho, the algorithm is quite effective : not too many shots, rather well spaced. As you probably think too, the "infinity end" and the "macro end" can be improved with some work. That's why I asked for the error messages.
I would like to do a timelapse of the milky way in July. I will have to focus on "infinity". So, I have worked on scripts to help with that and I will share. Others have already done that in C. dmilligan and you have helped me a lot : thank you for that too !

QuoteAs to debugging and error detection, I'm afraid my experience is limited. My development approach is slow, as 'all' I can do is code things up, transfer to my 5D3 and read any errors that are reported and correct them.
As you will see in my code, I do try and account for user errors, but as I'm developing scripts for myself and sharing on that basis, I'm fairly relaxed regarding 'error detection'. Having said this, I do try and place comments in my scripts to help others.
Like you; the "cards" door of the 5D3 is rather "durable".
I have found the "Zerobrane" lua "sdk" on the internet (not Eclipse; I have to learn more about it) (no kidding, Zerobrane means zero brained - then, it's good for me to start learning...) . It can help to test algorithms and logic snippets more easily. I think it is possible to redefine the Lua functions (those that are used in the script) in "dummy" modules. For exemple, you can "emulate" the step by step focus motor with a file (the results of a complete scan of the lens from macro end to infinity end with storage of the values of "fp"...) . I wonder if others have already made more powerful things.

I wonder : the "editor.lua" can be used to make simple typo corrections while testing on camera.
By the way, I think it is possible to fix it by analogy:
Quote-- fixme: neither global width nor sb.w appear to be used anywhere
    -- if width == nil then sb.w = 2 end
I propose to replace the last line with
Quoteif w == nil then sb.width = 2 end

Have you already tried "big jumps" with  "step_size" of more than one step, like lens.focus(1,100) for instance ?
Quote
focus (num_steps[, step_size=2[, wait=true[, extra_delay=0]]])
I'll try as soon as possible.

A+

garry23

@BBA

The infinity 'large number' approach is already in ML's C coding as 1000 * 1000 (mm): I just adopted that protocol.

As to changing/editing on camera: I personally wouldn't bother - too fiddly.

Regarding moving the lens, I did look into that, but on my 5D3, the lens zips along even if I move one step at a time. However, on my 50D the same script runs at a snail's pace.

So I'm going to look at a more efficient algorithm to home in one the next focus point, eg jump past the point and quickly collapse to the 'optimum' position.

Cheers

Garry

garry23

@BBA

Forgot to say, thanks for pointing me towards Zerobrane lua. I'm hopeful this will help me with my debugging  :)

I wonder if it can be enhanced with some ML 'Lua stuff'?

Cheers

Garry

dmilligan

lens.focus returns true or false for whether or not the call sucedded, it's just not documented.

If you have a touchscreen camera, the version of the editor in the lua_touch branch is quite usable (on screen touch keyboard). Without the touch keyboard, I agree that trying to use the editor is a bit too tedious to be practical.

You can use luac or an editor that supports syntax checking (like LDT, mentioned in the OP), make sure you use Lua 5.3 version, for a very basic check on the computer. A stub version of the ML Lua API for the computer would be really nice, but very time consuming to make, so no such thing exists yet, but it's on the long term wish/todo list. HINT: modifying ldoc, the tool that generates the API docs, to output a stubbed version of the API in Lua code, might be one potential avenue.

garry23

David

I really want to help push the 'Lua environment' along, ie more tools to help debug code etc, but I fear my skills let me down. For instance I wouldn't have a clue how to 'modify Idoc'.

But I am keen to learn, but I will need help/pointers.

Cheers

Garry

dmilligan

https://github.com/stevedonovan/LDoc

It's a program written in Lua that converts source code comments in C or Lua to the HTML pages you see here: http://davidmilligan.github.io/ml-lua/index.html

You can reuse it's parsing capabilities, you just need to change the output code and templates that generates HTML to create some Lua source code instead. I've not looked at ldoc source so I have no idea how much work this would be.

You would probably want to start with simply manually writing some stub functions. A stub is an implementation of an API function that typically simply doesn't do anything, except perhaps validate the input to the function, and return some fake/synthetic/random data if the function is supposed to return a value (this will quickly become monotonous doing it for the entire API, which is why you eventually want to automate it with ldoc or whatever).

The stubs will give you the ability to "run" your script directly on the computer and do some basic validation, the quality of this validation depends on the complexity of your stub layer. The more work and complexity you put in your stubs the closer it will be to actually running your script on the camera and the more stuff about your script you can test.