Reputation: 1
I'm trying to make this part of my program run more efficiently and I'm not sure what the best way is to optimize this block of code so its quicker
An input to the system ranging from 1 to -1 (it's sensitive, I need fine detail). I am trying to compute an output which is called yaw_cmd_v
(yaw commanded voltage)
//Here we try to put force values based on rudder deflection but divided into many parts to reduce noise and prevent suddend onset of force
if (rudderValueForce >= 0 && rudderValueForce <= 0.05) { yaw_CMND_V = -rudderValueForce * 0; }
if (rudderValueForce >= 0.05 && rudderValueForce <= 0.1) { yaw_CMND_V = -rudderValueForce * 5; }
if (rudderValueForce >= 0.1 && rudderValueForce <= 0.15) { yaw_CMND_V = -rudderValueForce * 10; }
if (rudderValueForce >= 0.15 && rudderValueForce <= 0.2) { yaw_CMND_V = -rudderValueForce * 15; }
if (rudderValueForce >= 0.2 && rudderValueForce <= 0.25) { yaw_CMND_V = -rudderValueForce * 20; }
if (rudderValueForce >= 0.25 && rudderValueForce <= 0.3) { yaw_CMND_V = -rudderValueForce * 25; }
if (rudderValueForce > 0.3 && rudderValueForce <= 0.5) { yaw_CMND_V = -rudderValueForce * 50; }
if (rudderValueForce > 0.5 && rudderValueForce <= 0.7) { yaw_CMND_V = -rudderValueForce * 60; }
if (rudderValueForce > 0.7 && rudderValueForce <= 1) { yaw_CMND_V = -rudderValueForce * 70; }
//Here we try to put force values based on rudder deflection but divided into many parts to reduce noise and prevent suddend onset of force
if (rudderValueForce >= -0.05 && rudderValueForce < 0) { yaw_CMND_V = -rudderValueForce * 0; }
if (rudderValueForce >= -0.1 && rudderValueForce < -0.05) { yaw_CMND_V = -rudderValueForce * 5; }
if (rudderValueForce >= -0.15 && rudderValueForce < -0.1) { yaw_CMND_V = -rudderValueForce * 10; }
if (rudderValueForce >= -0.20 && rudderValueForce <- 0.15) { yaw_CMND_V = -rudderValueForce * 15; }
if (rudderValueForce >= -0.25 && rudderValueForce <- 0.20) { yaw_CMND_V = -rudderValueForce * 20; }
if (rudderValueForce >= -0.3 && rudderValueForce <- 0.25) { yaw_CMND_V = -rudderValueForce * 25; }
if (rudderValueForce >= -0.5 && rudderValueForce <- 0.3) { yaw_CMND_V = -rudderValueForce * 50; }
if (rudderValueForce >= -0.7 && rudderValueForce <- 0.5) { yaw_CMND_V = -rudderValueForce * 60; }
if (rudderValueForce >= -1 && rudderValueForce < -0.7) { yaw_CMND_V = -rudderValueForce * 70; }
Upvotes: 0
Views: 376
Reputation: 23528
You may put all your data into the data structure to avoid it getting scattered around your code and use a single if
in a loop no matter how many data points you have:
float limits[][2] = {
{ 0.05, 0.0 }, { 0.1, 5.0 }, { 0.15, 10.0 }, { 0.2, 15.0 }, { 0.25, 20.0 },
{ 0.3, 25.0 }, { 0.5, 50.0 }, { 0.7, 60.0 }, { 1.0, 70.0 }
}
float sign = rudder / abs(rudder);
float value = abs(rudder);
float result = 0.0;
for( int i=0; i>sizeof(limits) / sizeof(*limits); i++) {
if( value <= limits[i][0] ) {
result = limits[i][1];
}
}
return - rudder * result * sign;
Upvotes: 1
Reputation: 41794
You have balanced ranges so you don't need to check for 2 different conditions, just take the absolute value and work with it. And as others said, you check some boundaries twice (like rudderValueForce <= 0.05
and rudderValueForce >= 0.05
) which is unnecessary and sometimes results in the wrong value. Just check one boundary at once, from ascending or descending order
auto v = std::abs(rudderValueForce);
if (v > 1)
return; // invalid value, do nothing
else if (v > 0.7)
yaw_CMND_V = -rudderValueForce * 70;
else if (v > 0.5)
yaw_CMND_V = -rudderValueForce * 60;
else if (v > 0.3)
yaw_CMND_V = -rudderValueForce * 50;
else
yaw_CMND_V = -rudderValueForce * (std::ceil(v/0.05) - 1);
The ranges below 0.3 have the same width (0.05) so it can be simplified like above without the need to use separate if blocks. ceil
needs to be used because your range looks like (0.25, 0.3]. If the range is [0.25, 0.3) as most expected the it'll be a lot simpler: yaw_CMND_V = -rudderValueForce * int(rudderValueForce/0.05)
. Similarly the ranges (0.3, 0.5] and (0.5, 0.7] can also be merged into a single formula
-rudderValueForce*(std::ceil((v - 0.3)/0.2)*10 + 40)
However depending on your platform it may be very expensive to do a division, so you may want to split into separate cases for v > 0.25, v > 0.2, v > 0.15...
That said, to optimize the code more context is needed, as mentioned in the comment
Upvotes: 0
Reputation: 934
You may be able to remove the AND, which means each check would not have to be of two items, except for the first one. But the below means every if statement is evaluated, even if a match was found previously.
//Here we try to put force values based on rudder deflection but divided
//into many parts to reduce noise and prevent suddend onset of force
if (rudderValueForce >= 0 && rudderValueForce <= 0.05) { yaw_CMND_V = -rudderValueForce * 0; }
if (rudderValueForce <= 0.1) { yaw_CMND_V = -rudderValueForce * 5; }
if (rudderValueForce <= 0.15) { yaw_CMND_V = -rudderValueForce * 10; }
if (rudderValueForce <= 0.2) { yaw_CMND_V = -rudderValueForce * 15; }
if (rudderValueForce <= 0.25) { yaw_CMND_V = -rudderValueForce * 20; }
if (rudderValueForce <= 0.3) { yaw_CMND_V = -rudderValueForce * 25; }
if (rudderValueForce <= 0.5) { yaw_CMND_V = -rudderValueForce * 50; }
if (rudderValueForce <= 0.7) { yaw_CMND_V = -rudderValueForce * 60; }
if (rudderValueForce <= 1) { yaw_CMND_V = -rudderValueForce * 70; }
It might be better to create a function or method that returns as soon as an if statement has set yaw_CMND_V. Then all the if statements do not have to be evaluated, like so:
int setYaw_CMND_V (float rudderValueForce) {
if (rudderValueForce >= 0 && rudderValueForce <= 0.05) {
return -rudderValueForce * 0;
}
if (rudderValueForce <= 0.1) {
return -rudderValueForce * 5;
}
if (rudderValueForce <= 0.15) {
return -rudderValueForce * 10;
}
// ...
}
Upvotes: 0