Beckhoff#TF7000 Let’s Talk about Container

Good morning and welcome back to my Tutorial.In this topic I will talk a little bit more about “Container”.Container is a very important concept in Tc3_Vision – you need to use it in any vision function, for example barcode or qr code reading, object detection.Let’s start!

Last Post:

Beckhoff#Using TwinCAT TF7000 to read a QRCode | (soup01.com)

Functions

Let’s Explain the Tc3_Vision Functions concept before the Container.All the Tc3_Vision function are started with F_VN_XX and the format is like this:

hr

The result of your function.

F_VN_

All the Tc3_Vision functions are started with F_VN.

Parameter<..>

You would fill-in all the parameters while the function is called.There are 3 types of parameters:

  • Images or Container
  • algoritim settings
  • return Values


Expert Functions

Sometimes you may see the Functions are ended with F_VN_xxxExp. It is the short-name of Expert and These functions are the Advance version – you need to pass more parameters and can return more information about the image or process more operations to the images.

Define the Container

OK, time to start with the Container.Let’s Define a new container. 

Please imagine this container is a box that you can put anything inside, and the size is dynamic.you only need to be careful the element inside the container –  they need to be the same type.

After you defined the Container and login to the runtime, the value of Container is 16#0. 

F_VN_CreateContainer

Now we can use F_VN_CreateContainer to create the container. The Container is still empty now because we just defined it in the VAR Area. F_VN_CreateContainer () lets you define your “Box”, how many elements, what is their type,etc.

The parameters that pass inside the function  – is just the specification of your container.

You can see ipContainer is containing some value like 16#xxxx.

This value is not meaningful and just remember if its value is zero, the Container is “Empty” and does not reference anything.

Take a look at what Container that we created.

ContainerType_Vector_REAL  – we defined the element type as Real.

nElementNum=10 – 10 elements are defined defaultly.


Function Block

VAR_INPUT

ipContainerITcVnContainerReturns the created container
nTypeGidGUIDType GUID of the container to be created
nElementNumULINTNumber of elements
hrPrevHRESULTthe result of previous operations 

Return Value

F_VN_CreateContainerHRESULTthe result of  operations 

Code

//Create a Container
IF bcreateContiner THEN
hr:=F_VN_CreateContainer(
ipContainer:=ipContainer
,nTypeGuid:=ContainerType_Vector_REAL
,nElementNum:=10
,hrPrev:=hr
);
IF SUCCEEDED(hr) THEN
bcreateContiner:=FALSE;
END_IF
END_IF

Adding Element

This part I will explain how to operate the element inside the Container.Their operations are very like arrays.

F_VN_AppendToContainer_REAL

This function can be used to append the elements at the end of your Container.

The element with a default value 1.23 is appended at the end of your Container.

Now your Container had 11 elements.

Function Block

VAR_INPUT

fElementReference To REALSingle element to append to ipContainer
ipContainerITcVnContainerContainer to which the element will be appended
hrPrevHRESULTthe result of previous operation

Return Value

F_VN_AppendToContainer_REALHRESULTthe result of operation

F_VN_InsertIntoContainer_REAL

This Function is used to insert the element in any position that you like, depending on the index parameter.The element that is named FrealTest  is inserted at the position 0 of your Container.Now your Container has 12 elements.

Function Block

VAR_INPUT

fElementReference To REALSingle element to insert into ipContainer
ipContainerITcVnContainerContainer in which to insert the element
nIndexULINTPosition, before which the element will be inserted
hrPrevHRESULTthe result of previous operations

Return Value

F_VN_InsertIntoContainer_REALHRESULTthe result of operations

Code

IF bAddElement AND ipContainer <>0 THEN
hr := F_VN_AppendToContainer_REAL(1.23, ipContainer, hr);
hr := F_VN_AppendToContainer_REAL(2.23, ipContainer, hr);
hr := F_VN_InsertIntoContainer_REAL(FrealTest, ipContainer, 0, hr);
IF SUCCEEDED(hr) THEN
ii:=ii+1;
END_IF
bAddElement:=FALSE;
END_IF

Accessing Element

Tc3_Vision provides functions that start with  F_VN_GetAT_XX and F_VN_SetAt_XX to let you access the element inside the Container.

XX is the Data type of the elements.

Becarefully index is started from 0 and the data type is changed depending on your Container.


F_VN_GetAt_REAL

Function F_VN_GetAt_REAL allows you to get the value of Element, depending on the nIndex parameter.In the following example you are accessing the Element of Index5.

Function Block

VAR_INPUT

ipContainerITcVnContainerContainer with REAL elements
fElementReference To REALReturns the element at the specified index
nIndexULINTIndex of the requested element
hrPrevHRESULTthe result of previous operations

Return Value

F_VN_GetAt_REALHRESULTthe result of operations

F_VN_SetAt_REAL

Function F_VN_GetAt_REAL allows you to get the value of Element, depending on the nIndex parameter.In the following example you are accessing the Element of Index3.

Function Block

VAR_INPUT

fElementReference To REALElement to set at the specified container position
ipContainerITcVnContainerContainer with REAL elements, in which the element at positionnIndex is replaced by fElement
nIndexULINTIndex
hrPrevHRESULTthe result of previous operations

Return Value

F_VN_SetAt_REALHRESULTthe result of operations

Code

IF ipContainer <> 0 THEN
hr:=F_VN_GetAt_REAL(
ipContainer:=ipContainer
,fElement:=fElement
,nIndex:=myIndex
,hrPrev:=hr
);
END_IF

IF ipContainer <>0  AND bset3 THEN
hr:=F_VN_SetAt_REAL(
fElement:=fVarables
,ipContainer:=ipContainer
,nIndex:=3
,hrPrev:=hr
);
bSet3:=FALSE;
END_IF

Looping

In the Previous example, we can access the Single Element in one line.If we would like to loop all Elements inside the Container, an iterator can be used and have better performance. 

ITcVnForwardIterator

Offers an interface for a forward iterator.

Methods – TcQueryInterface

It is an interface to get the Query interface of your Element. 

HRESULT TcQueryInterface(RITCID iid, PPVOID pipItf )

VAR_INPUT

iidRITCIDInterface IID
pipItfPPVOIDinterface pointer

Return Value

実行に成功したらS_OK(0)や他の正の整数が戻ります。

HRESULTthe result of operations

Methods – CheckIfEnd

Method to check if the Iterator is end or not.

you can also use F_VN_CheckIfIteratorIsAtEnd().

Methods – Increment

Method the Iterator to loop the next element.

you can also use F_VN_IncrementIterator().

ITcVnAccess_REAL

An Interface to access the Real Data type Elements.

Methods – Get

Get the value.

Methods – Set

Set the Value.

Flow

Here is the flow for the above Sample Flow.

Program

//Get From Loop
IF bGet THEN
hr := F_VN_GetForwardIterator(ipContainer, ipIterator, hr);
index:=0;
IF SUCCEEDED(hr) AND ipIterator <> 0 THEN
hr := ipIterator.TcQueryInterface(IID_ITcVnAccess_REAL, ADR(ipAccess));
IF SUCCEEDED(hr) AND ipAccess<>0 THEN
WHILE  SUCCEEDED(hr) AND ipIterator.CheckIfEnd() <>S_OK  DO
hr:=ipAccess.Get(fValue:=fElement);
IF SUCCEEDED(hr) THEN
fElement:=fElement+1;
hr:=ipAccess.Set(fValue:=fElement);
END_IF
IF SUCCEEDED(hr) THEN
arrReal[index]:=fElement;
hr:=ipIterator.Increment();
index:=index+1;
END_IF
END_WHILE

END_IF
hr:=FW_SafeRelease(ADR(ipAccess));
END_IF
bGet:=FALSE;
hr:=FW_SafeRelease(adr(ipIterator));
bGet:=FALSE;
END_IF


+in Python

But if you just read it in Python, we explain the operation in these line:

elements=[4,1,2,4,5,7,8,1,2,66,224,4]
for element in elements:
#Do you stuff

Export Container as Array

Now we will Explain how to export the Elements inside Container as Array.

F_VN_ExportContainerSize

Determine the required buffer size in bytes to store all container elements (number_of_Elements *size_per_Element). Only possible for containers with basic elements.

VAR_INPUT

ipContainerITcVnContainerContainer with basic elements
nBufferSizeULINTOutput parameter containing the required buffer size
hrPrevHRESULTthe result of previous operations

Return Value

F_VN_SetAt_REALHRESULTthe result of operations

F_VN_ExportContainer

Export the container elements into a buffer (e.g. an array). Only possible for containers with basic elements.

VAR_INPUT

ipContainerITcVnContainerContainer with basic elements
pBufferPVOIDBuffer to store the container elements
nBufferSizeULINTSize of the buffer memory in bytes
hrPrevHRESULTthe result of previous operations

Return Value

F_VN_SetAt_REALHRESULTthe result of operations

Code

//Export it
IF bExport THEN
nBufferSize:=0;
FOR i:=0 TO 99 DO
arrReal[i]:=0.0;
END_FOR
hr:=F_VN_ExportContainerSize(
ipContainer:=ipContainer
,nBufferSize:=nBufferSize
,hrPrev:=hr
);
hr:=F_VN_ExportContainer(
ipContainer:=ipContainer
,pBuffer:=ADR(arrReal)
,nBufferSize:=nBufferSize
,hrPrev:=hr
);

bExport:=FALSE;

END_IF

Container In Container

Finally I will explain an Advanced concept – Container in Container. Let’s go through what we learnt before. There is 1 Container and it works like arrays,with same data type.

What happens If we Configure a Container inside a Container?

You can see the below pictures, the Subcontainers are saved like an array, the Container remains One Data type.

Here is the interesting point.we can see array elements are assigned in each Subcontainer.

And each Subcontainer had Real Elements. The numbers of these Elements are not fixed, you can see Container[0] had 6 elements, Container[4] had 2 elements.

It make sense that each container save the information of One Object, each object has their own information, and the information of each object may have different numbers of Elements.

Here is a flow to explain how my sample code works.

You do not need to 100% follow it and can do it by yourself:)

F_VN_AppendToContainer_ITcVnContainer

Append a single element to a container or concatenate containers (if ipElement has the same typeId as ipContainer).

Function block

VAR_INPUT

ipElementITcVnContainerSingle element to append to ipContainer or container withseveral elements to be concatenated
ipContainerITcVnContainerContainer to which the element(s) will be appended
hrPrevHRESULTthe result of previous operations

Return Value

F_VN_AppendToContainer_ITcVnContainerHRESULTthe result of operations

F_VN_ReserveContainerMemory

Reserve container memory (call with maximum required number of elements before manually appending elements for better performance)

VAR_INPUT

ipContainerITcVnContainerContainer for which to reserve the memory
nElementULINTNumber of elements for which the container should reserve memory
hrPrevHRESULTthe result of previous operations

Return Value

F_VN_AppendToContainer_ITcVnContainerHRESULTthe result of operations


Code

IF bSubContainerExample THEN
hr := F_VN_CreateContainer(ipContainerBase, ContainerType_Vector_Vector_REAL, 0, hr);
hr := F_VN_ReserveContainerMemory(ipContainerBase, TO_ULINT(cNumberOfSubContainers), hr);
FOR i:=0 TO (cNumberOfSubContainers-1) DO
hr := F_VN_CreateContainer(ipHelper, ContainerType_Vector_REAL, TO_ULINT(aContainerStructure[i]), hr);
hr := F_VN_AppendToContainer_ITcVnContainer(ipHelper, ipContainerBase, hr);
END_FOR


bSubContainerExample:=FALSE;
END_IF


IF ipContainerBase <> 0 THEN
F_VN_GetNumberOfElements(
ipContainer:=ipContainerBase
,nNumberOfElements:=nNumberOfElementsInSubContainter
,hrPrev:=hr
);
hr := F_VN_GetForwardIterator(ipContainerBase,ipIterator,hr);
hr := ipIterator.GetContainer(ADR(ipSubContainer));
IF ipSubContainer <> 0 AND SUCCEEDED(hr) THEN
iOpeartionCounter[9]:=iOpeartionCounter[9]+1;

hr:=F_VN_GetForwardIterator(ipSubContainer,ipIteratorInSubContainer,hr);
IF SUCCEEDED(hr) AND ipIteratorInSubContainer <> 0 THEN
iOpeartionCounter[10]:=iOpeartionCounter[10]+1;
ipIteratorInSubContainer.GetValueSize((nBufferSize));
ipIteratorInSubContainer.TcQueryInterface(
iid:=IID_ITcVnAccess_REAL
,ADR(ipAccessSubContainer)
);
IF SUCCEEDED(hr) AND ipAccessSubContainer<>0 THEN
iOpeartionCounter[11]:=iOpeartionCounter[11]+1;
ipAccessSubContainer.Get(fValue:=fElement);
ipAccessSubContainer.Set(fValue:=2);
ipAccessSubContainer.Get(fValue:=fElement);
END_IF
END_IF
END_IF
END_IF


Sample Code Download

TwinCAT3/TwinCAT Project_Vision_Container.tnzip at main · soup01Threes/TwinCAT3 (github.com)


Summary

In this tutorial, we used F_VN_AppendToContainer_REAL(),F_VN_InsertIntoContainer_REAL(),F_VN_GetAt_REAL(),F_VN_StAt_REAL() of access the element inside the Container, if we can changed it to らF_VN_AppendToContainer_INT() while the Elements Type is INT.

Because the Container is very flexible and allows you to re-size ,re-use it.
(please remember to release the memory if the pointer is not used any more. )

Footer_Basic

Please Support some devices for my blog

Amazon Gift List

Find ME

Twitter:@3threes2
Email:soup01threes*gmail.com (* to @)
YoutubeChannel:https://www.youtube.com/channel/UCQ3CHGAIXZAbeOC_9mjQiWQ

シェアする

  • このエントリーをはてなブックマークに追加

フォローする