【VisionMaster应用】第十一讲 全局变量与全局模块

VM是海康机器人自主研发的机器视觉软件,将一系列的图像算法、逻辑工具和通讯协议等封装成图形化模块,致力于帮助客户提供快速搭建视觉应用、解决视觉难题,能够满足视觉定位、尺寸测量、缺陷检测以及信息识别等机器视觉应用。
转自:机器视觉技术交流社区

1 引言

全局是指一切从系统整体及全过程出发的思想。这种全局概念同样应用在VM中,在VM的快捷工具条中有一组全局工具,例如相机管理、控制器管理、全局变量、通信管理、全局触发、全局脚本等,本文主要介绍全局变量和全局脚本。
全局变量,有编程基础的朋友们相信不会陌生,是一种可以被局部获取或设置的变量。在VM中,全局变量可以被模块的运行参数订阅(获取全局变量的值),也可以绑定模块的结果(设置全局变量的值),在VM中起到多流程间数据传递的桥梁作用另外,全局变量常用场景有:接收通讯数据,流程之间数据交换,计数等等。
全局脚本,支持调用算法平台SDK的C#版本(VM3.x)。在VM中,全局脚本可以控制流程的运行,快捷工具条上的单次执行按钮(方案中的所有流程执行一次)和连续执行按钮(方案中的所有流程连续执行)被点击之后都会进入全局脚本函数中。全局脚本常用场景有:执行一次指定流程、控制多个流程执行、模块参数配置、模块运行结果获取、全局变量设置、全局通信等等。

2 全局变量介绍

全局变量是在所有的函数外部定义的变量,是可以被本方案中所有流程调用或修改的变量,可自定义变量名称、类型和当前值,它在整个工程文件内都有效。单击图标可进行全局变量的配置。如图中所示,添加了一个变量,名称命名为var0,注释可不写,类型为float。
在这里插入图片描述
相关功能如下:

  • 添加变量:点击+添加变量后可新增全局变量。

  • 导入/导出:可以固定格式文件导入或导出全局变量信息。

  • 搜索:当全局变量较多时,可快速搜索。

  • 置顶/上移/下移:可对变量的位置进行上下调整。

  • 保存变量:可将当前设置的全局变量进行保存。

  • 输入来源:即设置全局变量的值,可通过对对应类型的模块结果数据进行绑定,只可以绑定一个,如下图所示。
    在这里插入图片描述

  • 目标输出:即获取全局变量的值,可通过对对应类型的模块运行参数数据进行绑定,可绑定多个,可以如下图所示。也可以双击某个模块打开参数配置,进而订阅全局变量。
    在这里插入图片描述

  • 初始化:开启的作用,则是接收通讯发送过来的固定格式的字符串,实现对全局变量的值的设置。如变量var0,当通讯发过来SetGlobalValue:var0=99,可以将该变量值设为99。
    在这里插入图片描述

3 全局脚本接口和示例

单击全局脚本图标打开编辑界面,菜单栏功能分别是:导入C#代码、导出C#代码、打开(导入)示例代码、打开工程目录、打开引用的程序集以及保存代码,菜单栏下方则是C#编辑区,C#编程区中Init()函数为初始化函数,Porcess()为处理函数。
在这里插入图片描述

  1. 全局脚本接口
    全局脚本中可以使用的设置和获取接口如下所示包含全局变量、脚本连续运行事件间隔、通讯接口等等。其它的接口函数调用可以查看《VisionMaster算法平台SDK开发指南V3.x.chm》,路径:VisionMaster4.2.0\Development\V3.x\Documentations。
功能函数方法参数说明
获取全局变量int型GetGlobalVariableIntValue(string paramName, ref int paramValue)输入:变量名paramName;输出:变量值paramValue
获取全局变量float型GetGlobalVariableFloatValue(string paramName, ref float paramValue)输入:变量名paramName;输出:变量值paramValue
获取全局变量string型GetGlobalVariableStringValue (string paramName, ref string paramValue)输入:变量名paramName;输出:变量值paramValue
设置全局变量int型SetGlobalVariableIntValue (string paramName, int paramValue)输入:变量名 paramName,变量值paramValue
设置全局变量float型SetGlobalVariableFloatValue (string paramName, float paramValue)输入:变量名 paramName,变量值paramValue
设置全局变量string型SetGlobalVariableStrignValue (string paramName, string paramValue)输入:变量名 paramName,变量值paramValue
获取连续运行时间间隔GetScriptContinusExecuteInterval ()
设置连续运行时间间隔SetScriptContinusExecuteInterval (uint nMilliSecond)输入:时间间隔nMilliSecond,单位ms
初始化全局通信StartGlobalCommunicate ()
注册通信接收事件RegesiterReceiveCommunicateDataEvent()
通信数据接收事件UserGlobalMethods_OnReceiveCommunicateDataEvent(ReceiveDataInfo dataInfo)输入:通讯信息dataInfo
通信发送数据SendCommDeviceData(string data,int deviceID)输入:待发送数据data,设备deviceID
  1. 全局脚本中示例
    在vm中的全局脚本示例中,保存了常见应用的示例代码,根据所需选择任意一个就是导入到当前方案中,随之可进行参考或修改代码。
    在这里插入图片描述

4 全局脚本引用和调试

  1. 添加引用
    在全局脚本界面,打开引用的程序集,根据需求进行程序集动态库的添加,仅支持C#程序集添加,到需要的第三方程序集路径下找到想要添加的.dll,点击打开即可添加,添加完成后在全局脚本中调用即可。
  2. 调试步骤
    在全局脚本界面,打开工程目录后就会自动跳转全局脚本所在的文件夹,选择.sln文件使用VS打开,设置断点并且重新生成,然后点击【调试】中的【附加到进程】,再选择GlobalScript.exe附加,最后在VM中运行方案的单次执行来查看是否能进入断点。
    提示:断点调试时,每次修改代码都需要重新编译,VS重新编译后,只有第一次运行会进入Init()函数。
    在这里插入图片描述

5 案例演示

需求:某定位项目,需要结合全局变量和全局脚本,通讯设置全局变量的值,给上位机发送物理坐标。
第一步,在VM通讯管理设置号通讯设备。
在这里插入图片描述
第二步,在全局变量中设置中对应的变量。
在这里插入图片描述
第三步,打开全局脚本中的示例-全局通信,适当修改代码。在全局脚本中根据输入的字符串进行分割设置对应的全局变量。
效果如下所示,实现通讯输入的点位信息赋值到全局变量中,那么其它模块将可以订阅全局变量的值。
在这里插入图片描述
完整代码如下所示:

using System;
using VM.GlobalScript.Methods;
using System.Windows.Forms;
using iMVS_6000PlatformSDKCS;
using System.Runtime.InteropServices;

/******************************
 * 示例说明: 接收全局通信模块数据示例
 *     前提: 全局通信模块中开启有通信设备
 * 控制逻辑: 1.接收来自全局通信模块接收到的数据
 *           2.如果接收到数据字符0,则执行流程1一次
 * ***************************************/
public class UserGlobalScript : UserGlobalMethods, IScriptMethods
{
    /// <summary>
    /// 初始化函数
    /// </summary>
    /// <returns>成功:返回0</returns>
    public int Init()
    {
        //二次开发SDK初始化
        InitSDK();
        //设置与全局通信模块的通信端口
        StartGlobalCommunicate();
        //注册通信数据接收事件
        RegesiterReceiveCommunicateDataEvent();

        return 0;
    }

    /// <summary>
    /// 运行函数
    /// 单次执行:该函数执行一次
    /// 连续执行:以一定时间间隔重复执行该函数
    /// </summary>
    /// <returns>成功:返回0</returns>
    public int Process()
    {
        MessageBox.Show("进入Process");
        //m_operateHandle 二次开发SDK操作句柄
        if (m_operateHandle == IntPtr.Zero)
        { return ImvsSdkPFDefine.IMVS_EC_NULL_PTR; }

        //默认执行全部流程,如果自定义流程执行逻辑,请移除DefaultExecuteProcess方法

        int nRet = DefaultExecuteProcess();

        return nRet;
    }
    /// <summary>
    /// 通信数据接收函数
    /// </summary>
    public override void UserGlobalMethods_OnReceiveCommunicateDataEvent(ReceiveDataInfo dataInfo)
    {
        if (dataInfo == null || dataInfo.DeviceData == null)
        { return; }
        //接收到的数据转成字符串
        string str = System.Text.Encoding.Default.GetString(dataInfo.DeviceData);
        MessageBox.Show(str);
        string[] strlist = str.Split(',');
        SetGlobalVariableFloatValue("X", Convert.ToSingle(strlist[1]));
        SetGlobalVariableFloatValue("Y", Convert.ToSingle(strlist[2]));
        SetGlobalVariableFloatValue("R", Convert.ToSingle(strlist[3]));

        //这里的deviceIndex和全局通信模块中的一致
        if (dataInfo.DeviceID == 1)
        {
            //解析收到的数据
            if (strlist[0] == "C")
            {
                //执行流程1 一次
                ImvsPlatformSDK_API.IMVS_PF_ExecuteOnce_V30_CS(m_operateHandle, 10000, null);
            }
        }
    }

    /// <summary>
    /// SDK回调函数
    /// </summary>
    public override void ResultDataCallBack(IntPtr outputPlatformInfo, IntPtr puser)
    {
        base.ResultDataCallBack(outputPlatformInfo, puser);
        ImvsSdkPFDefine.IMVS_PF_OUTPUT_PLATFORM_INFO struInfo = (ImvsSdkPFDefine.IMVS_PF_OUTPUT_PLATFORM_INFO)Marshal.PtrToStructure(outputPlatformInfo, typeof(ImvsSdkPFDefine.IMVS_PF_OUTPUT_PLATFORM_INFO));
        switch (struInfo.nInfoType)
        {
            //获取模块结果数据
            case (uint)ImvsSdkPFDefine.IMVS_CTRLC_OUTPUT_PlATFORM_INFO_TYPE.IMVS_ENUM_CTRLC_OUTPUT_PLATFORM_INFO_MODULE_RESULT:
                {
                    ImvsSdkPFDefine.IMVS_PF_MODULE_RESULT_INFO_LIST_P resultInfo = (ImvsSdkPFDefine.IMVS_PF_MODULE_RESULT_INFO_LIST_P)Marshal.PtrToStructure(struInfo.pData, typeof(ImvsSdkPFDefine.IMVS_PF_MODULE_RESULT_INFO_LIST_P));
                    break;
                }
            ///获取流程运行状态
            case (uint)ImvsSdkPFDefine.IMVS_CTRLC_OUTPUT_PlATFORM_INFO_TYPE.IMVS_ENUM_CTRLC_OUTPUT_PLATFORM_INFO_WORK_STATE:
                {
                    ImvsSdkPFDefine.IMVS_PF_MODULE_WORK_STAUS stWorkStatus = (ImvsSdkPFDefine.IMVS_PF_MODULE_WORK_STAUS)Marshal.PtrToStructure(struInfo.pData, typeof(ImvsSdkPFDefine.IMVS_PF_MODULE_WORK_STAUS));
                    break;
                }
            default:
                break;
        }
    }
}

6 总结

在以图形化交互为特色的VM算法平台里,用户应尽量避免写过多的代码。全局脚本中的示例代码功能,依靠VM自身已有的功能也能实现,例如示例代码中的模块参数设置,用户可鼠标双击模块,打开模块的参数配置窗口进行配参;示例代码中的全局通信接收数据,用户可使用快捷工具条中的通讯管理(自带接收事件进行协议解析)。最后,根据小编多年工程经验,有以下两点需要注意:

  1. 无法命中断点位置。建议调试过程中,打开工程目录后关闭脚本模块编辑界面,只使用Visual Studio修改代码和编译,然后附加到进程。
  2. 除打断点查看变量值,还可以使用MessageBox.Show(string paramValue)函数来查看相关变量。
  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值