脚本流程#
脚本流程 visionflow::param::ScriptPipeline 是测量工具等工具中,帮助用户自定义解决项处理流程的中间类。
它允许用户定义预脚本和解决项,以及为解决项添加条件判断和依赖关系,并将这些定义转换为可执行的 Python 脚本。
用户也能够从已定义的处理流程中反向解析出各个信息。
脚本流程中数据表示规则#
为了将处理流程关系和脚本的表达逻辑统一在一个数据源中,我们对表达脚本做了一定的规约,限制了用户的表达形式。
预脚本#
脚本流程支持用户设置 预脚本。 你可以在预脚本中导入模块或定义一些全局变量以便后续使用。
visionflow::param::ScriptPipeline pipeline;
// 设置预脚本.
pipeline.set_pre_script("import external\n\nglobal_info = external.data");
import external
global_info = external.data
解决项#
脚本流程中支持用户自定义 解决项 作为处理流程中的基本单元。 解决项可以是一次函数调用,也可以是一个表达式。
函数调用:一个可调用的函数对象。
例如:
geo.find_line,geo.find_circle。用户应清楚各个函数的输入输出参数信息。包括参数类型,取值范围等信息。
表达式:一个符合 Python 语法的表达式语句的变体。
在表达式中,用户可以自行使用约定的符号
${}标识出表达式中的参数部分。例如:
${line}.length() + ${circle}.radius这个表达式中有两项参数,分别是line和circle。
我们在执行时会根据解决方法中是否含有符号 $ 来区分两种不同的形式,并采取不同的参数填充形式。
同时 我们约定解决项的结果总是通过字典方式被存储在特定变量中 ,且后续使用时也通过特定变量直接读取数据。
因此默认会在预脚本之后定义字典 outs 用于存储解决项的结果。
pipeline.add_item("函数调用", "find_line");
pipeline.add_item("表达式", "${arg} + ${arg}");
pipeline.set_arg("表达式", "arg", "\"str\"");
outs = {}
outs["函数调用"] = find_line()
outs["表达式"] = "str" + "str"
可变参数和常量参数#
解决项参数支持两种形式:可变参数和常量参数。
可变参数:用户明确取值来自前面其他解决项结果或者结果的某个属性。
解决项的参数值依赖于其他解决项的结果。
我们约定;通过
$符号表示引用的解决项的对象变量。 这里的实现与表达式中的不同 。可以通过该符号重复引用同一个解决项。
常量参数:用户在参数设置阶段可以明确下来的参数。
这些参数不依赖于其他解决项的结果,在执行阶段是完全确定的,不会发生改变的。
我们约定:始终以直接对应的 Python 代码字符串表示。
pipeline.add_item("函数调用", "func");
// 添加常量参数.
pipeline.set_arg("函数调用", "arg", "0");
pipeline.add_item("表达式", "${arg} ** 2");
// 添加解决项可变参数.
pipeline.set_arg("表达式", "arg", "$.result", "函数调用");
outs = {}
outs["函数调用"] = func(
arg=0,
)
if outs["函数调用"] is not None:
outs["表达式"] = outs["函数调用"].result ** 2
条件判断和依赖关系#
上面那个例子最后自动添加了一个额外条件判断:即只有在 函数调用 的结果不为 None 时才执行 表达式 的计算。
我们认为,对于依赖其他解决项的解决项而言,被依赖对象不为空是必要条件。
但由于这一规则是普遍的,因此对于依赖的对象,总是会 自动判定依赖的解决项是否存在 。
仅在依赖的解决项存在的情况下才执行对应的解决方法。
同时我们也提供了 visionflow::param::ScriptPipeline::deps_on() 和 visionflow::param::ScriptPipeline::used_by() 帮助用户判断自行判断依赖关系。
解决项支持设置条件判断,表明尽在另一项满足某种条件时才执行。
当然此时条件判断中的对象必须是一个 bool 或者可以被当作 bool 表达式计算的值。
条件判断与可变参数类似,通过 $ 符号引用解决项对象。
// 添加解决项.
pipeline.add_item("函数调用", "func");
pipeline.add_item("表达式", "${arg} ** 2");
// 添加解决项可变参数.
pipeline.set_arg("表达式", "arg", "$.result", "函数调用");
// 添加条件判断.
pipeline.set_condition(
"表达式", "$.result > 0 and $.result < 100", "函数调用");
outs = {}
outs["函数调用"] = func()
if outs["函数调用"] is not None:
if out["函数调用"].result > 0 and out["函数调用"].result < 100:
outs["表达式"] = outs["函数调用"].result ** 2
脚本生成规则#
用户通过 visionflow::param::ScriptPipeline::to_script() 获取脚本流程对应的 Python 执行脚本。
解决项流程总是生成在一个函数内,函数签名则由用户定义。例如:
pipeline.set_pre_script("import external");
auto script = pipeline.to_script("pipeline(image, view=external.data)");
import external
def pipeline(image, view=external.data):
outs = {}
return outs
函数总是会将 outs 作为返回值,用户可以通过 outs 获取所有解决项的结果。