Community Browser
cancel
Showing results for 
Search instead for 
Did you mean: 

Designing LabVIEW NXG: Configurable Functions

Active Participant

LabVIEW’s vast math and signal processing IP has been a benefit of the platform since its early days. Engineers and scientists frequently need these algorithms for their designs. As LabVIEW IP has evolved over the years, similar functions have been created to solve different workflows. For example, have you ever typed “filter” into the palette search in LabVIEW when simply looking to filter 60 Hz noise out of your measurement? If you have, you were undoubtedly met with a list of choices that could give even the savviest of G programmers some anxiety.

 

LabVIEW uses the polymorphic VI to allow API developers to create smaller, easier to use APIs. However, polymorphism conflates two separate user needs: the ability of the user to choose between similar functionalities like a filtering algorithm as well as auto-adapting to a wired input type. Moreover, the API developer must decide if they want the user to manually select the polymorphic instance or if the node will auto-adapt to the wired types. These capabilities cannot be combined in a polymorphic set.  In LabVIEW NXG, we’ve created separate mechanisms to decouple these desired behaviors.

 

 Picture1.png

The DAQmx Read VI is an example of a polymorphic VI, with an option to select Double or Waveform datatype, 1D or 2D array, and 1 or N Channels and Samples.

 

Selecting Between Behaviors

 

In LabVIEW NXG, we added the internal concept of Modes, which allow API developers to create a decision tree for users like polymorphic VIs in LabVIEW. On node drop, the user receives configuration options that allow for an interactive choice. In the example below, the user can pick the frequency range and filtering algorithm after dropping the filter node. The image shows just some of the 28 different settings the user can select.

Picture2.png

 

Picture3.pngSome of the configuration options that are possible from the Filter node in LabVIEW NXG.

 

Automatically Adapt to Wired Datatype 

 

Picture4.pngFive different overloaded instances of the Lowpass Butterworth Filter nodes in LabVIEW NXGAn internal concept of Overloads makes it possible for API developers to create a group of GVIs that will automatically switch based on what the user wires to the inputs. The API developer specifies an Overload Group ID that governs which GVIs can be interchanged. The picture below shows five different overload instances of the lowpass Butterworth filter.

 

Eventually, we’d like to open the ability to overload some internal LabVIEW nodes by using Overload Group IDs.

 

 

 

 

 

 

API Development

 

The best part of these features is the ability to combine a mode hierarchy with leaf-level items that are part of an overload group. We’ve really taken advantage of this technology in our math and signal processing APIs. We believe the experience will make for a much more approachable and easier-to-use API.

 

In the filtering example described above, one palette entry has 28 different manual configurations. Combine that with the five different data type options in the overload group, and 140 different configurations exist from one palette entry.

 

Our filtering palettes have been reduced from 39 specific entries in LabVIEW to just 13 in LabVIEW NXG. In LabVIEW, these 39 functions only operate on a 1D numeric array. In LabVIEW NXG, they all operate on scalar numeric, 1D numeric, 2D numeric, waveform, and 1D array of waveform. The illustration below demonstrates how the filter hierarchy was built using both modes and overloads.

Picture5.png

 

 

This is just one example of how an API can utilize modes and overloads to help the user. The ability to create modes and overloads isn’t publicly available in the newest version of LabVIEW NXG; however, we’re looking to extend these features to our user base soon.

 

Read more about designing LabVIEW NXG >>

 

 

 

 

Regards,

Jon S.
National Instruments
LabVIEW NXG Product Owner
Comments
Active Participant

Very interesting.  I'm curious about how these are implemented:

 

  1. Is each VI in an overload group an entirely separate VI?  How are they represented in both the source project (the project creating the overload group) and the user project (the project that uses the overload group?)
  2. What are the restrictions on the connector pane for all the VIs in an overload group?
  3. Can the overload automatically switch based on more than on input terminal?
  4. Can the overload automatically switch based on what the output terminals are wired to?
  5. There appears to be some overlap between the mode/overload functionality and malleable VI functionality.  Can you outline cases where you think each technology is preferred?  (Assuming malleable VIs are targeted for NXG.)
Active Participant

Thank you for the questions Daklu,

 

1. Yes, each GVI is it's own separate file on disk. A GVI opts into a specific Overload group via an Overload ID (string) that is in the GVI properties. Any GVI that uses that Overload ID is considered part of the group. There is no other distinction that separates these GVIs from other GVIs.


2. There are no restrictions on the connector pane of the function.


3. During type propagation we internally run a type matching algorithm on GVIs that have an Overload ID. This algorithm chooses the best matched connector pane of all GVIs with the same Overload ID based on what is wired to the GVI. In our APIs, this is typically a single terminal that has a different data type, but there are certainly cases where the connector panes have more than one different terminal. Because we haven't implemented have a mechanism for the user to manually select the overload instance they want, simple differences in connector panes work the best.


4. Only input terminals are considered in the type matching algorithm.


5. There is definitely overlap for these two concepts. There are some use cases where both technologies could be a valid solution. One example could be if you really just want to create one function that works with N number of different data types on a terminal. Overloads are truly powerful in the sense that the instances of the overload group can be distributed. Theoretically, if NI created an OverloadID to the Add node, anyone could extend the Add node by creating a function for their data type that used the same Overload ID. Overloads allow an API developer to create an API that can be extended beyond what they originally create. Malleable VIs are a single file and don't have that extensibility. An example of where you would want to use Malleable VIs is if you wanted to create a function that works for an N-d Array or a Queue of any datatype. You can create one function that knows how to handle all dimensions of an array or any queue type whereas with overloads, you would need to create a single function for each dimension or queue type.

Regards,

Jon S.
National Instruments
LabVIEW NXG Product Owner