本帖最后由 hello怪 于 2017-7-25 22:24 编辑
3 _/ \5 D0 u+ P/ H1 P( Q2 {6 c1 O; }
(视频里面最终轮子与黑线的距离,都不超过6mm,最小距离只有2mm。虽然也有运气成分在里面,不过就结果来讲已经很令人满意了^_^)
优酷视频网址: http://v.youku.com/v_show/id_XMjkxOTU1MjEyNA==.html \4 W. Y' g2 S
首先说说车子的设计思路,希望也能对大家有用。我想到的影响车子走直线的因素有以下几个方面: + o, H ]6 s3 O+ U# j
场地
. _/ H# C8 g" {( a% J 水平度和光滑度 在家里当然瓷砖的效果是最好的
5 w, R! s- w+ h' t% W% J 线的直度 虽然规则里说起点终点之间不能有黑线,但是因为没用光感,完全是开环控制,所以也无所谓了。这里就直接用了瓷砖上的黑线来说明车子走的直不直
& ^7 G( p2 r8 Z) M/ C- x( @3 O0 }( F
车子结构
0 u. D) h0 L; O) n 轮子间距/ T5 g: C# d3 l2 ?7 {4 O7 C
轮子间距越大越好,稍微想一下便知
4 ^1 W h ^; H' Y 轮子大小/ H* H9 U: k& M8 H7 j5 u. T
轮子直径越小越好,而且轮皮要尽量薄(我这里用的是nxt自带的轮子)' `9 a/ M/ m* S: d) I3 F! v/ F
随动轮的设计. \, _+ C* R4 q R1 A' o3 Z
随动轮转动时对车子的影响应该尽量小。这里我自己想出了一个设计方案(当然我觉得别人也用过),让车子几乎不受随动轮的影响; u% i/ m5 r. a/ \' [1 O$ p; t* i. b
重心位置
% W( t5 o9 c& [8 O4 u3 I 重心应该稍稍靠近主动轮以增大主动轮的抓地能力。但是太靠近的话就会降低车子的稳定性,并且升级空间较小
' Y8 j" S$ S" Q# f3 W$ C0 k 结构稳定性 不用说,肯定是越结实越好。但是不能造成重量过大$ o7 X( u: W6 x. F
轮子个数 有三种方案:平衡车(独轮或双轮),三轮车,四轮或以上。虽然很想做平衡车,但是无奈暂时不会用陀螺仪。四轮的话转角不好把控,而且结构复杂,所以就用了最简单的三轮车。(另外,我个人认为不能拐弯的车子就不能叫车子~叫火车或者轨道炮比较合适。。。)0 }1 x: p# U4 Q: l( B
驱动方式 这里我选择了直接由马达驱动轮子,不经过任何齿轮传动,一种简单准确的方式驱动0 y8 k" Y9 ~( k% W
: c2 H. @# K! J
控制程序+ U J6 a. {6 L; t0 V/ m
运动过程控制0 J8 M$ U$ x& O2 E4 O6 ^$ s
好的程序应该使轮子不打滑,车子运行平稳。由此采取平滑运动的控制方法,让车子开始时(近似)匀加速,直到速度足够(160度每秒)。在开始时,加速度甚至更小,可以参考我的程序(加速度增加->加速度不变->加速度为零)
. C/ s6 M% e" a2 F S) Z, V) G
" v0 a- H7 Q" c" X调试与运行
" C" U5 S3 ?& ]3 h ]( b 轮子转速调整(车轮大小的设定)
& `% W' F8 Y: B( [' } 这个就没什么办法,只能硬着头皮调了。调整轮子的大小设置,实际上就是调马达转速,没有什么更有效的解决办法8 j' z, I# v% Q
起始位置车子正方向和直线间的夹角
. r3 f" O0 w7 n+ A+ M8 f% C 一个非常重要的因素,可谓差之毫厘谬以千里。所以尽可能减小两者的方向差。顺带一提,开环控制的小车,如果最终结果差距在一厘米只内,就已经没有什么可比性了。一厘米之内运气成分占比很大,因为0.01rad(0.5度以内)的夹角足以造成差距一厘米的偏差。这就是开环控制的特点 ; v- b8 v9 Z2 E/ U
4 K9 m) _: d1 {* R
0 i# D- o. k1 t7 x8 ~, l k
然后上源代码: - 8 L" Y O- y4 j* @* S
- importlejos.robotics.navigation.DifferentialPilot;" t6 Z. @- x E0 `& d
- import lejos.util.Delay;
9 K( G& ]2 N- i; J
1 _9 ?5 b0 d. U% I* @) v- /**
1 G3 U) v5 p. H - *Robot that stops if the buttons are presses before it completes its travel.
" j: W G; R+ e7 _: n - */
# D; z/ W, v* o$ g5 ] - % U8 r# N2 O, }6 j1 t1 X
+ M2 ^' B- E; m6 o8 m- public class Straight {: i6 p! Y# @. |- a1 M
- DifferentialPilotpilot;
" I, v+ d# n# b! _" u8 M* I3 u - doubleleftD = 4.3, rightD = 4.3;
4 s, L$ x. s7 e; ~: W( [8 _ - , M B# K2 @ { f g4 D
- publicvoid adjust() {
1 J; ]# L: S/ Q$ ]2 v& \8 `4 B - //wait for release
% O5 u( k& D8 n4 h2 x - while(Button.readButtons() > 0) z, O. E8 g& C# [* [! q
- ;2 ^1 }: ^1 [& O/ h4 Y, r% n
- while(Button.readButtons() == 0) {7 u# m2 W+ I0 V' g, F; D4 }
- //input size by adjusting the wheels6 p' i3 I1 z( t+ a! ]/ m+ _2 H
- rightD= (double) (Motor.A.getTachoCount()) / 2160 + 4.3;
: D* p( j* ~3 o2 K; A - leftD= (double) (Motor.B.getTachoCount()) / 2160 + 4.3148;// 调试所得值) G% _( Z) c& y! O, k- K
- % V$ c6 _3 o. G/ k* e& I& Q
- //display the size input/ p- O' r/ I7 {/ j p
- LCD.drawString("L:"+ String.valueOf(leftD), 0, 0);
Y% Q9 t& f0 O$ ?- K% \8 Z( E+ o% [ - LCD.drawString("R:"+ String.valueOf(rightD), 0, 1);
' ^1 n. @: {2 @$ f5 ]) u - Delay.msDelay(100);' _" f4 G, z! }2 Z* t5 h
- LCD.clear();
- @9 ^+ L) q; X - }+ q4 U. T" x; m- g7 O; t6 E
. t6 }- Q$ V& ]5 E: A% ?6 @/ ~- @- }; f0 H! ?: m# _# y M( D
- 8 e" y+ j2 T+ N8 h- |: d3 W: r
- publicvoid go() {
6 E/ Z, \$ Z' B$ Y - //准备起步! |$ R' T! U# h- ^
- //wait for release
/ v! n5 [& v' b6 D S- ]: V - while(Button.readButtons() > 0)
, T( N, |! P6 X7 Z; {# \ - ;/ ?/ {6 H9 T2 F8 U
- System.out.println("pressto go");
4 m3 C% ]) T- | ^( F8 [ S. ~) M/ {
$ ~8 c. b1 F2 t# u ^9 r+ N- Button.waitForAnyPress();
' z. {' a; X# i* w/ U - LCD.clear();
( Q' ?1 _% Q4 h - 4 s$ k7 Z, R5 l
- //初始化
) j# O5 J6 w# | t7 L& s - pilot= new DifferentialPilot(rightD, leftD, 13.5, Motor.A, Motor.B, true);1 _+ X( ~* e8 s) g/ F, {9 ~# e
- pilot.reset();
+ B5 D$ s0 `/ y# E, k( u0 Q+ V7 f0 g# V
- \( c) P! o9 R" Y, y- Delay.msDelay(3000);
, W7 Q! @$ A0 o! R% k' B - + l% Q4 ~: V- Z
- doublespeed = 10;4 r: t% f1 }% {
- doubledistance = 0;
4 O3 m/ D! V* E9 E; H - $ X* ]" y6 c m
- //起步加速
) _( c; e. w8 |3 Z; |) h7 \+ L - pilot.travel(300,true); q& J9 _. q. M9 R! C
3 L; T( j/ y( S2 U [/ B2 I- while(distance < 20) {& x& s) K8 j [
- distance= pilot.getMovement().getDistanceTraveled();9 H7 F7 \9 j7 Q
- speed= distance * 5 + 10;- p: H* u ~5 H
- pilot.setRotateSpeed(speed);
2 }8 s. s; k) c( c% q# J - Delay.msDelay(100);/ `, J3 K$ K9 m8 O# W5 ^
- }
+ u. n( l8 q3 g. L( _& R& q - for(int i = 0; i < 10; i++) {
8 {; I7 X/ T3 T% [4 C - speed+= 5;! F' V% `9 \9 a1 C% o6 U
- pilot.setRotateSpeed(speed);
7 \3 ^" Z8 K0 Z) Y9 C, I - Delay.msDelay(200);& ]% o7 F' s+ h0 {" }, b
- }# V/ \- [" m; H$ S+ |* E, l; C
" ]3 s- @" T |- k# Y: s5 }- //TODO 减速; p/ o6 n# O" K+ d: P" X/ U
+ L( ~$ `3 n! D0 D& V) w- m- //停止机能' v1 K4 G: O% k1 O
- while(pilot.isMoving()) {' P( c0 f. B# ^; D
- if(Button.readButtons() > 0)
8 y) E8 Z$ Y7 l! N$ S - pilot.stop();
, G" U+ g+ c9 E' v, o - }" t- w3 W+ {2 S8 D
- 1 ~. G; \5 @: `7 [7 w. {# k- t) F8 F+ |
- System.out.println("" + pilot.getMovement().getDistanceTraveled());
- U7 u# X4 D4 I/ X( G - System.out.println(-Motor.A.getTachoCount());
/ o4 d, }0 B3 y, n* w4 a( H - System.out.println(-Motor.B.getTachoCount());) X' w3 L8 T$ ~
- Button.waitForAnyPress();6 ]/ V5 @# X1 V/ p! ]
- }' R* p* c y0 S: U. F9 `) p$ ?; i
- , F: }5 Z# Q4 \8 f$ |
- publicstatic void main(String[] args) {
$ d( k6 k5 \" H, h - Straighttraveler = new Straight();
. Q- U1 ^2 i7 z1 w1 m' I$ H) a* z - ; o7 k% a0 Y2 s( \& |+ J
- traveler.adjust();
% b( g9 K0 m6 r$ L - traveler.go();$ ~4 {7 P* l2 a e6 Y) u% V
- }9 f* A" ?% w# d- s( j
- }
复制代码 - Z. t" B+ g5 _
|