Jump to content

Tomi Maila

  • Posts

  • Joined

  • Last visited

  • Days Won


Everything 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. APPLY NOW
  2. At JKI, we have found that a professional user interface design can make a huge difference for LabVIEW applications. That’s why we’re very proud to announce we have just released the JKI Flat UI Controls for LabVIEW, a beautiful, professionally-designed set of LabVIEW controls that we use on some of our own projects at JKI! We hope that by sharing these with the community, we can help make it easy for just about anyone to build their own beautiful and intuitive user interfaces in LabVIEW. Learn More & Download
  3. 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".
  4. 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.
  5. I recently posted a more detailed LabVIEW Idea Exchange post related to this topic. Check it out and kudo it so that we get type parameters and parametric polymorphism to LabVIEW.
  6. 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!
  7. 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
  8. 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...
  9. 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 p.s. See Joel's quick intro to functional programming if you are unfamiliar with the concept of functional programming.
  10. 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
  11. All, I am happy to announce that I am back in blogging on ExpressionFlow. I'm trying to cover more theoretical topics around visual programming and discuss new fresh approaches. I'd like to invite everyone to follow the blog and @expressionflow twitter account. url: http://expressionflow.com twitter: @expressionflow facebook: https://www.facebook.com/expressionflow Please let me know the kind of topics you'd like me to discuss. There's lots of cool topics on my mind already but I would love to hear from you, what would be something interesting for you all. Thanks, and happy Thanksgiving for everyone! Tomi
  12. Excited about blogging @ExpressionFlow again

  13. Would you like to report this to NI as a bug on application builder.
  14. I have seen this error a few times when the application builder has not managed to successfully built a valid executable but hasn't returned an error either. Last time I saw this error was when there was not enough memory in the build machine for LabVIEW to build a proper executable. As a result the executable didn't really contain anything and the final size of the executable was too small. When executing it, you got this error, which was natural because the executable was corrupted. The problem really was in LV application builder. We fixed the issue first time by getting LabVIEW to address more memory in 32-bit machine during the build and the second time by moving the 32-bit LabVIEW used for building to 64-bit machine.
  15. You know you can cluster event registration refnums and wire the cluster to the input of event structure.
  16. 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: Create user event refnum For each process receiving the user event create event registration refnum for that particular user event 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? 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.
  17. Equality fails. The first element in the brackets of the boolean indicators is the value of the indicator after the first iteration and the second value is the value of the indicator after the second iteration of the outer loop. event registration equality fails.vi
  18. 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.
  19. You must be kidding? 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.
  20. 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.
  21. 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.
  22. 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 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?
  23. 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. 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. 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.
  • Create New...

Important Information

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