Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   Programming (http://www.chiefdelphi.com/forums/forumdisplay.php?f=51)
-   -   Reducing code complexity (http://www.chiefdelphi.com/forums/showthread.php?t=116542)

MikeE 30-04-2013 19:04

Re: Reducing code complexity
 
Quote:

Originally Posted by apalrd (Post 1270351)
In LV and C I usually use a typedef enum to store the state, and a switch for the states.

As a team that uses Java (based on ME) I'm deeply envious of your casual use of the enum word.
Like many things in life I didn't really appreciate them until they were denied to me.

RyanCahoon 01-05-2013 04:13

Re: Reducing code complexity
 
Quote:

Originally Posted by MikeE (Post 1270387)
As a team that uses Java (based on ME) I'm deeply envious of your casual use of the enum word.
Like many things in life I didn't really appreciate them until they were denied to me.

It's possible to emulate enums using regular Java classes (though the code becomes a bit more verbose and not quite as readable). In addition to the method outlined in the linked article, you can also use static final int variables, such as are used in WPIlibJ, though you lose type safety that way.

apalrd 01-05-2013 12:55

Re: Reducing code complexity
 
Quote:

Originally Posted by MikeE (Post 1270387)
As a team that uses Java (based on ME) I'm deeply envious of your casual use of the enum word.
Like many things in life I didn't really appreciate them until they were denied to me.

I'm not sure how I would write code without the enum. It's possibly one of the most useful programming constructs I have ever used.

Lookup/Interpolation tables are also my favorites. I'm surprised I don't see them more in FRC.

As a note to LV users in this thread, you can make a typedef enum in LV by making a custom control (go to New instead of New VI and it's an option), set it to 'strict type def' and drop an enum. Anywhere you use it, it will auto-update to the type def, so you can change the control (.ctl file) and all of the constants and controls will update. When you create it, the order will define the associated number (it's to the right of the name), which is what you get if you use the enum as a uint. A similar method works for typedef struct, you just need a Cluster full of stuff.

MikeE 01-05-2013 13:11

Re: Reducing code complexity
 
Quote:

Originally Posted by RyanCahoon (Post 1270605)
It's possible to emulate enums using regular Java classes (though the code becomes a bit more verbose and not quite as readable). In addition to the method outlined in the linked article, you can also use static final int variables, such as are used in WPIlibJ, though you lose type safety that way.

I'm aware of the class approach but I don't see that the added complexity is warranted.
We do use static final int and a naming convention to simulate enum, but of course you lose the benefit of syntactic typing constraints.

My point was to subtly indicate that some of the earlier suggestions don't translate directly to the current platform due to Java ME limitations.

MrRoboSteve 01-05-2013 13:31

Re: Reducing code complexity
 
My Java skills are a bit crusty but this should give you an idea.

Code:

// Enum replacement for State in my previous post
public class State{
  public static final State Initializing = new State();
  public static final State Waiting = new State();
// and so on
}

State state = State.Initializing;

// No support for instances in switch in Java

if (state == State.Initializing)
{
}
else if (state == State.Waiting)
{
}
// and so on


Kevin Sevcik 01-05-2013 15:03

Re: Reducing code complexity
 
Quote:

Originally Posted by SoftwareBug2.0 (Post 1270330)
This year, my team actually used the command based stuff, and I can't recommend it with a straight face. You can kind of get towards a problem some call "callback hell".

I'm curious what sort of horrible difficulties you ran into with the command-based template. I used it this year and it greatly simplified organizing and modularizing code compared to working with the SimpleTemplate. The biggest headaches I ran into was forgetting to statically initialize subsystems to NULL, making it repeat fire discs when the trigger was held, and remembering that commands attached to events are actual object instances that are created once at program initialization. The latter was probably the biggest headache since it meant reworking the shoot command so it would check the joystick inputs and look up the selected setpoint itself instead of getting instantiated with it. The pluses were pretty significant, since it greatly simplified event sequencing for autonomous and firing sequences. I think the biggest limitation is that you can't easily implement a true general purpose Finite State Machine using Commands and CommandGroups since CommandGroups are just static lists of Commands to run one after the other(ish). No transitioning from one state to a variety of others based off inputs and such.

So, what's your beef with command based stuff?

Ginto8 01-05-2013 15:08

Re: Reducing code complexity
 
Quote:

Originally Posted by Kevin Sevcik (Post 1270814)
I think the biggest limitation is that you can't easily implement a true general purpose Finite State Machine using Commands and CommandGroups since CommandGroups are just static lists of Commands to run one after the other(ish).

There's nothing saying you can't make your own Command to do it, though. CommandGroups are just Commands implementing a special case of a state machine. Also, an interesting thing to note is that if you use requires(), each Subsystem acts as a state machine with Commands as the states (and it's really easy to add a state for these, as it just involves adding requires() to a Command's constructor).

Kevin Sevcik 01-05-2013 15:14

Re: Reducing code complexity
 
Quote:

Originally Posted by Ginto8 (Post 1270817)
There's nothing saying you can't make your own Command to do it, though. CommandGroups are just Commands implementing a special case of a state machine. Also, an interesting thing to note is that if you use requires(), each Subsystem acts as a state machine with Commands as the states (and it's really easy to add a state for these, as it just involves adding requires() to a Command's constructor).

Yeeeees... I can see how you could make that work, though I think you'd end up with either one huge command or your state machine logic spread over a half dozen files. I'll have to think on it a little more now that there's not a robot to finish already, dangit.

Ginto8 01-05-2013 15:32

Re: Reducing code complexity
 
Quote:

Originally Posted by Kevin Sevcik (Post 1270821)
Yeeeees... I can see how you could make that work, though I think you'd end up with either one huge command or your state machine logic spread over a half dozen files. I'll have to think on it a little more now that there's not a robot to finish already, dangit.

Check out the the CommandGroup source code for some inspiration... Though personally, I'm a fan of the "Subsystem-as-State-Machine" model.

Gigakaiser 01-05-2013 20:26

Re: Reducing code complexity
 
I highly recommend separating your code into classes per subsystem. In terms of condensing your code you will see the most benefit if you do that - it will also make your code easier to read while some of the other methods will save very little space and make your code more difficult to read.

davidthefat 01-05-2013 20:56

Re: Reducing code complexity
 
Just a hint: take full use of classes and inheritances.

SoftwareBug2.0 02-05-2013 00:37

Re: Reducing code complexity
 
Quote:

Originally Posted by Kevin Sevcik (Post 1270814)
So, what's your beef with command based stuff?

My major beef with the command based stuff is that it makes it harder to understand the system as a whole. If you have commands that don't complete immediately, it can be hard to know exactly what is happening. You end up at a place with neither a simple set of variables that tells you everything that's going on nor a straightforward callgraph to follow.

Here's a more minor problem: Our autonomous mode became

Code:

correct angle -> shooter speed -> shoot
rather than:
Code:

correct angle-\
              +--> shoot
shooter speed-/

Because it was so much easier to just make it a list of commands. So we took longer to shoot things than we needed to. People have mentioned how to work around this in this thread, but it was enough that it didn't happen.

I get that it's also easier to do the steps linearly in non-command based code, but it's not much different. You'd go from:

Code:

switch(mode){
        case 0:
                run_aim_stuff()
                if(aimed) mode=1;
                break;
        case 1:
                turn_on_shooter()
                if(up_to_speed) mode=2;
                break;
        case 2:
                shoot()
                if(done) mode=3
                break;
        case 3:
                ...
}

to

Code:

switch(mode){
        case 0:
                if(!aimed) run_aim_stuff()
                if(!up_to_speed) turn_on_shooter()
                if(aimed && up_to_speed){
                        shoot()
                        if(done) mode=3
                }
                break;
        case 3:
                ...
}


Ginto8 02-05-2013 04:39

Re: Reducing code complexity
 
Quote:

Originally Posted by SoftwareBug2.0 (Post 1271167)
Here's a more minor problem: Our autonomous mode became

Code:

correct angle -> shooter speed -> shoot
rather than:
Code:

correct angle-\
              +--> shoot
shooter speed-/


This will fulfill the second sequence:
Code:

addParallel(new MoveAngle());
addParallel(new SpinUpShooter());
addSequential(new WaitForChildren());
addSequential(new Shoot());


apalrd 02-05-2013 10:39

Re: Reducing code complexity
 
This thread reminds me why I dislike Java and the command architecture for embedded systems.


I've always designed the code so we can pass desired setpoints in a single auton function then terminate. That way, we send the Set command in the script, and the subsystem listens and controls to that commanded value indefinitely (or until disable->enable transition).

This way, the subsystem holds all of the code required to fully run a mechanism, and the rest of the code just is just a button map or auton command. I can test the subsystem individually by commanding setpoint directly, and verify results using all of the data present in the subsystem.

In our C code for Vex, each subsystem gets a single C and two H files (since RobotC dosen't exactly work like normal C, the data is in a H with externs in the other H, if we used 'real' C the data would be in a C, code in a C, and externs/prototypes/typedefs in a H). Main (which runs the main task and HMI) gets another C, and Auton has a few files (autosel, routines, psc, nav). All of the code fits easily in a single directory, and totals ~1400 lines (lots of comments and diagnostics).

Joe Ross 02-05-2013 11:31

Re: Reducing code complexity
 
Quote:

Originally Posted by apalrd (Post 1271277)
This thread reminds me why I dislike Java and the command architecture for embedded systems.


I've always designed the code so we can pass desired setpoints in a single auton function then terminate. That way, we send the Set command in the script, and the subsystem listens and controls to that commanded value indefinitely (or until disable->enable transition).

We used 3 different methods with the command system.
1)Send a setpoint and exit immediately while holding the setpoint.
2)Send a setpoint, wait for it to get there, then exit and keep holding.
3)Send a setpoint, wait for it to get there, then exit and stop holding

Not sure why you think there's only one way to write things with the command system.


All times are GMT -5. The time now is 16:26.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi