Jump to content

GregFreeman

Members
  • Posts

    323
  • Joined

  • Last visited

  • Days Won

    5

Everything posted by GregFreeman

  1. I agree, LabVIEW lacks in readability when it comes to doing math like this, but there's not much you can do about it. Now with wire labels it helps a little bit because you can label your intermediate "variables" so-to-speak. You've made it about as clean as you can. I'm guessing the formula node has some sort of overhead on a "per call" basis so calling it in the for loop is causing the long execution times as compared to the primitives. I think, in general, primitives are always the best option in terms of performance due to optimization (but someone else can probably give better detail on the why than I can so I'll just leave it at that).
  2. You don't have to tell me twice. If my boss asks where I'm going, I'll just say Stephen told me to go home because he agreed with ShaunR. I do already read all the data at once (comes out of a CAN bus so it's just a single read that returns all message data), it's just parsed differently depending on the type of message. I have kind of been toying with different ideas and what I ended up doing was creating a "message parser" class, which has children parsers. I have a method that checks the class type, then instantiates the correct parser. This parser has methods that know how to act on the message of that particular type. It gets all the data, like suggested above, then sticks it into a class. This way I keep all the message parsing encapsulated in its own class, and can reuse the parser class throughout the different modules in my code where messages are received and needed to be managed this same way. I may be off base but it seems to work, keep things more loosely coupled, and be reusable. I can't be way off base then, I assume! But, if down the road it causes problems and I need to refactor, I'll chalk one point up to lessons learned.
  3. So, just to come full circle on this post, what I have ended up doing is the following: I realized, as my message comes in it consists of two things, a numeric value and an array of data which goes into a class, call it BaseMessage. I then had type n message inherit from this class, and grandchildren messages inherit from that. I thought about it using all of your suggestions, and I came to realize, the first level of inheritance was not necessary. What really is happening is I am using the data from the message received to create a new class, and this new class doesn't care about the byte array of data as a byte array. Therefore, it doesn't need it in order to maintain state and as such doesn't need to inherit from the BaseMessage class. It only cares about what that data represents once it's been taken out of its byte array form (temperatures, pressures etc). So, when I create my classes, the "constructor" now takes the BaseMessage as an input. My new class is being created from the data in BaseMessage, but is really not a base message. Taking this step begins to clear things up quite nicely. Any comments on this are appreciated, but it seems to work quite well. Thanks for all the suggestions.
  4. ^^^ This! I have an absurd inheritance heirarchy trying to encapsulate the specific functions for each "step" in the parsing into their particular classes within the heirarchy. That is what really brought me to ask this question in the first place. Maybe I'll just make a message parser class and stick all methods for parsing in there, and it can return the correct message with it's private data populated, allowing me to scrap some of the parent message classes (which are really there only to hold their parsing functions and a few properties that apply to all child messages).
  5. In my cross post to here does the response I got seem valid? I am still questioning it.
  6. Correct, I actually meant to put that in there. I was thinking, "it would be nice if I could change the message order" while I was writing my post. It definitely makes sense, but implementing it could be a different story. I'll see where I can get on my own but may come back for suggestions and clarifications.
  7. Back with another "there-must-be-a-better-way" question. I have a situation that may work, but feels icky. I have an incoming message that has an array of u8 data. A subset of this data is parsed to determined the "type" of the message. There are 4 different types of messages so I have a class for each type, and a factory that creates the proper one based on the type. Then I have a method for each type that futher parses the u8 array (the array is parsed differently based on message type). This gives me a bit more information, and I finally know the "final" type of message so I can generate that class. Basically I have a hierarchy that looks like this (ugh didn't format correctly but you get the idea) base message / / \ \ type1 type2 type3 type4 / | \ finalsubclass The issue is, because I find out a little more information with each step of parsing the u8 array, which tells me how to parse the next step I keep having to "downcast" my class which means continually trying to preserve data that already exists in the parent class. I have seen the methods mentioned here but it gets really hairy with multiple levels of children. From purely a cosmetic standpoint, the levels of inheritance seem to make sense because they match the protocol of the messages I am receiving (there are multiple messages that can come in, these can be of different types (this is the first child class), and those types have children (grandchildren class)). I'm just looking for suggestions that may make my life easier.
  8. Shaun, yup, this is what I plan on doing. I just meant the ctual CAN read I can't do in every zone
  9. Sorry, to clarify I have CAN bus messages classes, which have a "generate can bus message" method that formats that class's data and returns it in a format the CAN driver accepts. This above sentence is the route we have gone when refactoring. Breaking these things out into more dedicated processes. I think most of the problems arose from the following: There is firmware on the hardware that runs, which we are trying to simulate. When the hardware is present we do nothing, the hardware does everything itself. So, we are not interfacing with the hardware at all in our application. We are purely writing a simulator should the hardware not be there. If the hardware is present, there are multiple zones. Each of these zones has its own buffer with the same CAN bus split and wired into it. Because of this, a single message can be sent out on the CAN bus, but each zone can still read that same message. Now, when I simulate this idea of multiple zones in software, I don't have this ability. I can't structure it the same as the hardware (multiple zones each reading the same CAN message) because can't have multiple readers of the CAN bus in my software. So, I have to take the idea James suggested and read in a single place, pass it off to the zone managers, they respond, then write in a single place. Does this make a little more sense? I think the confusion came from trying to have the same architecture as the firmware (multiple zones all reading the same message off the CAN bus) but this is not possible in a simulated environment on the PC.
  10. Thanks James, I agree. I will go with my "gut feeling" on this one and can modify if needed. That said, in doing the architecture design (we're sticking this into an existing code base which can often be a mess) we realized the current "manager" approach may not work as expected when some external devices are simulated, some are real etc (not just zones but other devices on the system). So, this problem may be a non-issue after the rearchitecting is finished. We shall see...
  11. It's not so much that, but that fact that I don't know if the zone itself should handle the writing to the CAN bus, or the manager should. I understand how to make it work if I want the zone to do the writing, but should the zone own the WriteToCan method in the first place is what I'm struggling with.
  12. I have a pretty simple process that I'm sticking in parallel to some other things. It is a "manager" that holds in it's private data an array of "zone" classes. These zones are essentially simulated devices. When an incoming message comes in (CAN bus), that message contains information on which zones the data applies to. Some messages are broadcast so the same data applies to all zones, some are zone specific, with the zones to which the data applies to being specified within the incoming message The message data is then applied to those specified zones (i.e. their private data is updated accordingly), and then an outgoing message is created to be sent out. I am not exactly sure how to handle the outgoing messages when I have zone specific data. For instance, a message comes in and says update zones 1,3,and 4. So I update those zones, but then I need to respond back out with multiple messages, saying zone 1 updated, zone 3 updated, zone 4 updated. So I have a couple thoughts. The way I have it now, in the "managers" private data I have a "zones to execute" array and I also have a single outgoing message. When an incoming message is received, I inject the proper outgoing message that will be sent. When the outgoing message is being sent, loop through the zones to execute array, find those appropriate zones, grab the necessary data, update the "outgoing messages" data and send it. Or, I could have my "outgoing message" class hold the "zones to execute" but follow a similar style to the above. Instead, I'd use an accessor to get the zones to execute out of the message class. Finally, I could still have the "zones to execute" in the manager class. But, each zone could hold a CAN bus reference and they could handle sending out the CAN messages from within themselves. I'm not sure I like the idea of the single CAN reference being held by multiple different zones, though, when it is the manager handling the opening and closing of the reference. Does anyone have a better suggestion? If you need clarification let me know.
  13. I feel your pain. I am no GIMP or photoshop wiz either, which makes certain things quite difficult. I am running into this more lately, where customers say "I want it to look like .NET does" but they want to use LabVIEW for the sake of quick development. I understand the NI "branding" that comes with a LabVIEW-looking UI, but I think it is important for NI to make some headway on this front to allow us more modern UIs. To be sure, the silver controls were a step in the right direction (though I still find them to take up way too much space). But, when I drop a .NET control and see the ridiculous amount of functionality available, I realize LabVIEW definitely is still lacking.
  14. If I want to create something similar to a "static method" in c++, is it just as simple as removing the object input and output terminals from a VI which is placed within a class? If so, will this avoid object creation, or does LabVIEW still create the object?
  15. I'm assuming since you are using clusters you are not using RT FIFO's. That said, if you are using RT FIFOs, I believe waveform attributes are lost when using them so be aware of this.
  16. I'm wondering how people feel about mixing messaging architectures in an application. For instance, I have some reusable code that fits the actor framework nicely due to its dynamic launching of VIs that it already has built in. But there are other parts of my application with static loops for which it is much more intuitive to the average user to use LapDog. Is it in general bad practice to mix and match the two; better asked, would it be confusing if you picked up a project that used both?
  17. Let there be light! Thanks for your patience and persistence! So, for type checking, the child class's methods would just have the correct class type on the connector pane, then call the parent method inside themselves (assuming they want the parent classes functionality such as with add or delete)? I think I'd prefer to be lazy and just force the programmer to know not to mix types in the list.
  18. Just bear with me as you read this...I think I realized something in the middle of my post. Shane, First thanks for the time to draw this up. This is exactly what I was envisioning when reading your explanation, but I still see the issue from my first post. This is forcing my classes to inherit from the same base class, solely for the purpose of managing them both in this one specific user interface. To stick with the classes in your example, lets say I wanted to use "Not so random class" in another project. I am forced to bring along "random class", even if the only purpose for random class and the inheritance I have set up is for the class to work with this one specific UI, and the classes can run on the same wire. I guess what I'm thinking of is like a template in c++. You'd do List<Not so random class> mylist and you could create this list without dealing with inheritance from any object. Then you could do (ignore the spaces in variable names) List<Not so random class> mylist mylist.push_back(instance of not so random class) Not so Random class nsrc = mylist.front() String ListboxItem = Not so random class.GetListboxString() Now if I wanted to use Other Not So Random Class... Oh, wait a minute...it just clicked I think. Even with the template method you'd still need the line in red not to be specifically equal to Not So Random Class, but instead equal to Random class (i.e. the base class) for it to work when switching out the data type being used by the template Therefore, I think I do have to have them both inherit from the same base class to make this generic. I don't know why I was so opposed to this in the first place; I think it just seemed counter intuitive to have two classes which may be totally unrelated, inheriting from the same base class, just so they can run on the same wire in my UI.
  19. I think I'm thinking too much and not coding enough . I understand this but still see some potential issues (which may not be issues at all) so I will implement it when I get free time, then post back with specific questions to what I have done. I think that will help get everything cleared up.
  20. Shane, I actually read that topic the first day you posted it, but I will revisit it to see how it may apply. The reason I have the list box is actually so I can do configuration as you suggest. Depending on the type of test each step will be executing, there may be different parameters necessary. So, I was going to have a different self displaying object based on the type of test that was chosen, just like a configuration dialog. But, all of these different test configurations would be test steps. I wanted to put all these test steps in an array -- if the user created a new step, I would just create a new test step object and add it to the array; if the user deleted a step, delete it from the array; moved a step in the listbox, I would move it in the array etc. This is where Shaun's idea comes into play. Then, when the user saves, I would go through all the test steps and get the "next" step in the array and put it in the private data of each current step (the base Test Step class's private data because every test step will need this information). Each test step would have an associated "do test step" (or some other name) method which would define what would be done for that test step. This way I can just call a test step and when it finishes it will pump out the next step to be enqueued from its private data. It can also have in its private data where to go on different errors for that step etc. This would allow for new test step types etc to be created on the fly and just plugged in to the configuration dialog. So, this is what I was envisioning, I'm just not quite there yet in terms of handling this add,remove, reorder functionality in a generic way (as I said, so I don't have to use this for test step objects only), mostly because I'm not too familiar with OOP so I have some trouble wrapping my head around a few of the ideas. I'm sure once these ideas click, it will seem simple.
  21. Thanks for the clarification. I guess what I'm getting it is for, say, the add method in the base class TList, to make it generic and act similar to an "array of variants" like you suggest, do you just make the input a "LabVIEW object" so it can accept any class you wire to it? If I'm still off, would you mind posting a small example with just one method so I can hopefully understand correctly. Edit: I'm basically trying to avoid overriding add and delete etc if I don't have to because the base classes implementation will be fine. But, you can't put a TList in its own private data. I keep trying to relate to c++ templates, but with those you can specify the type, and I don't quite see how to do that here. I'm banging my head trying to get this haha. A quick example would probably be the fastest way to clear this up for me, just knowing the way I learn.
  22. Thanks James. We actually have something like this internally, and I agree it's a really nice way to do configuration. I also agree X Controls can be a huge pain and I have battled with them on multiple occasions. Somehow they always end up working, but are often messier than I'd like. Maybe I will convert it so the information is dumped out into classes, rather than csv files or super clusters. With regards to what Shaun said, would there be a TTestItem class that held an array of test items in its private data? Or would it be something different? If this is how it would be configured, excuse my ignorance but I am a bit confused how TList would handle all the adding and removing of items in a the private data of a child class? It seems I would have to provide a protected accessor method to get the array of items for every child class I make, so that no matter the items I use the TList may call the accessor, get the array of private data, and manipulate it. Is this correct, or am I overlooking something?
  23. I am going to respond to these posts as I listen to the commotion of the little girls birthday party in the apartment across from me. So forgive me if I accidentally throw random words into my response because it's what I'm thinking I want to say to my neighbors I think this is pretty much on par with what I want. Thanks for the info. I can read into this more and play around with it to see where I get. Number 2 is what i was thinking I'll try different things, see how they work out and post back. Then hopefully you guys can give me more direction then, specific to the code I have written. It's usually easier for me to wrap my head around things once I've coded something up and get feedback on that. Thanks!
×
×
  • Create New...

Important Information

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