In Eagle I often prefer to route some wires myself (power, xtal, UBS, etc), and leave the rest to the autorouter. When I am not pleased with the result I route some more myself, and let the autorouter have another try.

My problem is undoing the work of the autorouter, without undoing my own work. The basic way to do this is simply not saving the autoroutered version, and then loading the board again. But once I make the mistake of saving the autorouted version (and purging the backups) I still want to be able to go back to the pre-autorouted version.

One attempt to do this is to identify all autorouted wires in an ULP and create the command string to RIPUP these segments. I can arrange for the ULP to identify the autorouted wires, for instance by giving them a different width. But the RIPUP command seems to ripup the selected wire segment AND ADJACENT SEGMENTS. So far I have not found a command that rips just the selected wire segment.

So I guess I have two questions: - How do you combine hand-routing and auto-routing in an iterative (trial-and-error) way? - Is there a way (probably using ULP and commands) to ripup a subset of wire segments?

(update) I tried the opposite approach: in an ULP, gather all wire segments I want to keep, do a full ripup, and then restore the wires segments (using the ROUTE command). No success, the segments must be in a specific order for the route commands (not the order in which the ULP finds them :( ), the via's must be made first, and some more problems.

GRRRR, there must be an easy way to do this, or am I overly optimistic?

  • \$\begingroup\$ If Eagle's data file follows the same approach as older ones that I have played with (eg ye olde DOS Autotrax) then each track segment has a line to itself. If the track widths are unique it should [tm] be easy to identify track segments and delete the lines concerned. Dim memory tells me that at one stage I wrote a routine to identify component labels and resize, rotate and move them relative to the component body. Track identification sounds easy compared. Save a copy before running program !!! :-). \$\endgroup\$
    – Russell McMahon
    Aug 25, 2011 at 4:48
  • \$\begingroup\$ this is a terrific question, might I suggest you also post it to the Element14 expert on Eagle element14.com/community/message/5177. If you do and you find anything please do post back to here! \$\endgroup\$
    – vicatcu
    Aug 26, 2011 at 19:56
  • \$\begingroup\$ Ok, done. If that fails I can try the eagle forums. \$\endgroup\$ Aug 27, 2011 at 19:49

3 Answers 3


I hate answering my own question, but here I go. I hope I don't get get points for answering, that would be weird, only for accepting an answer? (BTW, I did not get any response on the Element14 forum.)

The solution is to use the DRAW command, not ROUTE. DRAW will place a wire segment, exactly where you specify (unlike ROUTE, which tries to connect to an unrouted airwire. ROUTE is essentially useless in a script.). The next issue is via's: I can't (or don't want to) distinguish between a manual via and an autorouted via, so I keep all via's that connect two (or more) manual wire segments. Other via's are deleted.

So what my final script does is:

prepare a ripup command
for all copper segments that are not 0.01 wide (the width I use for autorouting)
   check both endpoints for a via at that location
      prepare the via to be resurrected when it is visited the 2nd time
   prepare a command that resurrects the copper segment
execute the prepared commands

Note that it will probably not work for more than two layers, nor for other things than wire segments at the copper layer.

IMHO the whole concept of the eagle ULP and command languages is troublesome. An ULP runs in a read-only environment, the only way it can affect the circuit, board or library is by creating a list of commands. This eliminates some useful programming techniques, but worse is that the commands were not designed to be easily created from an ULP. You need all kinds of transformations (in this case: coordinates, shape names) to translate from the ULP world to the CMD world.

(edit) Before you run this ULP, set the 'wire bend' selection to allow arbitrary angles, otherwise eagle will try to adapt the resurrected wires to the allowed angles, which can result in a bloody mess. IMHO this is another example of the problem with ULP/SCR.

This is the ULP code:

// gather the commands that must be run on exit
string RunOnExit = "";
void cmd( string s ) { RunOnExit += s + "\n"; }

// return an x or y position in the form that can be used in a command
real f( int x ){
   board( B ) switch( B.grid.unit ) {
      case 0: return u2mic(x);
      case 1: return u2mm(x);
      case 2: return u2mil(x);
      case 3: return u2inch(x);

// return the string form of the a via's shape
string sn( int x ){
   if( x == VIA_SHAPE_SQUARE )  return "square";
   if( x == VIA_SHAPE_ROUND )   return "round";
   if( x == VIA_SHAPE_OCTAGON   ) return "octagon";
   if( x == VIA_SHAPE_ANNULUS   ) return "annulus";
   if( x == VIA_SHAPE_THERMAL   ) return "thermal";
   return "unknown-via-shape";

// count the number of times x occurs in s
int n_ocurrences( string s, string x ){
   int i, n = 0;
   while( 1 ){
      i = strstr( s, x );
      if( i == -1 ) return n;
      s = strsub( s, i + strlen( x ));

// add a via, but only when it is visited the second time
string via_list = "";
void add_via( int a, int b ){

   // for all via's
   board( B ) B.signals( S ) S.vias( V ){

      // if the via is at the current location
      if(( V.x == a ) && ( V.y == b )){
         string s, coo;

         // the coordinates of the via are used as its identification
         sprintf( coo, "(%.6f %.6f)", f( V.x ), f( V.y ));         

         // if this is the second visit to this via
         via_list += coo;
         if( n_ocurrences( via_list, coo ) == 2 ){

            // resurrect this via
            sprintf( s, "VIA '%s' %f %s %s;", 
            S.name, f( V.drill ), sn( V.shape[ 1 ] ), coo );
            cmd( s );      

if( !board ){
   dlgMessageBox("start this ULP in Board", "OK");
   exit( 0 );

board( B ){ 

   // first delete all coper segments, 
   // later we will resurrect what we want to keep 
   cmd( "RIPUP;" );

   // for all wire segments in the top and bottom copper layers
   B.signals(S) S.wires(W) {
      if( ( W.layer == 1 ) || ( W.layer == 16 ) ){ 

         // that are not 0.01 width (that is what the autorouter uses)
         if( f( W.width ) != 0.01 ){
            string s;

            // resurrect via's adjacent to this wire segment
            add_via( W.x1, W.y1 );
            add_via( W.x2, W.y2 );

            sprintf( s, "CHANGE LAYER %d;", W.layer );
            cmd( s );      

            // resurrect this wire segment                 
               s, "WIRE '%s' %f (%.6f %.6f) (%.6f %.6f);", 
               S.name, f( W.width),
               f(W.x1), f(W.y1), f(W.x2), f(W.y2));
            cmd( s );   
   // dlgMessageBox( RunOnExit, "OK");
   exit( RunOnExit );
  • \$\begingroup\$ Eagle's ULP/SCR are one of its most powerful features. As you've found, ULPs are used to query the board and write scripts which can be absolutely anything you can do yourself. That's its power. Having said that I wish that it was in a 'normal' language, perhaps Python or even Lua, but even you must admit that being able to do something that the authors of the software didn't think of is a good feeling. \$\endgroup\$
    – akohlsmith
    Feb 15, 2013 at 11:57
  • \$\begingroup\$ Sure, but their power must be wielded in an arcane way: ULPs are powerful, but can not change the schematic/bord, SCR is a crippled variation of the GUI. Together they can do useful work, but things could have been made much easier! And for my particular problem it would have been be nice if the things added by the autorouter were somehow identifiable. \$\endgroup\$ Feb 15, 2013 at 12:13
  • 2
    \$\begingroup\$ In EAGLE v6.3, the command is WIRE not DRAW (there is no DRAW command). \$\endgroup\$
    – user40475
    Apr 17, 2014 at 6:50

Wouter. I didn't see your question earlier because I was at Masters last week.

The way I deal with this is to save a copy of the board to a different name right before running the autorouter. I always name it SAVE.BRD, which can be safely deleted once all done.

My routing workflow seems to be a lot like yours. I route the critical parts manually, make sure the net classes are set up reasonably, then run the autorouter. Then I look for problems like where the autorouter couldn't find a solution, it ended up doing something inconvenient, etc. I go back to the saved version (before autoroute) make a few manual changes hopefully so that the autorouter won't get in trouble, then try again. This might be repeated 5-10 times, depending on the board complexity. The first few autoroute passes are mostly to see if there is a solution and roughly to find the trouble spots. For that I don't even use any optimization passes. The later autoroutes are with full optimization, which for me is usually 8 passes with costs changing over those passes to get the characteristics I want.

Even though I do a save to SAVE.BRD before each autoroute pass (and then re-open the original file to proceed with that), I try not to do a save on the autorouted result until I'm happy with the whole thing. Saving the snapshot to SAVE.BRD each time is a safety backup in case my fingers accidentally do a save before I think about it.

It would be nice if Eagle had a ripup option for the last autoroute pass, but there is no such thing.

  • \$\begingroup\$ You discipline will work for a person that is always disciplined. You might guess that I am not. Once I autorouted, then made some changes to the circuit, then deleted the brd and tried to switch back to the pre-autorouted version. Not a good idea... So now I more-or-less have a way to un-autoroute, provided that I can distinguish the autorouted traces by width. It would be nice if autorouted traces had some attribute that identified them as such. \$\endgroup\$ Sep 2, 2011 at 14:27
  • \$\begingroup\$ Strange, I had written "Hi, Wouter" at the beginning of my post, but the "Hi, " part seems to have gotten stripped off. \$\endgroup\$ Sep 2, 2011 at 14:31
  • \$\begingroup\$ I believe that is a "feature" that stack exchange has. They think saying "Hi" at the beginning of a post is not needed and should be removed to keep things "clean". Similar to them stripping off @username in some cases... and just like this case where I couldn't type @ Olin (with no space) and @ username in the same comment. \$\endgroup\$
    – Kellenjb
    Sep 2, 2011 at 18:09
  • \$\begingroup\$ See meta.stackexchange.com/questions/2950/… \$\endgroup\$
    – Kellenjb
    Sep 2, 2011 at 18:14

If Eagle's data file follows the same approach as older ones that I have played with (eg ye olde DOS Autotrax) then each track segment has a line to itself. Lines are "stand alone" and can be edited or deleted without impact on anything else. Newer "better" systems may not have such powerful simplicity.

If tracks are independent, as above, and if the track widths are unique it should [tm] be easy to identify track segments and delete the lines concerned.

Dim memory tells me that at one stage I wrote a routine to identify component labels and resize, rotate and move them relative to the component body. Track identification sounds easy compared. Save a copy before running program !!! :-).

  • \$\begingroup\$ Which file format are you talking about? The eagle .brd file is not a text file. My problem with the track segments is not that I can't identify them, but that the only command I am aware of that I can use will do too much: RIPUP rips not just the segment but (some) adjacent segments too. \$\endgroup\$ Aug 25, 2011 at 6:07
  • \$\begingroup\$ @Wouter van Ouijen - YMMV :-). Not being text per se does not mean it can't be hacked - but it may. I do not know what the Eagle .brd file looks like inside and I do not know if you can tear out whole track segments and concatenate the remainder safely - probably not. Worth a look though. You may be able to write a file reader and rewriter which intelligently rebuilds the file less the undesired parts. It would depend on how well known or knowable the file format is. \$\endgroup\$
    – Russell McMahon
    Aug 25, 2011 at 7:06
  • \$\begingroup\$ I realize that at the time of writing the question this was true, but Eagle's file formats now are straightforward XML text files. \$\endgroup\$
    – akohlsmith
    Feb 15, 2013 at 11:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.