Jump to content

Tomi Maila

Members
  • Posts

    849
  • Joined

  • Last visited

  • Days Won

    9

Posts posted by Tomi Maila

  1. Luminar Technologies, Inc. is currently seeking applicants for a LabVIEW Developer to join our growing team in Orlando, FL.
     
    Our vision is to power every autonomous vehicle with the first LiDAR capable of making them both safe and scalable. It’s easy to get an autonomous vehicle to work 99% of the time, but it’s the last 1% that’s preventing them from becoming a reality. That’s where we come in. We’ve built a breakthrough LiDAR from the chip level up, delivering 50x better resolution and 10x longer range than the most advanced LiDARs available today. Luminar is not just a sensor, but the core of a platform that can enable the industry to have safe autonomous vehicles on the road.
     
    We are a diverse team of passionate and driven individuals, making us a powerhouse of innovation, design, engineering, and manufacturing. We are hiring the best and the brightest to accelerate the industry, and bring forward the next transportation revolution.
     
    Apply online by clicking the link below.
     
     
    4-6-city-streets-8.png
  2. ShaunR, the List type in your example is not strongly typed but generic. That means the type of the list wire for a list of Strings is not different from the type of the list wire for the list of DBLs. That's the exact problem type parameters would solve. 

    Hooovahh, although the data type is strongly typed , the data type of the circular buffer is not encapsulated into a "Circular Buffer of type String" class but instead it exposes the private data to outsiders. Further one cannot create a type definition or a class that one can use in a VI front panel to tell that this VI expects a "Circular Buffer of type DBL" as input and returns a "DBL". 

  3. Generics without type parameters don't really solve the main programming problem I want to solve: Create class libraries that can be used with different type data. As a simple example creating a class library for a linked list of data of any type would not be possible with VIMs be cause they couldn't output a type parameterized type "Linked List<T> " where T is the datatype and Linked List is a class having T in the private data. Now T is a type parameter so we need to represent it somehow. VIMs don't provide a representation for type parameters in data structures.

  4. I made the Adapt to Type method public in JKI JSON allowing separation of the parsing from a JSON string and adapting to a LabVIEW type. It's not yet documented but if you look into JKI JSON Deserializer class the behavior should be relatively obvious. First deserialize from JSON string and then call adapt to type when you know what type you need. Thanks drjdpowell for the suggestion!

    • Like 1
  5. We recorded all JKI presentations and have made them available online. AI and deep learning with Javier Ruiz & Ian McFarlane, .NET integration and interface design with Sarah Zalusky, and Caraya unit testing with Jim Kring. Good stuff!

    Caraya: A New Take on LabVIEW Unit Testing - TS9754
    by Jim Kring

    Designing a LabVIEW Interface for .NET Applications - TS9757
    by Sarah Zalusky

    Artificial Intelligence With LabVIEW: Deep Learning-Based Classification and Control - TS9758
    by Javier Ruiz & Ian McFarlane

    Watch videos

     

     

     

    • Like 2
  6. I always love a small challenge. Here's what I did:

    • Calculate the offset of first pixel of each row in the final image where offset is the index of an element in the initial U64 array (this needs to be calculated only once)
    • Initialize a destination image of correct size
    • For each row of the destination image, replace the row content with an unpacked content of the initial U64 array of correct length

    I was able to drop the processing time to about 1/2 of the fastest algorithm in the initial VI.

     

    Download here

     

    p.s. LAVA refused any uploads... :(

     

    post-4014-0-00274300-1422842394_thumb.pn

  7. When I originally selected the name for my blog ExpressionFlow back many years ago, what I had in mind was functional dataflow programming and the ability to pass any subdiagrams (expressions) around as first class citizens of the language. Functional programming languages (haskell, clojure, lisp) have a lot in common with dataflow world. In principle, calling a function in a functional language is identical to calling a node in a visual language. Passing data between functions happens in an immutable way in functional languages, similar to the concept of data flowing between nodes in a flow-based programming languages. Monads determine execution order of functions with side effects, the same way as flow diagrams determine the execution order of nodes in LabVIEW.

     

    Functional programming is often seen as an alternative to object oriented programming. One can solve similar problems of dynamic dispatching either by passing functions around or passing objects with methods around. There are of course multi-paradigm languages supporting both objects and functions like Clojure and Scala. So what would LabVIEW look like if it supported concepts of functional programming paradigm? I posted an article on this on ExpressionFlow and I am intending to study the concept on ExpressionFlow in my future posts. 

     

    Would you use functional LabVIEW if such a language existed?

     

    My post on how a functional programming could appear in a visual dataflow language:

     

    Synchronous Functional Dataflow Programming & Closures of Named Functions

     

    post-4014-0-66830000-1386130732_thumb.pn

     

    p.s. See Joel's quick intro to functional programming if you are unfamiliar with the concept of functional programming.

     

     

     

     

  8. I actually really like the message passing concurrency models such than the one of Erlang. The good news is that the flow-based programming models actually rather well help architecting such models using a visual programming language. The downside is that such languages are not widely available as of today. 

     

    Read my last few posts on convergence of asynchronous and synchronous dataflow models. 

     

    Hybrid Dataflow – Convergence of Flow-Based Programming with Synchronous Dataflow

    Embedding synchronous dataflow into a flow-based programming diagram

  9. No, he's not. It's a design limitation that I've wished were fixed on multiple occasions.

    The problem is the one-to-one relationship of the registration refnum to the event structure. You should never share registration refnums with two different event structures -- that way leads to DOOM. As such, it makes little sense for the event registration refnum to be stored anywhere or passed around very much.

    I have no problem with the one-to-one relationship, after all event registration acts like a mailbox and people don't share mailboxes with their neighbors either. However, what I was confused of is if the event registration should actually happen in the same VI as the event structure.

    My typical program works as follows:

    1. Create user event refnum
    2. For each process receiving the user event create event registration refnum for that particular user event
    3. Launch all parallel processes that generate user events and receive them

    Executing step 2 before step 3 guarantees that the event registration exists before anybody generates events of that type. It would be very bad programming not to somehow guarantee that the event is registered before generating the events. The easiest way to do it is simply do the registration outside the process VI that handles the events. Of course the 1-to-1 relationship still holds, a single event registration is created for a single process VI with a event structure.

    Second model I have been thinking of and playing around but not used yet in real life is using multiple event structures with one event registration refnum, but in such a way that only one event registration refnum is executing at any single time. This way you can switch the way how a certain event is handled by a certain event listener on the fly.

    Should these two use cases work as I expect them to?

    PS: You should also not change which dynamic refnum a given event structure is using during the run of the VI. You can change which events are registered, but you should use the same registration refnum.

    If I have a subVI that has an event structure and a event registration refnum input terminal that is connected to the event structure register for events terminal, are you saying that this will fail if the same instance (clone) of the subVI is executed in different places of the application. Say it was a re-entrant VI but with share clonses option selected. Then one of the event handler VIs has done its job and exits gracefully. Now LabVIEW reused the VI instance for another event handler VI instance and another event registration refnum is connected to the event registration input terminal of the VI.

    Maybe I understand everything better when someone from NI is ready to explain all the weirdness that has been discussed elsewhere in this thread.

  10. Originally, I had a line in my previous reply about always keeping the event structure near the registration node, a line which I later removed. The reason for this is that each reg node should go to a single event structure (this is documented, albeit not very well). Since the only way of guaranteeing this is to have the reg node near the structure, that's what I do.

    Event registration is like a mailbox. User event is like a mailing address. When even is registered, the mailing address gets connected to a mailbox, that would by default be just a garbage bin. I want to register my events, that is create the mailbox, before I execute my event handler VI. This way the mailbox exists before anybody tries to send letters to the mailing address. If you register the events in the same VI where the event structure is, you need to use secondary synchronization mechanisms to guarantee that the mailbox has been created before anybody sends messages to it. I think this is unnecessary boilerplate code.

  11. I vaguely recall someone mentioning that event reg refnums are intended to be used only on block diagrams that service the event. That's part of the reason I gave up on them in my frameworks.

    You must be kidding?

    For that to work the event reg refnum wire *has* to violate normal data flow rules. In essence, the refnum has to behave like a global, at least on any single block diagram.

    From theoretical point this is not true, it would be very simple to implement the event structure in dataflow safe way. Each time the event structure is executed, the event registration would simply flow from left to right in dataflow manner. That is each case that do not have event registration refnum wire connected within the case, would simply be identical to a event case where the internal output terminal on the left would be directly connected with a wire to internal input terminal on the right. That is pure dataflow.

  12. It's neither a bug or an undocumented feature. It's the control doing exactly what all controls do. If I have a numeric control and I say, "Make current value default", and the current value is 3, then thereafter the default is 3. With a reference number, the same thing happens. If the current value is "0x33445522", and you say "Make Current Value Default", then the default value thereafter is "0x334445522". The control does *not* allocate a reference ever. It returns that (probably invalid) refnum. I (and others) thought that a control/constant of these types were always default of Not A Refnum, which would be undocumented special behavior. But, no, it's just the same behavior as all other controls.

    What you have to remember is that the controls store a reference number, not the thing that is referenced.

    The behavior you described is not the behavior I am seeing. Follow the exact steps with the example project I posted.

    1. Open Main VI

    2. Put a probe to the object array wire just before the loop (probe 4)

    3. Put a probe to the object array wire just after the loop (probe 5)

    4. Run VI

    5. Check the Event Registration Refnum values of each array element in probe 4 and probe 5

    6. Run VI again

    7. Check the Event Registration Refnum values of each array element in probe 4 and probe 5

    The results of my test run are (only event registration refnum is displayed):

    Probe 4 after step 5: [2922381312, 2922381312, 2922381312] (note all elements are same)

    Probe 5 after step 5: [2923429888, 2923429888, 2923429888] (note all elements are same but different than those of probe 4)

    Probe 4 after step 7: [2923429888, 2923429888, 2923429888] (note all elements are same as probe 5 values after step 5)

    Probe 5 after step 7: [2924478464, 2924478464, 2924478464] (note all elements are same but different than those of probe 4 after step 7)

    As probe 4 is returning values of constant we can deduce that the values of the constants are not constant as the values of probe 4 vary from run to run and are the same as those of probe 5 of the previous run. This is definitely undocumented. Second thing to notice is that when wired to the register for events node, the event registration refnum gets a new value but the new value is the same for every execution of the node within the same run of the app. I would expect either error to be returned because the input refnum is invalid or alternatively a new different refnum to be created each time. That is I would expect the values of Probe 5 array to be all different, or alternatively errors should be returned and the values should be those as the ones of Probe 4.

    post-4014-0-61324700-1297067480_thumb.pn

    post-4014-0-93803800-1297067583_thumb.pn

  13. Yeah, and what we discussed there is apparently wrong to some degree. :-)

    Can anyone describe what is happening in the example code I posted. It is a non-documented feature of LabVIEW. I would say it is a bug if the constant refnum was not different at every single run. But it is different, so LabVIEW allocates a new refnum at every single run. So it must be a designed feature, or accidentially implemented feature of refnum constants that get allocated when the class gets loaded to memory or when the refnum is dereferenced the first time.

  14. I made a test project that demonstrates the issue I was having. Just open the Main VI, place a probe where suggested and run it. Note that all three created event registration refnums are all the same.

    Event Registration Test.zip

    You know, I never thought about this, but what if we just made it so that the default value for refnums was *always* Not A Refnum? I don't think there's ever a valid reason for having a non-zero default value in either the default value or in a diagram constant.

    [EDIT] Ah... just saw Omar's post. :-)

    Actually LabVIEW seems to have a concept of refnum persistence and it would be actually cool to have it. Think the following for example. Drop a DVR constant somewhere. Set it to have a non-default value. Then distribute the DVR across your app by wiring from the constant (or control). Now you would not need to initialize the DVR, but instead it would automagically have a default instance created upon the time the constant is read. This would be especially cool with LabVIEW class private data, that would have DVR's as private members. Now you could drop a class constant on block diagram and you would not need to call constructor to initialize the DVRs, but instead they would be automatically initialized when the class is loaded to memory. Practically you would have a singleton, unless you set your class constants to have non-default values across your app. Or maybe there could be an option to avoid the singleton issue.

    EDIT: Can someone (from NI) explain to me what exactly is going on in my example code. It still doesn't make complete sense to me.

    1. Why do I get a different default value for the reference from each constant each time I run the code.

    2. Why do the register for events nodes not create a new event registration refnum but instead always return the same?

  15. I debugged multiple hours today a bug in my code where for some reason I did not receive user events to my event structure. The bug happened in a class whose private data looks the following.

    post-4014-0-24356000-1296690948_thumb.pn

    In the code, I set the input event registration refnum within a method VI of the class. In the particular class the same VI could be called multiple times, so I only registered the events if they had not been registered earlier. I wrote a test case and the test case looked like it was deadlocking. I was looking the bug everywhere but not the class private data. Finally I find the bug by placing a probe on the wire originating from a constant of that class.

    post-4014-0-23397700-1296690953_thumb.pn

    The bug in my code was that the class private data had an event registration refnum, which had a default value that was non-zero. However, there is no way to see this bug by just looking the class private data. There is also no way of fixing the bug, other than creating a completely new event registration refnum constant of the same type and copying it to the class private data to replace the original one.

    The bug originates from the fact that in LabVIEW you cannot drop event registration refnums fron control palette but you have to instead create one on the block diagram and then copy the event registration refnum from your diagra (front panel) to your class private data. Again there is no way of noticing if the event registration refnum has a non-zero value. So I must have ran my code once, then copied an indicator to my class private data, carrying the non-zero default value with it not seeing it as the look-and-feel of the event registration refnum is exactly the same if it is null or not.

    In my code, LabVIEW did not return me an error when I reregistered a user event with an old invalid event registration refnum. They got properly registered, at least it appeared so. In some cases the code even worked properly, apparently LabVIEW created a event registration refnum to the memory address specified by the constant that was connected to the input of register for events. It was only in case of multiple instances trying to use the same event registration refnum constant when I ran into troubles, I was unable to use the constant registration refnum with multiple event structures (surprise). I am confused of the fact that I did not get an error from event registration refnum, I think that might be a bug in LabVIEW. I am quite as surprised that LabVIEW did not crash when I used invalid reference for creating an event registration. When I was debuggin the code, not-a-refnum node returned false indicating that the constant refnum was a valid refnum, which I think is another LabVIEW bug.

    My question for you guys is, what would be the best way to improve the user experience to avoid this problem for occurring. One idea I have is to have refnum types to have a right click option to set them to null reference. That still would not fix the issue but would help to clear references. Another idea would be to visually change the appearance of the reference controls, indicators and constants that do have a non-zero value, so that the programmer would have a way of knowing that the reference type is non-zero. This visual difference should be rather visible, it is very seldom the case that you actually want to use a constant value for a reference type. Usually you just want your reference values to be zero.

  16. This is now CAR 280980. I aim to fix it in the next version of LabVIEW (not 2010 SP1 ;)). The current solution we're considering is allowing overriding properties to have different long names, but to always show the name from the base class.

    Thanks Mike, your proposed solution makes sense to me.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.