From 54cbd5f7fc58a6c5dc7f9a1a62d0d403375d3406 Mon Sep 17 00:00:00 2001 From: Jasen Jacobsen Date: Wed, 11 Mar 2020 10:17:21 -0400 Subject: [PATCH 01/12] Initial commit. --- .../java/frc/robot/status/ImageAction.java | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/main/java/frc/robot/status/ImageAction.java diff --git a/src/main/java/frc/robot/status/ImageAction.java b/src/main/java/frc/robot/status/ImageAction.java new file mode 100644 index 0000000..47c48f8 --- /dev/null +++ b/src/main/java/frc/robot/status/ImageAction.java @@ -0,0 +1,147 @@ +package frc.robot.status; + +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +import edu.wpi.first.wpilibj.util.Color; + +import java.awt.image.BufferedImage; +/** + * Use an image file to set the addressable LEDs + * + * Provide the pathname to an image file. + * Interval can be set which is the delay between frames. + * Oscillate tells whether to start walking through the columns back at 0 or to count down when the end of the image is reached. + * Count is how many times to go through the image. LEDs will be left at the last "frame". -1 cycles forever. + * + * Each column in the image file will be treated as a "frame" or a full buffer. + * + * Height of the image does not matter, pixel selection will be scaled to the size of the buffer. + * This is a naive percentage scaling. If the LED being set is 1/2 way through the buffer, + * the pixel 1/2 way up the image will be used. + * e.g. If the buffer is 60 LEDs long and the image is 240 pixels high and LED 30 is being set, + * pixel 120 will be selected from the image. + * + * The "bottom" of the image is LED 0. 0,0 is usually the top, left of an image. + * For our purposes, LED 0 will get the highest numbered pixel. + * + */ +public class ImageAction extends LedAction { + + private static final double DEFAULT_INTERVAL = 0.050; + private static final int FOREVER = -1; // forever + + private File imageFile; + private BufferedImage image; + + private int currentColumn = 0; + private boolean oscillate = false; + private boolean goForward = true; + + public ImageAction() { + super(); + intervalTime = DEFAULT_INTERVAL; + intervalCount = FOREVER; + } + + public ImageAction(String pathname) { + this(pathname, DEFAULT_INTERVAL, FOREVER); + } + + public ImageAction(String pathname, double interval) { + this(pathname, interval, FOREVER); + } + + public ImageAction(String pathname, double interval, int count) { + super(); + intervalTime = interval; + try { + imageFile = new File(pathname); + image = ImageIO.read(imageFile); + intervalCount = count * image.getWidth(); + } catch (IOException e) { + e.printStackTrace(); + System.out.println("Problem opening image. Check the path.\nImage path = " + pathname); + } + } + + @Override + public double getDelay() { + return intervalTime; + } + + public ImageAction oscillate() { + this.oscillate = true; + return this; + } + + public void setOscillate(boolean b) { + oscillate = b; + } + + protected void updateBuffer() { + for (var i = 0; i < buffer.getLength(); i++) { + + // Scale the height of the image to the size of the buffer + // Do some shenanigans to force float arithmetic + double percent = (i * 1.0) / (buffer.getLength()-1); + int imageY = (int)(percent * (image.getHeight()-1)); + + int rgb = image.getRGB(currentColumn, imageY); + Color pixelColor = intToColor(rgb); + buffer.setLED(i, pixelColor); + } + + if (currentColumn < (image.getWidth()-1)) { + if (goForward) { + currentColumn++; + } else { + currentColumn--; + } + } else { // reached the end of the image + if (oscillate) { + goForward = false; + currentColumn--; + } else { + currentColumn=0; + } + } + + // Always move forward from the beginning + if (0 >= currentColumn) { + currentColumn = 0; // Handle edge case of drawing the zeroth column which then gets decremented. + goForward = true; + } + } + + /** + * Translate an integer representation INT_ARGB of a pixel's colors to + * a WPILib Color object. + * @param pixel + * @return WPILIB Color + */ + private Color intToColor(int pixel) { + int alpha = (pixel >> 24) & 0xff; + int redi = (pixel >> 16) & 0xff; + int greeni = (pixel >> 8) & 0xff; + int bluei = (pixel) & 0xff; + + double brightness = (alpha / 255.0); + double red = brightness * (redi / 255.0); + double green = brightness * (greeni / 255.0); + double blue = brightness * (bluei / 255.0); + + return new Color(red, green, blue); + } + + public BufferedImage getImage() { + return image; + } + + public void setImage(BufferedImage image) { + this.image = image; + } + +} \ No newline at end of file From ff766528695e46a149781fccd786600ecfce204b Mon Sep 17 00:00:00 2001 From: Jasen Jacobsen Date: Wed, 11 Mar 2020 10:26:47 -0400 Subject: [PATCH 02/12] Added some images --- src/main/deploy/images/fade.png | Bin 0 -> 6984 bytes src/main/deploy/images/stripe.png | Bin 0 -> 11418 bytes src/main/deploy/images/stripes.png | Bin 0 -> 11418 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/deploy/images/fade.png create mode 100644 src/main/deploy/images/stripe.png create mode 100644 src/main/deploy/images/stripes.png diff --git a/src/main/deploy/images/fade.png b/src/main/deploy/images/fade.png new file mode 100644 index 0000000000000000000000000000000000000000..66e4b73a5802102cdf23da907a4d867fce20e090 GIT binary patch literal 6984 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 U&Oce={W757M8`*6h}f|Af0r(?7ytkO literal 0 HcmV?d00001 diff --git a/src/main/deploy/images/stripes.png b/src/main/deploy/images/stripes.png new file mode 100644 index 0000000000000000000000000000000000000000..05f427cf5814397b1f362268d909dfa5ef5878e3 GIT binary patch literal 11418 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 literal 0 HcmV?d00001 From d064142aac10f7db4208d6a691d3ea48d742e633 Mon Sep 17 00:00:00 2001 From: Jasen Jacobsen Date: Wed, 11 Mar 2020 10:36:14 -0400 Subject: [PATCH 03/12] Clean up imports. --- src/main/java/frc/robot/status/ImageAction.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/frc/robot/status/ImageAction.java b/src/main/java/frc/robot/status/ImageAction.java index 47c48f8..9f9410d 100644 --- a/src/main/java/frc/robot/status/ImageAction.java +++ b/src/main/java/frc/robot/status/ImageAction.java @@ -1,13 +1,11 @@ package frc.robot.status; +import edu.wpi.first.wpilibj.util.Color; +import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; - import javax.imageio.ImageIO; -import edu.wpi.first.wpilibj.util.Color; - -import java.awt.image.BufferedImage; /** * Use an image file to set the addressable LEDs * @@ -144,4 +142,4 @@ public void setImage(BufferedImage image) { this.image = image; } -} \ No newline at end of file +} From d3f5bb1db02b6c454b9d4cde548e4fa65146e6d4 Mon Sep 17 00:00:00 2001 From: Jasen Jacobsen Date: Wed, 11 Mar 2020 17:59:01 -0400 Subject: [PATCH 04/12] Fix bug with which pixel to render. --- src/main/java/frc/robot/status/ImageAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/frc/robot/status/ImageAction.java b/src/main/java/frc/robot/status/ImageAction.java index 47c48f8..a5ff8e2 100644 --- a/src/main/java/frc/robot/status/ImageAction.java +++ b/src/main/java/frc/robot/status/ImageAction.java @@ -87,7 +87,7 @@ protected void updateBuffer() { // Scale the height of the image to the size of the buffer // Do some shenanigans to force float arithmetic double percent = (i * 1.0) / (buffer.getLength()-1); - int imageY = (int)(percent * (image.getHeight()-1)); + int imageY = (int)((1.0 - percent) * (image.getHeight()-1)); int rgb = image.getRGB(currentColumn, imageY); Color pixelColor = intToColor(rgb); From f7fe315853513b4f0c8bf3a5154607ae3f47fa8c Mon Sep 17 00:00:00 2001 From: Jasen Jacobsen Date: Thu, 12 Mar 2020 14:48:26 -0400 Subject: [PATCH 05/12] Added a bunch more images --- src/main/deploy/images/THfade.png | Bin 0 -> 3024 bytes src/main/deploy/images/noise.png | Bin 0 -> 11315 bytes src/main/deploy/images/noisy-pulse.png | Bin 0 -> 7954 bytes src/main/deploy/images/pulse-down.png | Bin 0 -> 2780 bytes src/main/deploy/images/pulse.png | Bin 0 -> 3457 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/deploy/images/THfade.png create mode 100644 src/main/deploy/images/noise.png create mode 100644 src/main/deploy/images/noisy-pulse.png create mode 100644 src/main/deploy/images/pulse-down.png create mode 100644 src/main/deploy/images/pulse.png diff --git a/src/main/deploy/images/THfade.png b/src/main/deploy/images/THfade.png new file mode 100644 index 0000000000000000000000000000000000000000..6eea34760ecac8efb17c31886112a3af60d0a2ff GIT binary patch literal 3024 zcmV;>3orDEP)EX>4Tx04R}tkv&MmKpe$iQ?(+M4t5afkfAzR5EXIMDionYs1;guFuC*#ni!H4 z7e~Rh;NZt%)xpJCR|i)?5c~jfa&%I3krMxx6k5c1aNLh~_a1le0HIN3n$)S(glehxvqHp#<}FOz%!#}HZw;YB^FB^taLCdn;P*Xaa`4O$`^7T ztDLtuYtKlt6PRh$_2lEO)#`^9lShJny7(5ySo_p#$NPk`VvaHY5X8x3Iklk|F9 ziyr}zZQ$a%ttorJq3=cUu7OHg90000PbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAV*0}P*;Ht7XSbW zx=BPqRA}C9T3MFkNDc$Sb^pW6LFPnhp+C5RA=m4ERcR|F1{V+n#sA^|JP$vA{P*Sg zovzWn#a`Qzt%J`bovKmY^@0zd!|2tc9$0un@s@ihtLh4nuG#?|?i`t!IqC<+n~ z|B((M zDDo*ch!WF~GXB)rRUYK)J`+HcSH=5Tl~gQu&!3DrJDd!Ah;shJF%i`AafM%wA{wM+lHp|m zZQkpYUHvtIWfobmj%AWSJS(*JC*;itRpCDbw2Kc;E6}oqbbr%$(N3*)ofQ(j+ywTIb0I@7|s45v_GD z*k=4e!onD0c8tfpc$py9{>?(kTVQ+rx| zPhlnP^cy8_q8E03f^0mU*-gc2+)t#Ts#Iv4`eL7*n4GtvI%98mDjZb zl(wWhPhnjLN!_Y1)J;H>1KFfe9d4LiVLpYSO3=Ynef57BL6P|Cx13lB)KMi_xGk$g z;^aS7T!PIXZ=Ql+nCjp@=}1<(N((*~xcXFK`KJXmLo-eTZM6)KcX4|fSf*JgfvpIW z9381_XQYN_&75OYC2CSOyNNUU7^nJ)N>?tHBmZ`9ul`3 zZQkxUF!iw(9dEM4%GGij$06J~;lMa$6@{Eb6=`CnQnX7^r+FMx zzAW=691?#d=~#(Pv<%m} zHFEKL8h#K>rBng}Ti-ZL5htuX#l4cOGO{S>iY0Y|r#4yNieZ~^F6zmqFdD`w7%dl70;%r!g}ldOYG{{$0Grq$}*AmdGhw0^8NE z+YuZZr>lMg&A8NK>y_nc9cd%PgO@yD=BQZ&G>2mXeUqRbF4-By#XEbnA5YE9D80EO z0G$_B@E6sTcL!H9Vu;k5JGeBIo2|;*>s{)*wy%8Z>knVraAoS2V}yGk4U*3!lNuS) zyV_32A8A9ZDtDzah3q}=DApH}Z2)k!Kv~H2Mkx7EZ7hjfpX|HlS3Bq>tx+bnRCKqe z<349l*=_YEqAPsF+Mq1`Lzf+{w`KElrD`U)ZaZp8k<(-6vd}%4l|hr17D$*|j4F)$ zi5AkOt*VY-+IokKn*FEQPJ}HgQ za_?tAKrAUgHgUb<3I)QFkdp0O)*!E{PE%D=q+)5%v{joSBNwfv_afF)iDx9?8nO<= zg<`%=XB&IRc-B_8);>^jRLk|nTxp#`TZAYc5{ydEw8th7^iBR$rxT{t%IFYSt0jH=dlx)wzPc>{?XE1C-VhAg-k z_v+JUr2)*X?_|Ps-`V1)+&xzQsoe1w!y1NjbFA4O^^jwmYUdzsareJHG_Dq5d;IBF zvjlA)o)Uoc(g$oA({r9u9Ep)hrBn5;A8S4w#@H*kO-cDnG^_wL_V|JVOlrC%sKKV$ z_$>x$W6=PAG;nVINe4UQDszdcLdFR^N~X?Am#}Mun|qB-dqAUd!?;JBHPW(Ze=CnECPw8_UN^#F~Zs}QFTvX z#wA#uy_`}S@=WZFNR4bFaV>?|?SRgnUDn}9?*ucIxIuKAsbS+firqNQeqHY1UK`ta<(+!JYsH2w%fO5n*Sv8lRlo1P)EX>4Tx04R}tkv&MmKpe$iQ?(+M4t5afkfAzR5EXIMDionYs1;guFuC*#ni!H4 z7e~Rh;NZt%)xpJCR|i)?5c~jfa&%I3krMxx6k5c1aNLh~_a1le0HIN3n$)S(glehxvqHp#<}FOz%!#}HZw;YB^FB^taLCdn;P*Xaa`4O$`^7T ztDLtuYtKlt6PRh$_2lEO)#`^9lShJny7(5ySo_p#$NPk`VvaHY5X8x3Iklk|F9 ziyr}zZQ$a%ttorJq3=cFdx!&I60000PbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAV*0}P*;Ht7XSbt z07*naRA}A>!3985TL1viyJRCaHej%kqq`gF?oh!*Q7i<-!fr$b1-_UF27+MGjZ#t) z(jncQW5vey{yDIHT6=Hr3su!bEx-o;4AuKs8BV`FFjh+Im2Yy_x0EyERaT8?jXM!d z0a|SwNX$GfNqwGI;9{W)0PoFhi}yChr5fa??*`fcdaXK4& zW#6i;BjiTG$d%Robxw2P&47{R;d|fSXq*VSu;cRBhmQ;fC%{1;AOMTS2e7Rljg>x6 z&rl@9{>-J(!P=FG`K~j;*U?E#EZI zz2Z4h#%P+VkKcEHgwsCxmh_SLs&XR-1_QS>6N5!%aj+)4o=)jP|NWTe82vqsURCo6tJhq7Og^|A~!IgB?x|uY)@3Z^ZmsIMZY zE=^_65O-QQ>l+CJ+&o~5z&u@{lwpZ;#<3w`Un=Sk^he`l1T{2OMHP7mYJ9~c;DO#$ z3Gq#Rs;d8`?8nD~>)K|QxJoJyr{{q_au^PYE|*URHP(x2;DZX$_@lkieNWCCmp zwUGX zRZl=)pX;db7uKS>TnqblKHvmU9RuRiPqVXFV`PDTIflsEez`+a^clauR?EQ~^P6k$ z7ZY#q4Mn_hO5K97z7_p&k#Kf8H>!%anAN9987LztSw0KrMLS5MOzy8Og^pQ`D;>Wb8AoIT%D#*csE*&P)F=mb_#CDcx!u&cA?Ke-|u|*0?-Tq-~P0m8VAk= z@Jwz?CFqG5|CrB$();o|OI>b6MFsh2DUJ0VK>s5CYO>xP@CpQ@Jv^xyt|BQKz2Ks0-*_uqTwe=hU>ZF9XU z{f@;Gl@Gh`Xj0UWq){13UV!X1sDZ3V&r&1fz-xfQhMxBw7Y66cz^Y5M&c_@^c( zCtB&a)5Q72egMzq{lOvv_B7kKO%Yw?UE(b#Z9Ply$Hn~VkX@_PJwl5_} z(8n}B@W$_m1Ba9DOsve_IpJeu%FQ)PWNg;e0x%8EZFEvn14u3&634 zx}y377dU1aur7No4=YoY-%UQ9LyuO@lyv2BFYWgUf1ddKid$tzPyH6Hp<^h^p%CEu z=?@<-3gMk-!po$e0(f}V=>3!G$xE9{om#V<)veN2#t*Hu0C{<;otgGKJNS_7%m;i} z;h{UbF5IfRfq@Cb?A+k6ofeTsm(lBzZC2yjh#kdE?MWJ`RnOo2TlrJbI+XCGv^<^l z2VT9UF@0n1tbj3}sWaJzE%H+ei2eOEr=uw8+b_Tuu*tBq?^TH#yh7uyOA9HANpDA` zrUE#3uZxkC+x?5XJdZo8EM|g{B(B1Z(|Me-J?NGN*^|t*K3$H z8Z6^)okcA@gUk;3g&z1?BSrVIg+-_04!pfG&^=~;1Tb*Flwq(Wz1ocVIaBt0 zF8Z1I2ZL|Qqj}e;5|RJ_Kp1-vw}4wR)Fi9-F7*|)Rr@LV?6dLaY1I?eIst%BPt#h)h#YRXw;8v)=@JRAp)r{SOg65NcXwKqMV(aLn<%fn&(+S zo&q8puTc+kG5_{Pz$qatI;rwq&i$Llr^A~(dfqmq z1seyW(15|*(#cd!l>Zp8%MOl$fO0=TvjLg~5NsgTedX0#O!d)YxbwCh8Y5sJ$uuQY z=jb*Z^e=XCdvO$w0?%M$UyJh^e=%yG8_ZkD@48GP+bvh$1hzCHp*$Hhpc|c*-3Nz3 zC9Q1@&te4dEBzB|&(fM-m*zp&I7f?*1*rtP=$iqxEeTKHjqftUd#98Cy*{jb5(x(|GyrUnHvZ{G z^SRmm%Q0OK{1m+eP=dH-6^uF%CIXqS5*e;vI|jOUGS3{xSl^7;VQ(ZC`RoUBZH;Dj zm;~&Et83S#5W>Lmhx(fL0bP@t(fXanBC3j$9I}Vd1gxA+O^{w5N zE)8@VDBjAP+!~6~x|K2cZUr}Jq$R5%rHmD)e<-UwKz}+a)LK4KaarT;L;=_qrHe}n zOL{KX=gvv3%hZS#y&ZlLyYo6vV7+f)ILu*R>aTpe>0_vBJk9|Oj?TrPPv#!X;0mr? zD2sZen8_IjU7*v1s)xh@l*(AmTDq;iHsB)^4um!yX|8zK=e65|sKB3CUBa(Owk)F*2jD&hZ{Agm=`j1K-&(A~JM4Jxv5j1<1pdP#o;sk)@oR_QQ!0uUiu5grH;OaDxC+FS_hTT8e_C*t?2iJee7M zNPi2)+Ge1R$eoUO_FMsG^0~T7S4qAo`o8FSbv_21Z9EFFEalfK*Ef?0C{Zk+Olw20 z$(e}Uo}#63y48})bKV_q{vo_Dc9c6}!P$Y_0-M}T?K;I1D(B;y{`2b)k7EYM?$+EZ?yjou?=jXBVa$?l z5>sNQu4K2C)JcxUFW)_=9YUa>Ir>WoofUZFk;Xc1DMAUDYgsrTywUOCg)wCRq;AKJnZ5O%cc2B>^eB-`Dy#9x{6%OS}p085|~qs3%n5dV;&jG_%EAio45mjsDDzb8B zhLqDgos+&*SST3_0E~r_o{zqRBwlW?c#|NA>D%sfwlF~vHV-5`aI?^I;)HK+@%tIQ zOw1-#g1XDp<5h3s)xCk$qt#|QWMo$@LV8p2m01Rn3X0b<#pPM?pL}VRI_52w0xH-@ zkvr!Yfvgx!x;WaqcTPW)%bV{Qo$5FT7NWd>6uFoJJz2%fiVI0%V1m<(G1-var6<0wwUJ!XJX$UnU;1@LPg>KBe5Pl$ zBcRW@l-FP`Z{pW?U#Lbx?1!qFKbRp7T(mmLS`jdMr~f@N0id_(%q@UsA@W)(FG$=8 z8g!HrmGHGUm6OH+0geEPowJs`tNr|`jop{zqmzGrFKuhdb^IBTQ~+S~Kh?4VD`dVP zn*q^1KYN`vJiX0^Kdy@{-_a2_aPQHV?+oPPasSZR>Dw>d{tK&!*iSv=qw1YCo%HF_ z1^LFHGufAp3q*DGOqh!9NGr|jXLQD_UHT)qipNmcjJ3|q=Hb~%fepz%cB`#|gX#yx zE&Oa=XIb}LpNKHBW8xosiwl?LsSL3HewB`-aEI#H(n@HoJ(DB-}KAAUQB`9n6zNMRmpX&vYC->k{m3Zc=dj z{;4j%9~a{_gtaqWe`JimJ5aQrfD`;$TYt7B{3!j33D?Y$>)77cmw8u5yQQY9l_ui4*}VpKnV*5% z%=8*XNP3mGp3?vNQqPGFpJ8GVY^Ua4EJa{Z<9WMGH=omEY( zc-P)#F}JpzO=UloHo?hg$(J`zeuE{BinQ9HJm*KZlx1XDVbFvA>%+TN1^F2Jol^O; zpK`i$&-nQzr8f_bqE>P~E-Z45^a)c?F9ydc_?N%PT-1^%ZvZkGc zyox1z4;vpAP+3DrE}H5}>#0aNS|~tVL9-y>L44$@K`Yz^-l%U`hlU1^}9*1X>b^EPHFY z8OrEF9Khpop`^tv79!j&7;K{-cwe2HWdB!|KHZGSssGd1HF_fYu|2`r7HeyPbdNH+ zQ9sbV^s)Ry^OrtGXQJhc%kz6P7e0zBi!^OlGZ2d%GaUfM5En;tw^_1c(f|q4W2|SE zmOI7=VHKyoJ1M(?6*Mdc-4ObFo!I403GD7&`2IKNu-XY~__yHb*J;sSVBP`d;S2zP zzO)0DFxU`}F8EJR*r=41rbSkBmG?XK@v4oG=RPNIiw`E3T#sM0IUk+-?3%`X<`TqQ zf%TGVlqHmrpQN`%LEOgmH!DxCx<%Xx*#j_4fMA_VeSs9NXKC;`+{amsm*H9=G=18NnsxQ+X$M zb5EFB%a6;x#h~G0;>gszP6@O;m&^b1``75uh9%@_CS-@)6n)h8C?PaV8q)dET6`0i zfEp*<*>zcjPb}@I3y?eTvL>~P^x=HqVd{AQ{2@DIErY9pK3ZPs z4Y@Z$9eU?G@atx7?2s3;4=%YKKVN)#ZgbjE*)i+kw#5&F1Jv-OSRH#~s-23<=i&|o z3PL}zOT@B-?*xYdGUZb74=ov0vp)-IU!?ah0Nkbl&uw&=f$~Q}SYV>AixfmC zt?Oj=rMIC9WOcU>-%~+s3zbY3VwXsJ)b^Dn#Vy!pnCfW!8EvmP{Z)hReIEP#>HDwi zWxBjYnP2v|$o6#7dm&rJ9hRfVfAutO%WQ^q?CV@>m6gH&sQ+DAH}~jUCX$au5>dot z)!Z7@6nng!jfqr8(o5o}Q<`nKNal@+i9VDNubQ5je(@IId~Bp=_dwg{j@jbGEA6(- z3}T#vG=nT;?0EBnXe8j!Ko97>?@1~1b$oogQuBVEzrOGY`89!Ba)lvRgpFGHser= znzASmWJaXlbuiFQD*NPR>J-N0$+Sa0T`IGLxP_DqaJeAwb5lek7T5Hpbyko!4ZJhd?H z<)>w8DS&nh!ie)zCY}jWm>%XP@BY45kdoen&CG7jS?MU*=xJ#i0=R(zE;s%J;GqaW z+Ue{Qu!URZOhIt)W9H*y#~9j>Z1_F{Ahhziw1c+I*>1nuQY$<^$;TqGe}{V8`?~Y` z3Ij*13%|6!g0f*_0J$jYhX{SBpS<(x%joy{I*Lk%%6BvR0a)fQ%+dlB_LyHk*w#Pw zuCzRTUkYx8U=6Is7sscTW()&G6|^~;d+tva#XLKF|MQU-r+vI%)TbQvx1?kKHIH{( z@(Ko9cq~&P?sY3H%**Sx|7pj2VObZWwMZIg-aQ={n=5nub*t=A&_-y6_=_e^dDYvq zopa5r^a=W;zP7M61t;^dHhZ-T^=kOP$*r+WsWK~=3wHyc*`OQOZDp&oq|{^n)_UoC z<}x&Bc{EmdMy^b~fjTJCp|RPbn8g%WCSVD^YQD2CgrRM4im|8YTo%yo0k~QFb9X}A zon(}^9E6Vbu^Kg1@aw!;IC>KYm)a2)_w3MBo7DHrwL*k+Fq&EsCne)^r%$ZkzIv3tICi@#2hhN?RHOKl_ne%CJX~f?N*B>G+*dJDW=t|~8SB1y zO+`S2c0cReO}~i3Z);wM*?@yvnQd?gJKdG{e5pHT8 ztTnV2(j3rnjWZ3(BHEgTp+*vxld$m}6eA>=Gt8}@80Tb_mmW|&gcBFy!nSnPWM)^E z!_iSvI^u)dEqQ+`b!64#3F^;=o-p8RXN=Ds$%_2ZUb3{gvODf3K~S`=zst!?MG!4) zF6>@cJVMnZn!;>;Z~QVfQCeqjOAacEA@O=JOPmVq-O#hEp&lY={H{;I*%ozw>5cE3 zGT%0*nDEDz&%S0ZecuF|CR^jDZrczY=zx8^ zJmgG(ci5L}$@`L~v$>`i8{J_$t|)h2ypO7?__XuEjp|z%F8(0;!gI#WE9)=#6h=_d z?o(!=!IlAgO#LsqAFAs5`>Uso04WMCs;blz%!p2q-EL+D9gQHT_g6O3}4BvtF{Xk+q2wcu(32}|C0>v8nl7Y4KxUaV*keU9vJ`|9?)s(+7u`QC0bN8rNEa!Q$5El8pF|Oy zrK;X_kMKETs098mR{Z^x1{A0M_UF#Z9H+A1$16&Ye~U1Vc&Yy}15tlZ^D*NB+eyiB zIAZ*7czxcnkEsE#ltq<|q>SeLpcL(_B|GR}=n!-hig$R1L*W1bX-DJxE;q8yLG|`S zV|oxCMR?(p0EfZOdhde1H-$Uz?;>oC%R)|g&(E5Liw-=XATE8?{Kg~>N<&oyY3vR$ z*$+Kt=tybbF^&;I;?0%yzu&r&d-EOu;MdU-&M_!c_Gh=ywvK=i1u1(){6WT%XP-_z zG?djjXMGv~Frf&Iib2aB5R|lZ#LnMS*M9ig-&4jXXM;!+NB{r|5lKWrRGgtMQC6Jd z`|}FdYAidTcM~tHQUCyMI<`jVJ=DHS@TujNn{1D2o zaW>I~D)P6pYoQPQ4OjD!=l0p2*-go=J$cYp>mc0ZSJU$K<|AD%-p6MY&f70-Eu$9Y zlhw%7^iz*#*QZ)QlZTPxFlXR;)nhbK(Av_ZWA5*Z`I~LA>3}5^A9yP<>p5>56YOM~ zGMXYLDxA7M{%2Dc5lPxy++3iIqJ@xyya7!Kz0QG}q~XU<%6P$Y!l~p(TRFd&+zsl% zBU~QjEgon<(z!j+WdiqL!aJioPy6rTl)rbF`8Onu(QjBOl~ThaN^ZyH)OGH>_1~Ri zKEM7BIGQWYFR_pa;G^ReTlxG|XA*2q@nJ>MgP^dAuC~~^_+`%GJ}>ve^+JfcYHgxP zr_qU;G(AJa>+&LFS^b2%*YTIm?EM(h(m$GUJP{V6Vn{MH7PgfIDr6NY8Jg~Hm7qaJ z&;0tz4lCK1UvUyx>0A5vHT>&Pqmtk(qH))5FU5fV;jyc_apSP=(1yT-GrO4_CSGiN zzE5Lhgoc6$T9RsTuqIp9(g~I4gKey%8QCEC;eJnTO=SWdK0mzPpA+)&b@OXJT_iL) zx@UT*anE0SIhWDRfdj$X^O*jk*}M|eYpnFh-K@deHlkQ~ZCn|#b77|c<& z&Om{vOA;MgOO`d)5UzCjA>I;5pHG=$j_!F8b=N-h~UK50fIj`4F*~!T+rSf=(bOr&o0@WEgmi;2;&4Xf~s|4os+{F7_+b+ zmk_%(f-uA_zI27NtzcUIcxra=7(_N zDC^hm^BXIkrUvz|1jZI8#WrL$k=pQa(C!d8sU%PA?PuOds*l*~=oL{6A5gt=J5}^E zOppS}-!)k0t^g!-!}knIYpNYp4lD}$rzQ<{ES9|Vdz(dJ7{wP+v9s(4T7lY6l5L)tAu$ zo8l@V5z-Pk6dWY69>M^?utjtG^9sT~hPwv>2wiD^_UuxCLUfT^zcGy86c0B)4|PQW zrg-Jw2~(=duDi*hh9`|)Mr>QsqgH}*|K-StlK1QE^EGwOudlmoabC!>7e(p*+12v7 zuvcw3ByQ~13-=_F4BFvE0Q7O_(bvyB?8=C)2WHhp~T$@oD9#j>1VR;JvOlrlTjnAuyBG`}NQCpVpg2T-gS< zW655;U{6f&7r{ptoUaIK51A*pG-d5F+m)MiJo0;eb?osYfX_!vB^U3!fA_GfI}(m< z|F>`}xj+a(#G#2kW_!6+h+!~+KqAswKX6zu)To4@kYGCdtrc+x>5kzCwYrDD5`^&r z909tEp_#E7)!WFnDGfA&Y7&`n-TKDs?8=|rKjjJ1TO95w#!WsJKsv)m&x%l;5W><@ zMftV1`~WqQ;+;QtAKS+9#HOE>X6>rKAIHB^#LrmRp3}u^iPE%c*q^b2+}PdGk3Q!n z9JmfR!j@4HFes}N0DgJ*Zxa=5f`It>^w{{ItK@LI(Y=e4ZvdaTyb9Q_w_~HlpG8g` zv=wsTTEB$S_ zauj-nFvXZ#W3PzuiRvuA zs;{aa8Q=(|@-sq2g7r%z$m0NE#DGaQa^~CA9c|!fF79u{}z{ zE>mE|)c5=+JN3PNwB2JGV-(j6#5m%DG>RBTfJt84Z||Q!^K~puM&aL13d?MCjDAw@ zWQ|~9!Aju-Y@m`^#7DtSe!7|xusHF|ESz5rJgs|@1R$6P2qAkk*AB(kCyEyl{QF7-J3Xt}Y^NI)%)8XmnyH|gldR-Cz z_0X8h#&M25&LptcNzV6p;PvJ_-dwJ2A-PU9)t-_OT!M3!ZhF{Vax zH^$D4jV$#Hb*~dvN}=yKoB62MAFNe&{2PHMeCSIzxkm~H2W*1y7}0iWEkckf{$e=x zsAkx|wQlR3WD&I$1##0?)yXH-PoS`vwuL|D+B&jK4LMl}6{>tcr{Q9V9l~HPAp4+_ z`HZ=)1eqi#O%kxz3h3!y&ZB=~plNf0llROXNMR(Z7HZ2v3noR|9c>k*HR&wuxSfS0 zmxa}#%E1V0Ue6D&ZY>t|{&F?d5+?{r2q-PEmW0fg%r(?R7FBln>pGih07xjUwDtT> pFLMdc!r}ZQ9l4Lkq<002ovPDHLkV1ge)H#`6U literal 0 HcmV?d00001 diff --git a/src/main/deploy/images/noisy-pulse.png b/src/main/deploy/images/noisy-pulse.png new file mode 100644 index 0000000000000000000000000000000000000000..1b0b1dac70b71f279c3f918ff7712ff26e090d0c GIT binary patch literal 7954 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 literal 0 HcmV?d00001 From 1d66644b74417b75e3271abcf0068e8366469f73 Mon Sep 17 00:00:00 2001 From: Jasen Jacobsen Date: Thu, 12 Mar 2020 14:48:49 -0400 Subject: [PATCH 06/12] One more image --- burst.bmp | Bin 0 -> 11162 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 burst.bmp diff --git a/burst.bmp b/burst.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5414a887109d11d8ff0fd70aad09b6f1b4048f02 GIT binary patch literal 11162 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 literal 0 HcmV?d00001 From ba72b9dfd77c40c0c2b3a0409a3ee7e23580ad87 Mon Sep 17 00:00:00 2001 From: Jasen Jacobsen Date: Thu, 12 Mar 2020 14:49:32 -0400 Subject: [PATCH 07/12] Oops. Put in wrong place. --- burst.bmp | Bin 11162 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 burst.bmp diff --git a/burst.bmp b/burst.bmp deleted file mode 100644 index 5414a887109d11d8ff0fd70aad09b6f1b4048f02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11162 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 From 82b35387f1dcb13b7e35ab533b0bb521e01261f5 Mon Sep 17 00:00:00 2001 From: Jasen Jacobsen Date: Thu, 12 Mar 2020 14:50:09 -0400 Subject: [PATCH 08/12] A BMP image. --- src/main/deploy/images/burst.bmp | Bin 0 -> 11162 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/deploy/images/burst.bmp diff --git a/src/main/deploy/images/burst.bmp b/src/main/deploy/images/burst.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5414a887109d11d8ff0fd70aad09b6f1b4048f02 GIT binary patch literal 11162 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 literal 0 HcmV?d00001 From e634a69da9eb5920992b473659ba6152e6951607 Mon Sep 17 00:00:00 2001 From: John Doe Date: Thu, 12 Mar 2020 20:04:03 -0400 Subject: [PATCH 09/12] Added LED Demo CG. --- .../frc/robot/command_groups/LEDDemoCG.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/main/java/frc/robot/command_groups/LEDDemoCG.java diff --git a/src/main/java/frc/robot/command_groups/LEDDemoCG.java b/src/main/java/frc/robot/command_groups/LEDDemoCG.java new file mode 100644 index 0000000..77bfa3c --- /dev/null +++ b/src/main/java/frc/robot/command_groups/LEDDemoCG.java @@ -0,0 +1,48 @@ +package frc.robot.command_groups; + +import edu.wpi.first.wpilibj.Filesystem; +import edu.wpi.first.wpilibj.command.CommandGroup; +import edu.wpi.first.wpilibj.command.WaitCommand; +import frc.robot.status.ImageAction; +import frc.robot.status.LedAction; +import frc.robot.status.commands.ActionCommand; +import java.io.File; + +public class LEDDemoCG extends CommandGroup { + + public LEDDemoCG() { + File deployDir = Filesystem.getDeployDirectory(); + String pathPrefix = deployDir.getAbsolutePath() + "/images/"; + + ImageAction ia = new ImageAction(pathPrefix + "THfade.png").oscillate(); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + ia = new ImageAction(pathPrefix + "noise.png"); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + ia = new ImageAction(pathPrefix + "noisy-pulse.png"); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + ia = new ImageAction(pathPrefix + "pulse.png").oscillate(); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + ia = new ImageAction(pathPrefix + "pulse-down.png").oscillate(); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + ia = new ImageAction(pathPrefix + "stripes.png").oscillate(); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + ia = new ImageAction(pathPrefix + "fade.png").oscillate(); + addSequential(new ActionCommand(ia)); + addSequential(new WaitCommand(10)); + + addSequential(new ActionCommand(new LedAction(0, 0, 0, 0))); + } + +} \ No newline at end of file From 8a9f9d4a51c84554762e3402bbf5037939230d79 Mon Sep 17 00:00:00 2001 From: Jasen Jacobsen Date: Thu, 12 Mar 2020 21:40:41 -0400 Subject: [PATCH 10/12] Added image brightness. --- src/main/java/frc/robot/status/ImageAction.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/frc/robot/status/ImageAction.java b/src/main/java/frc/robot/status/ImageAction.java index 3355465..9e34b7b 100644 --- a/src/main/java/frc/robot/status/ImageAction.java +++ b/src/main/java/frc/robot/status/ImageAction.java @@ -37,6 +37,7 @@ public class ImageAction extends LedAction { private int currentColumn = 0; private boolean oscillate = false; private boolean goForward = true; + private double brightness = 1.0; public ImageAction() { super(); @@ -70,6 +71,17 @@ public double getDelay() { return intervalTime; } + public ImageAction brightness(double brightness) { + setBrightness(brightness); + return this; + } + + public void setBrightness(double brightness) { + if (0.0 > brightness) { brightness = 0.0;} + if (1.0 < brightness) { brightness = 1.0;} + this.brightness = brightness; + } + public ImageAction oscillate() { this.oscillate = true; return this; @@ -126,7 +138,7 @@ private Color intToColor(int pixel) { int greeni = (pixel >> 8) & 0xff; int bluei = (pixel) & 0xff; - double brightness = (alpha / 255.0); + double brightness = (alpha / 255.0) * this.brightness; double red = brightness * (redi / 255.0); double green = brightness * (greeni / 255.0); double blue = brightness * (bluei / 255.0); From 2149037708761553b43672ba57959276d5e232a8 Mon Sep 17 00:00:00 2001 From: Jasen Jacobsen Date: Mon, 16 Mar 2020 20:02:22 -0400 Subject: [PATCH 11/12] Update to latest WPILib --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c216213..18c096f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id "java" - id "edu.wpi.first.GradleRIO" version "2020.2.2" + id "edu.wpi.first.GradleRIO" version "2020.3.2" } sourceCompatibility = JavaVersion.VERSION_11 From 1458805459a754c8724b4b51731b9b5635629391 Mon Sep 17 00:00:00 2001 From: Jasen Jacobsen Date: Mon, 16 Mar 2020 20:06:57 -0400 Subject: [PATCH 12/12] Refactor Status Actions to own sub-package. Use Timer to manage Action intervals. --- .../frc/robot/command_groups/LEDDemoCG.java | 4 +- src/main/java/frc/robot/status/Status.java | 172 ++++++++++++------ .../robot/status/{ => actions}/Action.java | 24 ++- .../status/{ => actions}/ChaseAction.java | 2 +- .../status/{ => actions}/ImageAction.java | 19 +- .../robot/status/{ => actions}/LedAction.java | 35 ++-- .../status/{ => actions}/PowerUpAction.java | 2 +- .../status/{ => actions}/RainbowAction.java | 2 +- .../status/{ => actions}/ScannerAction.java | 2 +- .../robot/status/commands/ActionCommand.java | 22 ++- .../status/commands/ToggleFlashlight.java | 6 +- 11 files changed, 192 insertions(+), 98 deletions(-) rename src/main/java/frc/robot/status/{ => actions}/Action.java (67%) rename src/main/java/frc/robot/status/{ => actions}/ChaseAction.java (98%) rename src/main/java/frc/robot/status/{ => actions}/ImageAction.java (94%) rename src/main/java/frc/robot/status/{ => actions}/LedAction.java (82%) rename src/main/java/frc/robot/status/{ => actions}/PowerUpAction.java (97%) rename src/main/java/frc/robot/status/{ => actions}/RainbowAction.java (97%) rename src/main/java/frc/robot/status/{ => actions}/ScannerAction.java (98%) diff --git a/src/main/java/frc/robot/command_groups/LEDDemoCG.java b/src/main/java/frc/robot/command_groups/LEDDemoCG.java index 77bfa3c..b5e24b9 100644 --- a/src/main/java/frc/robot/command_groups/LEDDemoCG.java +++ b/src/main/java/frc/robot/command_groups/LEDDemoCG.java @@ -3,8 +3,8 @@ import edu.wpi.first.wpilibj.Filesystem; import edu.wpi.first.wpilibj.command.CommandGroup; import edu.wpi.first.wpilibj.command.WaitCommand; -import frc.robot.status.ImageAction; -import frc.robot.status.LedAction; +import frc.robot.status.actions.ImageAction; +import frc.robot.status.actions.LedAction; import frc.robot.status.commands.ActionCommand; import java.io.File; diff --git a/src/main/java/frc/robot/status/Status.java b/src/main/java/frc/robot/status/Status.java index 4c60eab..5e02867 100644 --- a/src/main/java/frc/robot/status/Status.java +++ b/src/main/java/frc/robot/status/Status.java @@ -7,15 +7,24 @@ package frc.robot.status; +import java.io.File; + import edu.wpi.first.wpilibj.AddressableLED; import edu.wpi.first.wpilibj.AddressableLEDBuffer; import edu.wpi.first.wpilibj.DigitalOutput; +import edu.wpi.first.wpilibj.Filesystem; import edu.wpi.first.wpilibj.Timer; import edu.wpi.first.wpilibj.command.CommandGroup; import edu.wpi.first.wpilibj.command.Scheduler; import edu.wpi.first.wpilibj.command.Subsystem; import edu.wpi.first.wpilibj.command.WaitCommand; import edu.wpi.first.wpilibj.util.Color; +import frc.robot.status.actions.Action; +import frc.robot.status.actions.ChaseAction; +import frc.robot.status.actions.ImageAction; +import frc.robot.status.actions.LedAction; +import frc.robot.status.actions.PowerUpAction; +import frc.robot.status.actions.ScannerAction; import frc.robot.status.commands.ActionCommand; // @@ -48,10 +57,11 @@ public class Status extends Subsystem { private Action currentAction = null; // Object used for locking operations around the currentAction - private Object actionLock = new Object(); + private final Object actionLock = new Object(); - // Timer allows us to do things at specific game time. + // Timer tracks the delay between intervals/frames. private Timer timer = null; + private double currentDelay = 0; // If both are false then the RIO is running but neither init has triggered // (it's in boot up). @@ -91,16 +101,18 @@ private Status() { } // This will set/send the buffer to the LEDs. - public synchronized void setLedData(AddressableLEDBuffer buffer) { + public synchronized void setLedData(final AddressableLEDBuffer buffer) { addressableLed.setData(buffer); } - public void setAction(Action action) { + public void setAction(final Action action) { // Before doing anything with an action synchornize around it. // This prevents swapping the action while the action runner thread is doing // something with it. synchronized (actionLock) { currentAction = action; + action.reset(); + currentDelay = 0; // Run the first time } } @@ -108,14 +120,16 @@ public void setAction(Action action) { // Note: these can't be commands since commands require enablement. private void scheduleBootActions() { - ScannerAction scannerAction = new ScannerAction(245, 0, 255, 90); + final ScannerAction scannerAction = new ScannerAction(245, 0, 255, 90); scannerAction.setIntervalTime(0.075); - scannerAction.setIntervalCount(ADDRESSABLE_LED_COUNT * 5 * 2); // number of lights, how many times to update them, back and fourth + scannerAction.setIntervalCount(ADDRESSABLE_LED_COUNT * 5 * 2); // number of lights, how many times to update + // them, back and fourth setAction(scannerAction); - ChaseAction chaseAction = new ChaseAction(245, 0, 255, 90); - chaseAction.setIntervalCount(-1); - //setAction(chaseAction); + /* + * ChaseAction chaseAction = new ChaseAction(245, 0, 255, 90); + * chaseAction.setIntervalCount(-1); setAction(chaseAction); + */ } // Things to do when auto resets/inits. @@ -123,9 +137,66 @@ private void scheduleBootActions() { private void scheduleAutoActions() { // Power up to purple, and stay on. - PowerUpAction powerUpAction = new PowerUpAction(245, 0, 255, 90); - powerUpAction.setIntervalCount(ADDRESSABLE_LED_COUNT); - setAction(powerUpAction); + /* + * PowerUpAction powerUpAction = new PowerUpAction(245, 0, 255, 90); + * powerUpAction.setIntervalCount(ADDRESSABLE_LED_COUNT); + * setAction(powerUpAction); + */ + final File deployDir = Filesystem.getDeployDirectory(); + // ia.setOscillate(true); + // setAction(ia); + + final CommandGroup commandGroup = new CommandGroup(); + + String imagePath = deployDir.getAbsolutePath() + "/images/" + "blueredfade.png"; + ImageAction ia = new ImageAction(imagePath, 0.050).oscillate(); + commandGroup.addSequential(new ActionCommand(ia)); + commandGroup.addSequential(new WaitCommand(10)); + + imagePath = deployDir.getAbsolutePath() + "/images/" + "fade.png"; + ia = new ImageAction(imagePath, 0.050).oscillate(); + commandGroup.addSequential(new ActionCommand(ia)); + commandGroup.addSequential(new WaitCommand(10)); + + final String ia2Path = deployDir.getAbsolutePath() + "/images/" + "stripes.png"; + final ImageAction ia2 = new ImageAction(ia2Path, 0.050).oscillate().brightness(0.5); + commandGroup.addSequential(new ActionCommand(ia2)); + commandGroup.addSequential(new WaitCommand(10)); + + final String ia3Path = deployDir.getAbsolutePath() + "/images/" + "pulse.png"; + final ImageAction ia3 = new ImageAction(ia3Path, 0.050); + commandGroup.addSequential(new ActionCommand(ia3)); + commandGroup.addSequential(new WaitCommand(10)); + + imagePath = deployDir.getAbsolutePath() + "/images/" + "noisy-pulse.png"; + ia = new ImageAction(imagePath, 0.050).oscillate().brightness(0.8); + commandGroup.addSequential(new ActionCommand(ia)); + commandGroup.addSequential(new WaitCommand(10)); + + imagePath = deployDir.getAbsolutePath() + "/images/" + "noise.png"; + ia = new ImageAction(imagePath, 0.050).oscillate().brightness(0.1); + commandGroup.addSequential(new ActionCommand(ia)); + commandGroup.addSequential(new WaitCommand(10)); + + imagePath = deployDir.getAbsolutePath() + "/images/" + "burst.bmp"; + ia = new ImageAction(imagePath, 0.050); + commandGroup.addSequential(new ActionCommand(ia)); + commandGroup.addSequential(new WaitCommand(10)); + + imagePath = deployDir.getAbsolutePath() + "/images/" + "pulse-down.png"; + ia = new ImageAction(imagePath, 0.050).oscillate(); + commandGroup.addSequential(new ActionCommand(ia)); + commandGroup.addSequential(new WaitCommand(10)); + + final String burstPath = deployDir.getAbsolutePath() + "/images/" + "THfade.png"; + final ImageAction burstAction = new ImageAction(burstPath, 0.05).oscillate().brightness(200); + commandGroup.addSequential(new ActionCommand(burstAction)); + // commandGroup.addSequential(new WaitCommand(10)); + + // LedAction blackAction = new LedAction(0, 0, 0, 0); + // commandGroup.addSequential(new ActionCommand(blackAction)); + + Scheduler.getInstance().add(commandGroup); } // This is what we want to run when teleop starts. @@ -133,24 +204,25 @@ private void scheduleAutoActions() { private void scheduleTeleOpActions() { // Power up to purple, and stay on - should be on already in match. - PowerUpAction powerUpAction = new PowerUpAction(245, 0, 255, 90); + final PowerUpAction powerUpAction = new PowerUpAction(245, 0, 255, 90); powerUpAction.setIntervalCount(ADDRESSABLE_LED_COUNT); setAction(powerUpAction); // Using a command group with sequentials to force timely control of the leds. - CommandGroup commandGroup = new CommandGroup(); + final CommandGroup commandGroup = new CommandGroup(); // With 40s to remain, warning. commandGroup.addSequential(new WaitCommand(94)); - LedAction warnAction = new LedAction(255, 127, 0, 127); + final LedAction warnAction = new LedAction(255, 127, 0, 127); commandGroup.addSequential(new ActionCommand(warnAction)); // With 15s remain, go nuts to climb. - commandGroup.addSequential(new WaitCommand(24)); // 15 sec before match end (adding extra since it takes a bit to start an action) + commandGroup.addSequential(new WaitCommand(24)); // 15 sec before match end (adding extra since it takes a bit + // to start an action) - // Run the rainbow to indicate we need to climb. - ChaseAction chaseAction = new ChaseAction(255, 127, 0, 90); - chaseAction.setIntervalCount(-1); + // Run the chase to indicate we need to climb. + final ChaseAction chaseAction = new ChaseAction(255, 127, 0, 90); + chaseAction.setIntervalCount(-1); // run forever commandGroup.addSequential(new ActionCommand(chaseAction)); // Don't do anything for some time. @@ -213,19 +285,21 @@ public boolean isFlashlightOn() { } // Specifically sets the flashlight on/true or off/false. - public void setFlashlightState(boolean state) { + public void setFlashlightState(final boolean state) { flashlightOutput.set(state); } // Toggles the state of the flashlight. public void toggleFlashlight() { - boolean isOn = isFlashlightOn(); + final boolean isOn = isFlashlightOn(); setFlashlightState(!isOn); } @Override public void initDefaultCommand() { - // No default command - the output buffers are set in the reset* above. + String imagePath = Filesystem.getDeployDirectory().getAbsolutePath() + "/images/" + "fade.png"; + ImageAction ia = new ImageAction(imagePath).oscillate(); + setDefaultCommand(new ActionCommand(ia, 1000.0)); } @Override @@ -239,15 +313,16 @@ public void periodic() { // Set a color from the predefined wpilib Color // Brightness is on a scale of 0-255 - public void setColor(Color color, int brightness) { + public void setColor(final Color color, final int brightness) { setColor((int) color.red, (int) color.green, (int) color.blue, brightness); } // Set RGB color values. // RGB values are 0 (full off) - 255 (full on) // Brightness is on a scale of 0-255 - public void setColor(int red, int green, int blue, int brightness) { - double b = brightness / 255.0; + public void setColor(int red, int green, int blue, final int brightness) { + this.currentAction = null; // Clear any action that is running. + final double b = brightness / 255.0; red = (int) (red * b); green = (int) (green * b); @@ -255,7 +330,7 @@ public void setColor(int red, int green, int blue, int brightness) { // Create a buffer for all the LEDs, set all of them to the same value, and // output the buffer. - AddressableLEDBuffer buffer = new AddressableLEDBuffer(ADDRESSABLE_LED_COUNT); + final AddressableLEDBuffer buffer = new AddressableLEDBuffer(ADDRESSABLE_LED_COUNT); for (var i = 0; i < buffer.getLength(); i++) { buffer.setRGB(i, red, green, blue); } @@ -270,9 +345,6 @@ private class ActionRunner extends Thread { // allows the OS schedular a good slice to do things. private static final double MINIMUM_DELAY_SECONDS = 0.010; - // How long to delay/sleep when there's no action. - private static final double IDLE_DELAY_SECONDS = 0.250; - public void run() { // The thread should persist while the code does (forever). @@ -280,35 +352,29 @@ public void run() { // TODO: A watchdog should probably check to see if the thread died off // due to an exception and restart it. while (true) { - synchronized (actionLock) { if (currentAction != null) { - //System.out.println("ActionRunner: run"); - currentAction.run(); - - // If the current action is now done, remove it and loop back around. - if (currentAction.isFinished() == true) { - //System.out.println("ActionRunner: finished"); - currentAction = null; - continue; - } - // Delay the amount of time requested by the action. - double delay = currentAction.getDelay(); - if (delay < MINIMUM_DELAY_SECONDS) { - delay = MINIMUM_DELAY_SECONDS; + currentDelay = currentAction.getIntervalTime(); + if (currentDelay < MINIMUM_DELAY_SECONDS) { + currentDelay = MINIMUM_DELAY_SECONDS; } - //System.out.println("ActionRunner: delay"); - Timer.delay(delay); - continue; - } - } - - // Nothing to do; delay before looping. - Timer.delay(IDLE_DELAY_SECONDS); - } - } + if (timer.hasElapsed(currentDelay)) { + timer.reset(); + // System.out.println("ActionRunner: run"); + currentAction.run(); + + // If the current action is now done, remove it and loop back around. + if (currentAction.isFinished() == true) { + // System.out.println("ActionRunner: finished"); + currentAction = null; + } + } // currentDelay expired + } // currentAction != null + } // sync + } // while(true) + } // run() } } \ No newline at end of file diff --git a/src/main/java/frc/robot/status/Action.java b/src/main/java/frc/robot/status/actions/Action.java similarity index 67% rename from src/main/java/frc/robot/status/Action.java rename to src/main/java/frc/robot/status/actions/Action.java index 4b40927..2abd76a 100644 --- a/src/main/java/frc/robot/status/Action.java +++ b/src/main/java/frc/robot/status/actions/Action.java @@ -5,10 +5,21 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -package frc.robot.status; +package frc.robot.status.actions; public class Action implements Runnable { + // How long to delay intervals. + protected double intervalTime = 0.0; + + public double getIntervalTime() { + return intervalTime; + } + + public void setIntervalTime(double intervalTime) { + this.intervalTime = intervalTime; + } + // If this returns true the action runner thread will stop invoking run on this action. public boolean isFinished() { return true; @@ -16,12 +27,11 @@ public boolean isFinished() { // How long to delay the action runner thread before calling run again. // The thread will have a minium that is enforced if this value is to low. - public double getDelay() { - return 0.0; - } + + // Reset the action. Used when adding to the action runner to reset anything that needs resetting. + public void reset() {} // Every loop of the action runner thread will call this method. - public void run() { - - } + public void run() {} + } diff --git a/src/main/java/frc/robot/status/ChaseAction.java b/src/main/java/frc/robot/status/actions/ChaseAction.java similarity index 98% rename from src/main/java/frc/robot/status/ChaseAction.java rename to src/main/java/frc/robot/status/actions/ChaseAction.java index 9830bad..8624be5 100644 --- a/src/main/java/frc/robot/status/ChaseAction.java +++ b/src/main/java/frc/robot/status/actions/ChaseAction.java @@ -5,7 +5,7 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -package frc.robot.status; +package frc.robot.status.actions; public class ChaseAction extends LedAction { diff --git a/src/main/java/frc/robot/status/ImageAction.java b/src/main/java/frc/robot/status/actions/ImageAction.java similarity index 94% rename from src/main/java/frc/robot/status/ImageAction.java rename to src/main/java/frc/robot/status/actions/ImageAction.java index 9e34b7b..295b144 100644 --- a/src/main/java/frc/robot/status/ImageAction.java +++ b/src/main/java/frc/robot/status/actions/ImageAction.java @@ -1,10 +1,10 @@ -package frc.robot.status; +package frc.robot.status.actions; -import edu.wpi.first.wpilibj.util.Color; -import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; +import edu.wpi.first.wpilibj.util.Color; +import java.awt.image.BufferedImage; /** * Use an image file to set the addressable LEDs @@ -28,8 +28,8 @@ */ public class ImageAction extends LedAction { - private static final double DEFAULT_INTERVAL = 0.050; - private static final int FOREVER = -1; // forever + public static final double DEFAULT_INTERVAL = 0.050; + public static final int FOREVER = -1; // forever private File imageFile; private BufferedImage image; @@ -60,15 +60,16 @@ public ImageAction(String pathname, double interval, int count) { imageFile = new File(pathname); image = ImageIO.read(imageFile); intervalCount = count * image.getWidth(); + curIntCount = intervalCount; } catch (IOException e) { e.printStackTrace(); System.out.println("Problem opening image. Check the path.\nImage path = " + pathname); } } - @Override - public double getDelay() { - return intervalTime; + public void reset() { + super.reset(); + this.currentColumn = 0; } public ImageAction brightness(double brightness) { @@ -154,4 +155,4 @@ public void setImage(BufferedImage image) { this.image = image; } -} +} \ No newline at end of file diff --git a/src/main/java/frc/robot/status/LedAction.java b/src/main/java/frc/robot/status/actions/LedAction.java similarity index 82% rename from src/main/java/frc/robot/status/LedAction.java rename to src/main/java/frc/robot/status/actions/LedAction.java index 47a422a..5566991 100644 --- a/src/main/java/frc/robot/status/LedAction.java +++ b/src/main/java/frc/robot/status/actions/LedAction.java @@ -5,17 +5,16 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -package frc.robot.status; +package frc.robot.status.actions; import edu.wpi.first.wpilibj.AddressableLEDBuffer; +import frc.robot.status.Status; public class LedAction extends Action { // How many times to run, less than 0 will run forever. protected int intervalCount = 1; - - // How long to delay intervals. - protected double intervalTime = 0.0; + protected int curIntCount = 1; // The current interval. // Buffer this action uses for sending to the LEDs. protected AddressableLEDBuffer buffer = new AddressableLEDBuffer(Status.ADDRESSABLE_LED_COUNT); @@ -41,12 +40,17 @@ public LedAction(int red, int green, int blue, int brightness) { } } - public void setIntervalTime(double intervalTime) { - this.intervalTime = intervalTime; - } - public void setIntervalCount(int intervalCount) { this.intervalCount = intervalCount; + this.curIntCount = intervalCount; + } + + public int getIntervalCount() { + return this.intervalCount; + } + + public int getCurrentIntervalCount() { + return this.curIntCount; } // Implementations should override the updateBuffer method. @@ -62,12 +66,19 @@ public boolean isFinished() { // If the intervalCount is greater than 0 or less than zero // we're not finished. The run() method will decrement if greater // and never finish if less than (a repeating pattern). - if (intervalCount == 0) { + if (curIntCount == 0) { return true; + } else { + return false; } - return false; } + @Override + public void reset() { + this.curIntCount = this.intervalCount; + } + + // Require by the parent Action class. // This is invoked by the running thread until isFinished returns true. @Override @@ -81,8 +92,8 @@ public void run() { // Only decrement the intervalCount if it's over 0. // Otherwise it may overflow backwords and cause problems. - if (intervalCount > 0) { - --intervalCount; + if (curIntCount > 0) { + --curIntCount; } } } diff --git a/src/main/java/frc/robot/status/PowerUpAction.java b/src/main/java/frc/robot/status/actions/PowerUpAction.java similarity index 97% rename from src/main/java/frc/robot/status/PowerUpAction.java rename to src/main/java/frc/robot/status/actions/PowerUpAction.java index 913c9f1..8b67d3a 100644 --- a/src/main/java/frc/robot/status/PowerUpAction.java +++ b/src/main/java/frc/robot/status/actions/PowerUpAction.java @@ -5,7 +5,7 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -package frc.robot.status; +package frc.robot.status.actions; public class PowerUpAction extends LedAction { diff --git a/src/main/java/frc/robot/status/RainbowAction.java b/src/main/java/frc/robot/status/actions/RainbowAction.java similarity index 97% rename from src/main/java/frc/robot/status/RainbowAction.java rename to src/main/java/frc/robot/status/actions/RainbowAction.java index c5c37ec..9c3089e 100644 --- a/src/main/java/frc/robot/status/RainbowAction.java +++ b/src/main/java/frc/robot/status/actions/RainbowAction.java @@ -5,7 +5,7 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -package frc.robot.status; +package frc.robot.status.actions; public class RainbowAction extends LedAction { diff --git a/src/main/java/frc/robot/status/ScannerAction.java b/src/main/java/frc/robot/status/actions/ScannerAction.java similarity index 98% rename from src/main/java/frc/robot/status/ScannerAction.java rename to src/main/java/frc/robot/status/actions/ScannerAction.java index 061d804..03f08d7 100644 --- a/src/main/java/frc/robot/status/ScannerAction.java +++ b/src/main/java/frc/robot/status/actions/ScannerAction.java @@ -5,7 +5,7 @@ /* the project. */ /*----------------------------------------------------------------------------*/ -package frc.robot.status; +package frc.robot.status.actions; public class ScannerAction extends LedAction { diff --git a/src/main/java/frc/robot/status/commands/ActionCommand.java b/src/main/java/frc/robot/status/commands/ActionCommand.java index 4f54fbf..094f614 100644 --- a/src/main/java/frc/robot/status/commands/ActionCommand.java +++ b/src/main/java/frc/robot/status/commands/ActionCommand.java @@ -1,10 +1,10 @@ package frc.robot.status.commands; -import com.team2363.logger.HelixEvents; +// import com.team2363.logger.HelixEvents; import edu.wpi.first.wpilibj.command.Command; -import frc.robot.status.Action; +import frc.robot.status.actions.Action; import frc.robot.status.Status; public class ActionCommand extends Command { @@ -12,21 +12,27 @@ public class ActionCommand extends Command { private Status status = null; private Action action = null; - // Default constructor - will toggle the light. + // Default constructor. public ActionCommand(Action action) { - status = Status.getStatus(); - requires(status); + this(action, 0.0); // Make the command complete instantly. + } + public ActionCommand(Action action, double timeout) { + super(timeout); + this.status = Status.getStatus(); + requires(status); this.action = action; } + // Called just before this Command runs the first time @Override protected void initialize() { - HelixEvents.getInstance().addEvent("STATUS", "Starting ActionCommand"); + // HelixEvents.getInstance().addEvent("STATUS", "Starting ActionCommand"); // This will set our action to run on the subsystem. // This action will run in the dedicated thread to output the rainbow pattern. + action.reset(); status.setAction(action); } @@ -41,13 +47,13 @@ protected void execute() { protected boolean isFinished() { // This command literally just sets the action on the subsystem. // So there's nothing to do. - return true; + return this.isTimedOut(); } // Called once after isFinished returns true @Override protected void end() { - HelixEvents.getInstance().addEvent("STATUS", "Ending ActionCommand"); + // HelixEvents.getInstance().addEvent("STATUS", "Ending ActionCommand"); } // Called when another command which requires one or more of the same diff --git a/src/main/java/frc/robot/status/commands/ToggleFlashlight.java b/src/main/java/frc/robot/status/commands/ToggleFlashlight.java index bcd3a88..1a13e4b 100644 --- a/src/main/java/frc/robot/status/commands/ToggleFlashlight.java +++ b/src/main/java/frc/robot/status/commands/ToggleFlashlight.java @@ -1,7 +1,7 @@ package frc.robot.status.commands; -import com.team2363.logger.HelixEvents; +// import com.team2363.logger.HelixEvents; import edu.wpi.first.wpilibj.command.Command; import frc.robot.status.Status; @@ -33,7 +33,7 @@ public ToggleFlashlight(boolean state) { // Called just before this Command runs the first time @Override protected void initialize() { - HelixEvents.getInstance().addEvent("STATUS", "Starting ToggleFlashlight"); + // HelixEvents.getInstance().addEvent("STATUS", "Starting ToggleFlashlight"); // The command can either toggle as is, or set to a specific sate. if (forceSet == true) { @@ -59,7 +59,7 @@ protected boolean isFinished() { // Called once after isFinished returns true @Override protected void end() { - HelixEvents.getInstance().addEvent("STATUS", "Ending ToggleFlashlight"); + // HelixEvents.getInstance().addEvent("STATUS", "Ending ToggleFlashlight"); } // Called when another command which requires one or more of the same