home *** CD-ROM | disk | FTP | other *** search
/ Between Heaven & Hell 2 / BetweenHeavenHell.cdr / 500 / 470 / rccl044 < prev    next >
Text File  |  1987-03-02  |  15KB  |  560 lines

  1. /* Demo program puma-600                         */
  2. /* Author.: V. Hayward                            */
  3. /* Updated .: J.Juan                            */
  4. /* Date last update : apr 9,1984                    */
  5.  
  6. #include "../h/rccl.h"
  7. #include "../h/rtc.h"
  8. #include "../h/hand.h"
  9. #include "../h/umac.h"
  10.  
  11. extern struct how how;
  12. extern struct chg chg;
  13.  
  14. #define PUMA
  15. #define CLR     '\032'
  16.  
  17. pumatask()
  18. {
  19.     int q;
  20.  
  21.     putchar(CLR);
  22.     printf("This is an implementation of the program given in Chap 5.\n");
  23.     printf("of Prof. Paul's book\n");
  24.     printf("Type 'y' to proceed");
  25.     QUERY(q);
  26.     if (q == 'y') {
  27.         book();
  28.     }
  29.     putchar(CLR);
  30.     printf("This program demonstrates that we can perform a task\n");
  31.     printf("namely, moving in loop to four different locations,\n");
  32.     printf("with respect to a moving coordinate frame.\n");
  33.     printf("The first part is performed in cartesian mode\n");
  34.     printf("in other words, the trajectory is constantly evaluated\n");
  35.     printf("with respect to the Cartesian world description\n");
  36.     printf("The second part is executed in joint mode,\n");
  37.     printf("this means that the succesive locations are computed\n");
  38.     printf("only at the beginning of each path segment, the coordinate\n");
  39.     printf("velocities estimated, and the intermediate locations\n");
  40.     printf("linearly interpolated at the joint level.\n");
  41.     printf("Type 'y' to proceed");
  42.     QUERY(q);
  43.     if (q == 'y') {
  44.         cvsj1();
  45.     }
  46.     putchar(CLR);
  47.     printf("This example is similar to the previous one.\n");
  48.     printf("Now the moving coordinate frame describes a circle\n");
  49.     printf("and the same move statement is executed four times.\n");
  50.     printf("This example clearly shows that the trajectories executed\n");
  51.     printf("in joint mode are aproximate\n");
  52.     printf("Type 'y' to proceed");
  53.     QUERY(q);
  54.     if (q == 'y') {
  55.         cvsj2();
  56.     }
  57.     putchar(CLR);
  58.     printf("This example again uses of moving coordinate frame.\n");
  59.     printf("We will instruct the robot to move along a path defined\n");
  60.     printf("by a spiral and a rotation\n");
  61.     printf("Type 'y' to proceed");
  62.     QUERY(q);
  63.     if (q == 'y') {
  64.         spire();
  65.     }
  66.     putchar(CLR);
  67.     printf("This example again uses of moving coordinate frame.\n");
  68.     printf("We will instruct the robot to move at separate locations\n");
  69.     printf("by changing asynchronously the value of a frame\n");
  70.     printf("as if this frame was updated by some external sensor\n");
  71.     printf("like a camera or a range finder.\n");
  72.     printf("Type 'y' to proceed");
  73.     QUERY(q);
  74.     if (q == 'y') {
  75.         psv();
  76.     }
  77.     putchar(CLR);
  78.     printf("This program makes use a very simple sensor to perform\n");
  79.     printf("a trajectory tracking on an arbitrary surface\n\n");
  80.     printf("The second part of the program uses the same sensor");
  81.     printf(" in a different way.\n");
  82.     printf("Motions will be interrupted upon detection of an obstacle\n");
  83.     printf("When the robot senses an obtacle, it proceeds to the next\n");
  84.     printf("path segment.\n");
  85.     printf("Type 'y' to proceed");
  86.     QUERY(q);
  87.     if (q == 'y') {
  88.         ftrk();
  89.     }
  90.     putchar(CLR);
  91.     printf("This program shows the problems caused by the volume\n");
  92.     printf("swept when the arm changes it's configuration.\n");
  93.     printf("Type 'y' to proceed");
  94.     QUERY(q);
  95.     if (q == 'y') {
  96.         pcnf();
  97.     }
  98.     putchar(CLR);
  99. }
  100.  
  101.  
  102. book()
  103. {
  104.  
  105.     TRSF_PTR e, z, p, pa, pg, pd, h, ht, pha, pch, pac, pn;
  106.     POS_PTR pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8;
  107.     int q;
  108.  
  109.     z = gentr_eul("Z", 0., 0., 330., 0., 0., 0.);
  110.     e = gentr_eul("E", 0., 0., 175., 0., 0., 0.);
  111.     p    = gentr_eul("P"   , 350., 0., 20., -90., -90., 0.);
  112.     pa   = gentr_eul("PA"  , 100., 0., -50., 0., -45., 0.);
  113.     pg   = gentr_eul("PG"  , 0., 0., -50., 0., -45., 0.);
  114.     pd   = gentr_eul("PD"  , 50., 0., 0., 0., 0., 0.);
  115.     h    = gentr_eul("H"   , 400., 300., 20., 0., -90., 0.);
  116.     ht   = gentr_pao("HT"  , 100., 0., 50., 0., 1., 0., 0., 0., -1.);
  117.     pha  = gentr_eul("PHA" , 0., 0., -20., 0., 15., 0.);
  118.     pch  = gentr_eul("PCH" , 0., 0., 0., 0., 15., 0.);
  119.     pac  = gentr_eul("PAC" , 0., 0., 0., 0., 0., 0.);
  120.     pn   = gentr_eul("PN"  , 0., 0., 40., 0., 0., 0.);
  121.  
  122.     pos1 = makeposition("P1", z, t6, e, EQ, p, pa, TL, e);
  123.     pos2 = makeposition("P2", z, t6, e, EQ, p, pg, TL, e);
  124.     pos3 = makeposition("P3", z, t6, e, EQ, p, pd, pg, TL, pg);
  125.     pos4 = makeposition("P3", z, t6, e, EQ, h, ht, pha, pg, TL, pg);
  126.     pos5 = makeposition("P5", z, t6, e, EQ, h, ht, pch, pg, TL, pg);
  127.     pos6 = makeposition("P6", z, t6, e, EQ, h, ht, pac, pg, TL, pg);
  128.     pos7 = makeposition("P7", z, t6, e, EQ, h, ht, pn, pg, TL, pg);
  129.     pos8 = makeposition("P8", z, t6, e, EQ, h, ht, pn, pa, TL, e);
  130.  
  131.     OPEN;
  132.     for (; ; ) {
  133.         movejnts(pos1, 200, 2000);
  134.         movecart(pos2, 300, 700);
  135.         waitfor(completed);
  136.         CLOSE;
  137.         movecart(pos3, 100, 700);
  138.         movejnts(pos4, 100, 500);
  139.         movecart(pos5, 100, 500);
  140.         movejnts(pos6, 100, 700);
  141.         movecart(pos7, 100, 700);
  142.         waitfor(completed);
  143.         OPEN;
  144.         movecart(pos8, 100, 700);
  145.         printf("more ?");  QUERY(q);
  146.         if (q == 'n')
  147.             break;
  148.     }
  149.     movejnts(park, 200, 2000);
  150. }
  151.  
  152.  
  153.  
  154. cvsj1()
  155. {
  156.     TRSF_PTR z, e , b1, s1, s2, s3, conv1, conv2;
  157.     POS_PTR  p0;
  158.     POS_PTR p1[4], p2[4];
  159.     int convfn1();
  160.     int i, j, q;
  161.  
  162.     conv1 = newtrans("CONV1",convfn1);
  163.     conv2 = newtrans("CONV2",convfn1);
  164.     z = gentr_rot("Z",  0.,  0., 330., zunit, 0.); /* at the base */
  165.     e = gentr_eul("E" , 0. , 0. , 170. , 0. , 0.,  0.);/* finger tips */
  166.     b1 = gentr_rot("B1", 500. , -400., 150., yunit, 180.);
  167.     s1 = gentr_trsl("S1", 0., 0., 80.);
  168.     s2 = gentr_trsl("S2", 80., 0., 80.);
  169.     s3 = gentr_trsl("S3", 80., 0., 0.);
  170.  
  171.     p0 = makeposition("P0" , z, t6, e, EQ, b1, TL, e);
  172.     p1[0] = makeposition("P10" , z, t6, e, EQ, conv1, b1, TL, e);
  173.     p1[1] = makeposition("P11" , z, t6, e, EQ, conv1, b1, s1, TL, e);
  174.     p1[2] = makeposition("P12" , z, t6, e, EQ, conv1, b1, s2, TL, e);
  175.     p1[3] = makeposition("P13" , z, t6, e, EQ, conv1, b1, s3, TL, e);
  176.     p2[0] = makeposition("P20" , z, t6, e, EQ, conv2, b1, TL, e);
  177.     p2[1] = makeposition("P21" , z, t6, e, EQ, conv2, b1, s1, TL, e);
  178.     p2[2] = makeposition("P22" , z, t6, e, EQ, conv2, b1, s2, TL, e);
  179.     p2[3] = makeposition("P23" , z, t6, e, EQ, conv2, b1, s3, TL, e);
  180.  
  181.  
  182.     movejnts(p0, 100, 1500);
  183.     for (; ; ) {
  184.         waitfor(completed);
  185.         rtime = 0;
  186.         for (j = 0; j < 6; ++j) {
  187.             for (i = 0; i < 4; ++i) {
  188.                 movecart(p1[i], 100, 300);
  189.             }
  190.         }
  191.         movejnts(p0, 100, 1500);
  192.         waitfor(completed);
  193.         rtime = 0;
  194.         for (j = 0; j < 6; ++j) {
  195.             for (i = 0; i < 4; ++i) {
  196.                 movejnts(p2[i], 100, 300);
  197.             }
  198.         }
  199.         movejnts(p0, 100, 1500);
  200.         waitfor(completed);
  201.         printf("more ? ");
  202.         QUERY(q);
  203.         if (q == 'n') break;
  204.     }
  205.     movejnts(park, 100, 1500);
  206. }
  207.  
  208.  
  209. convfn1(t)
  210. TRSF_PTR t;
  211. {
  212.     t->p.y = .08 * rtime;
  213. }
  214.  
  215.  
  216.  
  217. cvsj2()
  218. {
  219.     TRSF_PTR z, e, conv, or, fl;
  220.     POS_PTR  pm, pf;
  221.     int convfn2();
  222.     int i;
  223.  
  224.     conv = newtrans("CONV",convfn2);
  225.     z = gentr_rot("Z",  0.,  0., 330., zunit, 0.); /* at the base */
  226.     e = gentr_eul("E" , 0. , 0. , 170. , 0. , 0.,  0.);/* finger tips */
  227.     or = gentr_eul("OR", 000. , 600., 350.,    0., 0., 90.);
  228.     fl = gentr_rot("FL", 0. , 0., 0., yunit, 180.);
  229.  
  230.     pf = makeposition("PF" , z, t6, e, EQ, or, fl, TL, e);
  231.     pm = makeposition("PM" , z, t6, e, EQ, conv, or, fl, TL, e);
  232.  
  233.  
  234.     movejnts(pf, 300, 1500);
  235.     for (; ; ) {
  236.         printf("cart ");QUERY(i);
  237.         if (i == 'y') {
  238.             movecart(pm, 100, 800);
  239.             for (i = 0; i < 12; ++i) {
  240.                 movecart(pm, 100, 800);
  241.             }
  242.         }
  243.         movecart(pf, 100, 800);
  244.         printf("jnts ");QUERY(i);
  245.         if (i == 'y') {
  246.             movejnts(pm, 100, 800);
  247.             for (i = 0; i < 12; ++i) {
  248.                 movejnts(pm, 100, 800);
  249.             }
  250.         }
  251.         movecart(pf, 100, 800);
  252.         printf("quit ");QUERY(i);
  253.         if (i == 'y') {
  254.             break;
  255.         }
  256.         movecart(pf, 100, 800);
  257.     }
  258.     movecart(park, 300, 1500);
  259. }
  260.  
  261.  
  262.  
  263. convfn2(t)
  264. TRSF_PTR t;
  265. {
  266.     extern int rtime;
  267.     double time;
  268.  
  269.     double omega = .220;
  270.     double radius = 200.;
  271.  
  272.     time = rtime / 1000.;
  273.     t->p.x = radius * cos(omega * time * PIT2);
  274.     t->p.z = radius * sin(omega * time * PIT2);
  275. }
  276.  
  277.  
  278. spire()
  279. {
  280.     int spirefn();
  281.  
  282.     int q;
  283.  
  284.        TRSF_PTR
  285.     base = gentr_rot("BASE", -200., 100., 330., yunit, 0.),
  286.     tool = gentr_rot("TOOL", 0., 0., 180., yunit, 0.),
  287.     pin = gentr_rot("PIN", 400. , 300., 0., zunit, 0.),
  288.     pintip = gentr_rot("PINTIP", 0., 0., 50., yunit, 180.),
  289.     spire = newtrans("SPIRE", spirefn);
  290.  
  291.     POS_PTR
  292.     touch = makeposition("TOUCH",
  293.         base, t6, tool, EQ, pin, pintip, TL, tool),
  294.     spiral = makeposition("SPIRAL",
  295.         base, t6, tool, EQ, spire, pin, pintip, TL, tool);
  296.  
  297.     setvel(200, 100);
  298.  
  299.     for (; ; ) {
  300.         setmod('c');
  301.         move(touch);
  302.         QUERY(q); if (q == 'n') break;
  303.         setime(200, 15000);
  304.         move(spiral);
  305.     }
  306.     setmod('j');
  307.     move(park);
  308. }
  309.  
  310. /*
  311.  * generate a spiraling motion in the x y plan
  312.  */
  313.  
  314. spirefn(t)
  315. TRSF_PTR t;
  316. {
  317.     real radius = goalpos->scal * 50.;
  318.     real turns = 10.;
  319.     real heigth = 100.;
  320.     real angle = - 5.;
  321.     VECT k;
  322.  
  323.     t->p.x = radius * (k.x = cos(turns * goalpos->scal * PIT2));
  324.     t->p.y = radius * (k.y = sin(turns * goalpos->scal * PIT2));
  325.     t->p.z = 0.; /* heigth * goalpos->scal; */
  326.     k.z = 0.;
  327.     Rot(t, &k, angle * goalpos->scal);
  328. }
  329.  
  330.  
  331.  
  332. psv()
  333. {
  334.     TRSF_PTR z, e , b1, conv;
  335.     POS_PTR  p1;
  336.     int convfo();
  337.     int q;
  338.     double iy;
  339.  
  340.     conv = newtrans("CONV",convfo);
  341.     z = gentr_rot("Z",  0.,  0., 330., zunit, 0.); /* at the base */
  342.     e = gentr_eul("E" , 0. , 0. , 170. , 0. , 0.,  0.);/* finger tips */
  343.     b1 = gentr_rot("B1", 600. , 0., 100., yunit, 180.);
  344.  
  345.     b1->fn = hold;
  346.     p1 = makeposition("P1" , z, t6, e, EQ, conv, b1, TL, e);
  347.  
  348.     setmod('c');
  349.     setvel(300, 100);
  350.     move(p1);
  351.     for (; ; ) {
  352.         move(p1);
  353.         waitfor(completed);
  354.         if (p1->code == LIMIT) {
  355.             printf("limit reached\n");
  356.         }
  357.         printf("more "); QUERY(q); if (q == 'n') break;
  358.         printf("enter Z increment ");
  359.         scanf("%f", &iy);
  360.         b1->p.z += iy;
  361.     }
  362.     setmod('j');
  363.     move(park);
  364. }
  365.  
  366.  
  367. convfo(t)
  368. TRSF_PTR t;
  369. {
  370.     double time;
  371.  
  372.     time = rtime / 20000.;
  373.     t->p.y = 400. * cos(time * PIT2);
  374. }
  375.  
  376.  
  377. int sensor;
  378.  
  379. #define TOUCHED 10
  380.  
  381. ftrk()
  382. {
  383.     TRSF_PTR z, k1, kk1, kkk1, k2, k3, finf, abov;
  384.     TRSF_PTR b1, b2, b3, b4, b5, over, fing, getit, flip;
  385.     POS_PTR  q1, qq1, qqq1, q2, q3, got;
  386.     POS_PTR  p1, p2, p3, p4, p5, pp1, pp2, pp3, pp4, pp5, get;
  387.     int touchfn();
  388.     int fingfn();
  389.     int q;
  390.  
  391.     finf = newtrans("FINK",fingfn);
  392.     rot(finf, zunit, -90.);
  393.     fing = gentr_rot("FINS", 0., 0., 110., zunit, -90.);
  394.     z = gentr_rot("Z",  0.,  0., 330., zunit, 0.);
  395.     k1 = gentr_rot("K1", 600. ,-300., 200., yunit, 180.);
  396.     kk1 = gentr_rot("KK1", 600. ,-300., 100., yunit, 180.);
  397.     kkk1 = gentr_rot("KKK1", 600. ,-300., 20., yunit, 180.);
  398.     k2 = gentr_rot("K2", 600. , 200., 200., yunit, 180.);
  399.     k3 = gentr_rot("K3", 600. , 200., 350., yunit, 180.);
  400.     abov = gentr_rot("OVER", 600., 0., 200., yunit, 180.);
  401.     b1 = gentr_trsl("B1", 600. ,-200., -100.);
  402.     b2 = gentr_trsl("B2", 600. ,-100., -100.);
  403.     b3 = gentr_trsl("B3", 600. , 000., -100.);
  404.     b4 = gentr_trsl("B4", 600. , 100., -100.);
  405.     b5 = gentr_trsl("B5", 600. , 200., -100.);
  406.     over = gentr_rot("OVER", 0., 0., 250., yunit, 180.);
  407.     flip = gentr_rot("FLIP", 0., 0., 70., yunit, 180.);
  408.     getit = gentr_rot("GETIT", 600. , 0., 350., yunit, 180.);
  409.  
  410.  
  411.     q1 = makeposition("Q1" , z, t6, fing, EQ, k1, TL, fing);
  412.     qq1 = makeposition("QQ1" , z, t6, fing, EQ, kk1, TL, fing);
  413.     qqq1 = makeposition("QQQ1" , z, t6, fing, EQ, kkk1, TL, fing);
  414.     q2 = makeposition("Q2" , z, t6, finf, EQ, k2, TL, finf);
  415.     q3 = makeposition("Q3", z, t6, EQ, k3, TL, t6);
  416.     got = makeposition("GOT", z, t6, EQ, getit, TL, t6);
  417.     p1 = makeposition("P1" , z, t6, fing, EQ, b1, over,TL , fing);
  418.     p2 = makeposition("P2" , z, t6, fing, EQ, b2, over,TL , fing);
  419.     p3 = makeposition("P3" , z, t6, fing, EQ, b3, over,TL , fing);
  420.     p4 = makeposition("P4" , z, t6, fing, EQ, b4, over,TL , fing);
  421.     p5 = makeposition("P5" , z, t6, fing, EQ, b5, over,TL , fing);
  422.     pp1 = makeposition("PP1" , z, t6, fing, EQ, b1, flip, TL , fing);
  423.     pp2 = makeposition("PP2" , z, t6, fing, EQ, b2, flip, TL , fing);
  424.     pp3 = makeposition("PP3" , z, t6, fing, EQ, b3, flip, TL , fing);
  425.     pp4 = makeposition("PP4" , z, t6, fing, EQ, b4, flip, TL , fing);
  426.     pp5 = makeposition("PP5" , z, t6, fing, EQ, b5, flip, TL , fing);
  427.     get = makeposition("GET", z, t6, EQ, getit, TL, t6);
  428.  
  429.  
  430.  
  431.     movejnts(get, 400, 1500);
  432.     waitfor(completed);
  433.     OPEN;
  434.     printf("put the sensor in the jaws ");
  435.     QUERY(q);
  436.     CLOSE;
  437.     printf("go ahead ");
  438.     QUERY(q);
  439.     if (q == 'n') {
  440.         movejnts(park, 400, 2500);
  441.         return;
  442.     }
  443.     sensor = adcopen(7);
  444.     for (; ; ) {
  445.         movecart(q1, 400, 1500);
  446.         stop(0);
  447.     /*    movecart(qq1, 400, 1500);
  448.         movecart(qqq1, 400, 1500); */
  449.         sample(15);
  450.         movecart(q2, 200, 8000);
  451.         waitfor(completed);
  452.         sample(30);
  453.         QUERY(q); if (q == 'n') break;
  454.         movecart(q3, 400, 1500);
  455.         movecart(got, 400, 1500);
  456.     }
  457.     movejnts(get, 400, 1500);
  458.     printf("type 'y' for poking");
  459.     QUERY(q);
  460.     if (q == 'n') {
  461.         movejnts(park, 400, 2500);
  462.         waitfor(completed);
  463.         OPEN;
  464.         return;
  465.     }
  466.     for (; ; ) {
  467.         sample(14);
  468.         movejnts(p1, 200, 3000);
  469.         evalfn(touchfn);
  470.         movejnts(pp1, 200, 3000);
  471.         movejnts(p2, 200, 3000);
  472.         evalfn(touchfn);
  473.         movejnts(pp2, 200, 3000);
  474.         movejnts(p3, 200, 3000);
  475.         evalfn(touchfn);
  476.         movejnts(pp3, 200, 3000);
  477.         movejnts(p4, 200, 3000);
  478.         evalfn(touchfn);
  479.         movejnts(pp4, 200, 3000);
  480.         movejnts(p5, 200, 3000);
  481.         evalfn(touchfn);
  482.         movejnts(pp5, 200, 3000);
  483.         movecart(get, 200, 3000);
  484.         waitfor(pp1->end)
  485.         if (pp1->code == TOUCHED) printf("touched\n");
  486.         else printf("not touched\n");
  487.         waitfor(pp2->end)
  488.         if (pp2->code == TOUCHED) printf("touched\n");
  489.         else printf("not touched\n");
  490.         waitfor(pp3->end)
  491.         if (pp3->code == TOUCHED) printf("touched\n");
  492.         else printf("not touched\n");
  493.         waitfor(pp4->end)
  494.         if (pp4->code == TOUCHED) printf("touched\n");
  495.         else printf("not touched\n");
  496.         waitfor(pp5->end)
  497.         if (pp5->code == TOUCHED) printf("touched\n");
  498.         else printf("not touched\n");
  499.         waitfor(get->end);
  500.         sample(28);
  501.  
  502.         printf("more ? ");
  503.         QUERY(q); if (q == 'n') break;
  504.     }
  505.     movejnts(park, 400, 1500);
  506.     waitfor(completed);
  507.     OPEN;
  508. }
  509.  
  510.  
  511. touchfn()
  512. {
  513.     if (how.adcr[sensor] > 1) {
  514.         nextmove = TOUCHED;
  515.     }
  516. }
  517.  
  518.  
  519. fingfn(t)
  520. TRSF_PTR t;
  521. {
  522.     t->p.z += (how.adcr[sensor] * .01 - 3.) / 3.;
  523. }
  524.  
  525.  
  526.  
  527. pcnf()
  528. {
  529.     TRSF_PTR z, e , b1, b2 ,rt;
  530.     POS_PTR  p1, p2, p3;
  531.     int q;
  532.  
  533.     z = gentr_rot("Z",  0.,  0., 330., zunit, 0.); /* at the base */
  534.     e = gentr_eul("E" , 0. , 0. , 170. , 0. , 0.,  0.);/* finger tips */
  535.     b1 = gentr_pao("B1", -128. , 800.,  200., 0., 0., -1., 0., 1., 0.);
  536.     b2 = gentr_pao("B2", -128. , 980., 200., 0., 0., -1., 0., 1., 0.);
  537.     rt = rot(newtrans("RT", const), xunit, 90.);
  538.  
  539.     p1   = makeposition("P1" , z, t6, e, EQ, b1, TL, e);
  540.     p3   = makeposition("P3" , z, t6, e, EQ, b2, TL, e);
  541.     p2   = makeposition("P2" , z, t6, e, rt, EQ, b2, TL, e);
  542.  
  543.  
  544.     movejnts(p1, 300, 2000);
  545.     movejnts(p3, 300, 2000);
  546.     for (; ; ) {
  547.         printf("the arm is lun, goes luf ? ");
  548.         QUERY(q); if (q == 'n') break;
  549.         moveconf(p2, 300, 1000, "f");
  550.         printf("the arm is luf, goes ldn ? ");
  551.         QUERY(q); if (q == 'n') break;
  552.         moveconf(p2, 300, 2000, "dn");
  553.         printf("the arm is ldn, goes lun ? ");
  554.         QUERY(q); if (q == 'n') break;
  555.         moveconf(p1, 300, 2000, "u");
  556.     }
  557.     moveconf(park, 300, 2000, "lun");
  558.     printf("END\n");
  559. }
  560.