Our code this year (written in LabVIEW) runs really slow. Extremely slow. I have taken out all the refnums in teleop and in periodic tasks, but this did not seem to help. This would normally not be a problem, but we have several (4) PID loops update in teleop (running on CAN Talon SRX’s), and if they are not updated every ~120ms they will tell the motor to stop spinning. Right now, teleop runs every ~100-200ms (measured with “Elapsed Times.vi”). This is a huge problem when we are shooting and need our two wheel motors to spin at exact and fast speeds. Although at this point in the season we aren’t adding much code, the problem seems to be getting worse. It also may be worth noting that we are using the LabVIEW 2016 Vision Example to find the goal coordinates, although it is disabled with a global variable when not in use.
Does anyone have any fixes/ideas/suggestions/tips as to how to speed up our code?
Here is the link to Team 303’s LabVIEW Robot Code if it helps anyone. Feel free to redistribute if you so please.
I am unable to try out your code. You are using several Vis that are not included in your project or in the WPI library.
Are any error messages shown on the Driver Station message display? Catching and displaying errors slows down a LabVIEW program.
It looks like you are doing a lot of Talon SRX status checks in Teleop. Do those all need to take place every time a data packet arrives, or can you move some of the processing to Periodic Tasks?
Your Teleop is very busy and I’m finding it a little hard to follow without signposts. It all looks connected in a big collection of wires. Are there any functional groups that could be split out into individual SubVIs? That might clean up how the code looks and make it easier to understand.
@Alan - You need to install the NavX library to have his code load properly.
Looking at Teleop… Oh my…
There is a lot going on here. Forgive me if I miss something. Generally, when your code starts getting really complex, it’s a good idea to start creating SubVIs. It makes the code a lot easier to understand.
I’m not seeing anything that stands out. The only Wait blocks you have are in Periodic Tasks, which is good.
Are you trying to run this as built code or by pressing Run on Robot Main? I’ve experienced slow downs when running Robot Main if I have too many running LabVIEW windows open. This occurs because it has to sync all the values from the robot back to the front panel, and the issue gets worse if your are probing values as well. I can see how having just the Teleop window open might cause it to lag since there are so many Front Panel controls and indicators to update.
I didn’t try to run your code, but just looked at it.
Please run the code and give some indication of CPU usage from the DS chart. If your usage is high while the robot is disabled, your periodic tasks may be running too fast or doing too much.
If teleOp has high CPU usage when the panel is open, it is because you have lots of debug info shown and updated frequently. When you run without opening the panel, it should be far better, and will be better still when built and deployed.
Don’t forget that you can also put the Support Code/Elapsed Times into your teleOp code to see how often it runs. Your log file will also how how many of your teleOp control packets are not being processed.
Please post some more data and I’ll be happy to make a suggestion.
I split Teleop into a few more subVIs and used the clean-up-diagram button, so it should be more readable now. I also took out most of the debug indicators and controls, and necessary Talon SRX get status’, since we don’t need them anymore. We were running the code from a build-deploy, and we got “Not running fast enough” errors a few times every second as of yesterday.
I will test again today and post logs when I get to our workshop.
So one of things that you can do is remove all the get/set refnums in you’re project and bundle them together like you have done but make it a type def. I’m currently busy with other things so I do apologize if I’m not going into very much detail, I’ll sit down a write a proper response to your request however I will leave you with a link that another user had passed along to me when I was trying to optimize my code. Hope this helps!
I looked at your updated code, and still don’t see anything that scary. Moving the code into subVIs helps readability, but won’t affect performance.
So do you have CPU numbers? Do you have a log file? Do you have an elapsed time for TeleOp?
The only thing that looks like it may be excessive is the amount of stuff you have inside the 10ms periodic task. Doing NavX and CAN status and quite a few network tables may add a pretty hefty background load which would be present even during disabled mode. So if we see the logs, I can know roughly what that takes.
This might be a ridiculous question to ask but would finding a way to move the majority of this stuff to a state machine be of any use when trying to make the code efficient? I feel like there’s a few things that could probably go without the constant update that the Teleop.vi has. Do point out if I’m wrong in this case. Also Bradley, I’ve noticed that there are some unused values in your teleop code that can be attributing to the whole clutter issue that is evident in the project overall; I would assess whether or not you need those values anymore. Great job on your code however I’ve had fun puzzling your code out and have been able to glean a few concepts from this that are rather interesting and will keep a note on them for next robotics season. I’ll continue to with my efforts and will point out anything that I see that might want to be addressed.
I’m still not seeing anything that would ultimately cause the “Not running fast enough” errors. As The_Waffling said, you could replace that huge Refnum cluster to all the Joystick, Motor, Robot Drive, Solenoid, and Encoder Refnum_Get functions. If you’re debugging, those controls will still get updated and that is quite a few front panel controls to update every 50ms. Keep in mind all of this is going over the network.
You should definitely check your CPU usage like Greg said. If you’re running at 100%, that will likely cause you issues. You can easily check that using the Driver Station or you can Profile your program within LabVIEW while it’s running on the target.
The CPU and elapsed time of teleOp are hard numerical quantities that will help you diagnose if you have a problem, and what that problem likely is. It is like the doctor taking your temperature and blood pressure. If you don’t measure these things, you may very well be trying to fix something that isn’t broken or making something worse.
I glanced at your code and didn’t see anything horrible. The next step is to measure. Without that, we quickly get into code poetry and opinions. I much prefer to stay on the engineering side of programming. So, please, when you have access to the log files or the robot, post the CPU usage for a couple robot modes. Look at or post some log files. And if you think you have an issue with teleOp, add the Elapsed times VI, run the code, start teleOp on the DS, and open the subVI to see what the elapsed time is.
Okay so after doing a lot of clean up in the teleop in order to see what’s going on, I noticed that there are some values that are being written in teleop to global variables but never read anywhere else. Is there any particular reason for doing that. another thing that you can do for your begin.vi is replacing the write global variable that you have going with a funcional global variable (FGV) since the only place your are needing all that information is in autonomous. Like everyone else has said though check your CPU usage and try to locate any logs that might be pertinent to this issue. The logs will answer several questions.
we had an issue similar with our robot, trogdor. our autonomous wouldn’t work one time because it was an issue with our talons. not with the coding itself, which everyone believed it to be, but the hardware.
Ok here is my first round. I have done a lot so I am not going to tell you everything should work on the first try. I am still working on autonomous and I will update that as soon as possible. I have a lot of it done already. I am also trying to make the code do what I think you are trying to get it to do. I am available for questions.
If you message me your email, I can add you to a google drive folder that our team has been using to transport and store code. Thank you!
I don’t quite understand how a functional global variable would help in this situation. We are only writing the variable once (in begin.vi), so why would the data need to be feed into a loop/shift register? Thanks for your help.
I edited a lot of things in your code. I added functional globals or action engines as I call them. I reorganized the timed tasks to make the dashboard updates less often. I then added the action engines to get the data that you collect and store it for use everywhere else in your code. I updated the teleop vi. I think there is still more we can do there but I wanted to get this into your hands now so you can start to see and try understanding what I did.
I started working on the auto mode. I got through a lot of it. I am trying to do my best to understand what you were doing.
Again let me know if there is anything else I can do to help you understand what I did.
This thread seems to be trending into a “alternative ways to write the same code” thread. But the original post was about performance. Nobody is talking about performance.
LV is a language. There are infinite ways to write something. There are tradeoffs to each of those solutions. Rewriting code to be different without measuring and addressing the goals – in this case, performance improvement – is not good engineering.
When I loaded the code several days ago, it was broken and I didn’t have much time to spend on this. Has someone, anyone, run this code to make basic measurements? Without this data, everyone is making recommendations on hunches or past experiences. This doesn’t need to be theoretical work.
Did you get a chance to look a the code I put together? Do you have questions?
I do appreciate that sometimes code does not have to be rewritten if it works no matter if it uses good programming styles or not. It was not my intention when I started, to rewrite the code for this team. The more I dug into the code the more problems I saw. It seemed easier to fix the problems and make the code easier to read then to try to keep scrolling back and forth to understand the code. As I made things easier I found mistakes that I would not have found if I just let the code alone. They were calling a joystick that was never established in the begin file. They were call for a solenoid valve that was never established in the begin file. They were enabling and disabling some motor controllers in teleop. This is part of the reason the code was running slower than expected. Even if I did not change how the teleop timing was working the code is easier to read and easier to edit. I try to teach LabVIEW programming classes every summer to local teams in my area.
I also thought it would be a good opportunity to show them how to use proper programming techniques. This will help them write better more efficient, easier to maintain code in the future. I think LabVIEW gets a bad wrap around this forum because people feel that it does not work well. Part of the problem is that people are not using it to the best of its’ abilities. LabVIEW is easy to use. That is a strength and a weakness. People think that they have figured out how to use LabVIEW just because they get something to work. I do not work for National Instruments but I have over 16 year of programming experience with LabVIEW and I try to help people see how easy and efficient it can be if done with good programming standards.
That is why I published our code every year and why I took the time to help these guys out.