本帖最后由 hello怪 于 2017-7-25 22:24 编辑 + v$ R }' D h9 @6 \
2 P, J+ F) x& V O& `(视频里面最终轮子与黑线的距离,都不超过6mm,最小距离只有2mm。虽然也有运气成分在里面,不过就结果来讲已经很令人满意了^_^)
优酷视频网址: http://v.youku.com/v_show/id_XMjkxOTU1MjEyNA==.html
" D3 `( s/ G! x
首先说说车子的设计思路,希望也能对大家有用。我想到的影响车子走直线的因素有以下几个方面: ) C+ Y! Q e( F# R- T; D- V
场地
/ ~3 }% u4 @2 P& q% Z: M 水平度和光滑度 在家里当然瓷砖的效果是最好的
* U# C9 S- |" X( C- E 线的直度 虽然规则里说起点终点之间不能有黑线,但是因为没用光感,完全是开环控制,所以也无所谓了。这里就直接用了瓷砖上的黑线来说明车子走的直不直/ U9 v& c) Y1 G% ]7 P
) {7 n% P ~& @: p
车子结构0 [) [/ Y2 I& u5 ~: @
轮子间距
" Y, c( \& f: |) q 轮子间距越大越好,稍微想一下便知3 Y c! C2 D U
轮子大小( K3 c: {% {0 M
轮子直径越小越好,而且轮皮要尽量薄(我这里用的是nxt自带的轮子)
& {' ] r' s- v6 Y7 |3 t# I, E; h 随动轮的设计
- Z* }, E- e0 _1 H$ `, b' l 随动轮转动时对车子的影响应该尽量小。这里我自己想出了一个设计方案(当然我觉得别人也用过),让车子几乎不受随动轮的影响
0 `7 L; v% ^: s+ a8 y 重心位置
9 W3 k0 o# X5 ^! h 重心应该稍稍靠近主动轮以增大主动轮的抓地能力。但是太靠近的话就会降低车子的稳定性,并且升级空间较小
4 [4 R$ X' o( W; q 结构稳定性 不用说,肯定是越结实越好。但是不能造成重量过大
8 b! U" Q- N9 _6 V1 E" v7 b# t 轮子个数 有三种方案:平衡车(独轮或双轮),三轮车,四轮或以上。虽然很想做平衡车,但是无奈暂时不会用陀螺仪。四轮的话转角不好把控,而且结构复杂,所以就用了最简单的三轮车。(另外,我个人认为不能拐弯的车子就不能叫车子~叫火车或者轨道炮比较合适。。。)4 B% m' u& k& x0 U: b- m7 K
驱动方式 这里我选择了直接由马达驱动轮子,不经过任何齿轮传动,一种简单准确的方式驱动
@2 _1 j% K3 h d3 h" Y+ {% M. H) C, |' {% i* S+ v9 i% ]
控制程序% S# _0 S% ^7 k& A
运动过程控制( y+ u1 a8 T/ z9 R; K
好的程序应该使轮子不打滑,车子运行平稳。由此采取平滑运动的控制方法,让车子开始时(近似)匀加速,直到速度足够(160度每秒)。在开始时,加速度甚至更小,可以参考我的程序(加速度增加->加速度不变->加速度为零) ?3 ^3 _+ l; B! q: a
/ _- I: p# q( o( @" A8 o7 H/ C# ]调试与运行
/ O+ ^" T: E6 b; \4 Z 轮子转速调整(车轮大小的设定)+ R2 W! _6 T7 @; X
这个就没什么办法,只能硬着头皮调了。调整轮子的大小设置,实际上就是调马达转速,没有什么更有效的解决办法, ]1 b1 j0 T6 E& |
起始位置车子正方向和直线间的夹角4 ?& v5 a" u7 e8 F/ a6 o+ U
一个非常重要的因素,可谓差之毫厘谬以千里。所以尽可能减小两者的方向差。顺带一提,开环控制的小车,如果最终结果差距在一厘米只内,就已经没有什么可比性了。一厘米之内运气成分占比很大,因为0.01rad(0.5度以内)的夹角足以造成差距一厘米的偏差。这就是开环控制的特点 4 R3 q0 Y' S& S5 m" L3 K2 e* o3 y2 P
8 d/ j+ v% h) s
9 x( b/ R# j* ?6 T+ |5 u
然后上源代码: - - d* b2 q5 H9 w$ W/ g4 J5 X
- importlejos.robotics.navigation.DifferentialPilot;
) ~: ~/ L/ y, Y, ?* | - import lejos.util.Delay;. }0 N: V3 i& k- A' A
9 Z1 L: H1 [( v& }, \% {, ` V- /**' J7 h. q1 [) ^8 `7 y
- *Robot that stops if the buttons are presses before it completes its travel.
8 ~! q+ G$ `5 g" f* `+ c8 f/ u - */
$ P/ ~$ R+ E) u" M$ w6 G/ ]
) ~' Z. W6 J; \4 A2 s, c+ F
9 K1 ^3 I- j) w4 t6 ?, b B- public class Straight {
0 v, d/ J) }; \5 Z% u - DifferentialPilotpilot;- f; u; T$ ?* x6 |4 v; d$ Q1 h
- doubleleftD = 4.3, rightD = 4.3;
/ N* T9 C5 S7 M
* ?/ V: \" x, r- publicvoid adjust() {
' g. g8 B) c0 H/ ^# m. K. b$ C! J - //wait for release ?+ l: l }/ p
- while(Button.readButtons() > 0)5 R, S# A* |4 T1 u
- ;
1 ^9 y! S2 V8 P& n - while(Button.readButtons() == 0) {
1 |$ t! [3 O7 p Y - //input size by adjusting the wheels0 \5 |# }: j' ~# A* i
- rightD= (double) (Motor.A.getTachoCount()) / 2160 + 4.3;
5 G. l- h5 u( ^# r) @% {4 r - leftD= (double) (Motor.B.getTachoCount()) / 2160 + 4.3148;// 调试所得值
\" k5 j3 Y4 s G - 1 @* O. L* ?4 i. z7 {( Q9 v: z
- //display the size input& Z0 n/ d) H0 } D% @
- LCD.drawString("L:"+ String.valueOf(leftD), 0, 0);
1 y# m0 @2 N+ r, m - LCD.drawString("R:"+ String.valueOf(rightD), 0, 1);
# D! C0 {3 E) X - Delay.msDelay(100);
* m4 B z# R' x6 U/ \ - LCD.clear();
: }6 w$ S9 ^# Q9 ]4 B4 l5 l" e6 ?2 { - }
) u9 X |5 v3 T! x" t
/ E; U0 l* b% a* X3 d$ {- }
) ?* [% [. I$ v# B9 f. v0 ^/ n1 z - . W; F$ l+ c# u- T3 ?# L
- publicvoid go() {, U: O4 u% t' ?
- //准备起步
" q$ F) E: c1 \' X - //wait for release
5 k2 B; n- m& I) V' T1 [ - while(Button.readButtons() > 0)1 P7 m8 j& a- H0 {, j0 I
- ;
! G# h1 t8 V) c* L - System.out.println("pressto go");
4 @5 _& A; `( r9 s* ]8 j6 p+ ]
. O$ I2 U6 g+ X- Button.waitForAnyPress();8 n! G9 ~; L' _3 W
- LCD.clear();
# `9 v: k$ }5 B( h0 O0 b6 r' e3 ` - " U3 e2 h) \: V
- //初始化! X/ w6 o# h6 v9 T9 w( W" s
- pilot= new DifferentialPilot(rightD, leftD, 13.5, Motor.A, Motor.B, true);& Q0 j# m3 p# }+ M- k* I, I
- pilot.reset();
% {6 b* k0 X3 Y* D
/ n q) j+ T; @! [6 l' _9 ]: m- Delay.msDelay(3000);& p; T% ~8 q* `7 L2 T8 d
& K% u9 _, @0 V" R; P* S) L A- doublespeed = 10;/ u0 h" a" H; W. D8 d7 ]+ v
- doubledistance = 0;
3 r* f( `- ]4 H" A, Y - " g2 Y% Y: @/ U( i! J6 T- N
- //起步加速& ?) J' J6 X, E9 W; I
- pilot.travel(300,true);
# X2 Z6 X: ?; @7 U9 D; i9 s5 O$ P - w F/ R% S7 ]) [: l* F7 A
- while(distance < 20) {
% J" u7 Q; P: T5 n+ h2 p4 j, T - distance= pilot.getMovement().getDistanceTraveled();! `+ e$ n( [2 K( t: c1 m: u
- speed= distance * 5 + 10;' ^- m f. ~ `6 {) x0 n
- pilot.setRotateSpeed(speed);
9 Y+ {/ H& N/ p' n4 g5 D( o+ x - Delay.msDelay(100); j: |2 D0 p% @0 J. q6 [
- }
- l7 ] W, w9 T1 O - for(int i = 0; i < 10; i++) {# t3 l3 p! T$ T; O) E( o
- speed+= 5;4 r3 W% M$ j( @9 v
- pilot.setRotateSpeed(speed);6 X+ x3 X! P" W! G
- Delay.msDelay(200);0 Z0 a- ~3 S* ~8 A
- }- `+ y; ~* C) w
- - _1 F% ~0 J+ X; P+ |. Z' `
- //TODO 减速; |% z0 N0 U, j" C* a- Y
- & P. }5 V" r, w3 G% e
- //停止机能
+ ^: [0 O4 C; o: r7 o3 [& G: S0 x0 Q& E - while(pilot.isMoving()) {
' T4 }2 u0 m9 q+ n - if(Button.readButtons() > 0)
5 B3 \+ b2 {( Q- E9 M - pilot.stop();, X2 l$ a d; {5 z2 }/ b r- b
- }
2 k7 \: B5 Z* }9 d2 b% ?/ `, n' K - L2 \4 _, {! y+ n( v5 {( h5 q
- System.out.println("" + pilot.getMovement().getDistanceTraveled());
$ z% u- R& J# ?4 T. Z - System.out.println(-Motor.A.getTachoCount());7 m3 L6 n4 x3 ]- Z& a( O
- System.out.println(-Motor.B.getTachoCount());8 y/ S% ^ m6 k/ q/ d
- Button.waitForAnyPress();- h+ z( H+ A. I# l) t+ Z' Q. [
- }( P1 V. Y; R( R1 J; v; j3 U
- $ B+ z- _1 l+ v
- publicstatic void main(String[] args) {
6 x3 H s* }' P5 f* g5 V - Straighttraveler = new Straight();
* T; l% s( W% G# k2 ]- J# {1 I
5 r: O: C) _2 \1 {1 j( x. ?. u- traveler.adjust();
- v$ A s% ^2 a5 s4 M - traveler.go();
- r# d' ~7 K, x; P7 `5 A4 X - }
* B% ]! e% C& S - }
复制代码
' m2 f! R" x: Q |