本帖最后由 hello怪 于 2017-7-25 22:24 编辑
* t$ q) w- Y) W$ L0 A
' L+ e' L: S( g* ~(视频里面最终轮子与黑线的距离,都不超过6mm,最小距离只有2mm。虽然也有运气成分在里面,不过就结果来讲已经很令人满意了^_^)
优酷视频网址: http://v.youku.com/v_show/id_XMjkxOTU1MjEyNA==.html 0 H" q( S6 R% }9 N
首先说说车子的设计思路,希望也能对大家有用。我想到的影响车子走直线的因素有以下几个方面: & j" V$ b5 g7 s$ N/ ~
场地
! G3 d6 Q A3 Z9 d. X8 q 水平度和光滑度 在家里当然瓷砖的效果是最好的
5 P2 m* V$ V0 P! h9 m: i- a# e 线的直度 虽然规则里说起点终点之间不能有黑线,但是因为没用光感,完全是开环控制,所以也无所谓了。这里就直接用了瓷砖上的黑线来说明车子走的直不直
5 u. u* Y6 j3 H+ b1 n8 P# C: T& B3 x4 ?
车子结构; w4 e. J4 J6 g, g5 y# @
轮子间距
* G3 p! U5 \; [ 轮子间距越大越好,稍微想一下便知" |( f! I/ O! D: n" }
轮子大小- @, ]2 Q. h- k( r/ L, U7 R
轮子直径越小越好,而且轮皮要尽量薄(我这里用的是nxt自带的轮子)
0 L9 p/ d; x3 n+ T' C 随动轮的设计
9 s8 q8 T [& J/ [; U# s% T V 随动轮转动时对车子的影响应该尽量小。这里我自己想出了一个设计方案(当然我觉得别人也用过),让车子几乎不受随动轮的影响
* P, [ q% V. p$ s 重心位置7 k6 u# {$ E1 a" Z; L7 U
重心应该稍稍靠近主动轮以增大主动轮的抓地能力。但是太靠近的话就会降低车子的稳定性,并且升级空间较小
( M4 C& [& [/ v. O* H$ G' T& w4 b; F$ J 结构稳定性 不用说,肯定是越结实越好。但是不能造成重量过大9 p1 p& o& |" M% J3 L" T
轮子个数 有三种方案:平衡车(独轮或双轮),三轮车,四轮或以上。虽然很想做平衡车,但是无奈暂时不会用陀螺仪。四轮的话转角不好把控,而且结构复杂,所以就用了最简单的三轮车。(另外,我个人认为不能拐弯的车子就不能叫车子~叫火车或者轨道炮比较合适。。。)4 _+ W) l3 A t0 b0 I
驱动方式 这里我选择了直接由马达驱动轮子,不经过任何齿轮传动,一种简单准确的方式驱动
; a/ {6 X: y4 r, G% r/ K1 Q/ ~* _ t; V1 Y) s2 |9 J* F- [
控制程序4 k6 b9 e& }$ p: c0 c# ]! J0 w
运动过程控制4 i. P! N2 K/ N' u0 {4 q
好的程序应该使轮子不打滑,车子运行平稳。由此采取平滑运动的控制方法,让车子开始时(近似)匀加速,直到速度足够(160度每秒)。在开始时,加速度甚至更小,可以参考我的程序(加速度增加->加速度不变->加速度为零)* v+ v$ q9 u- H* C. W+ W
% A; j7 t/ m8 V* X# h( x
调试与运行& |: e4 |4 E- S A8 U, g; f
轮子转速调整(车轮大小的设定)2 ~; `8 |3 ^+ \8 ]1 X) W
这个就没什么办法,只能硬着头皮调了。调整轮子的大小设置,实际上就是调马达转速,没有什么更有效的解决办法/ r9 x ?3 K, J
起始位置车子正方向和直线间的夹角4 `$ p/ \: q& F! Y4 U8 E
一个非常重要的因素,可谓差之毫厘谬以千里。所以尽可能减小两者的方向差。顺带一提,开环控制的小车,如果最终结果差距在一厘米只内,就已经没有什么可比性了。一厘米之内运气成分占比很大,因为0.01rad(0.5度以内)的夹角足以造成差距一厘米的偏差。这就是开环控制的特点 4 d/ V4 \* e1 H* L
, j* l% h, w+ D+ K" p) ]! W
4 s1 p, R$ m' o* C* r5 I/ k 然后上源代码: - ) v) \8 c- P/ g0 F/ D0 J
- importlejos.robotics.navigation.DifferentialPilot;+ l5 w. ^4 \" ^- o. w9 d4 q
- import lejos.util.Delay;
c) z1 C+ |* [2 H1 f - 3 w% a" y6 [" @1 y5 w- {- ?* V; m6 A
- /**
* z, h- f! ~$ t - *Robot that stops if the buttons are presses before it completes its travel. {3 s# B1 _ T+ L& C$ ]( i, g
- */
9 g6 P% d) ~# a - 4 w1 X* |( d* o) |
1 y" R) } v5 I1 Y( [/ Z- public class Straight {6 N }: _* K0 _
- DifferentialPilotpilot;: H: k6 d; h) Y
- doubleleftD = 4.3, rightD = 4.3;
3 m; s! h2 i& `+ C* \
. I) L* m3 W ^% p I3 r$ Y- publicvoid adjust() {
0 a. {5 m' }0 d' N; z/ J6 y+ v - //wait for release& d' [4 p$ G+ B! m# V: l
- while(Button.readButtons() > 0)
' T Y9 j2 K, G7 d - ;3 v q3 S t1 U) y, I _
- while(Button.readButtons() == 0) {2 \: A( l! M ~+ ^/ h
- //input size by adjusting the wheels
0 P/ \+ u2 }$ P - rightD= (double) (Motor.A.getTachoCount()) / 2160 + 4.3;
7 b( r& f6 P& q- v* V: [ - leftD= (double) (Motor.B.getTachoCount()) / 2160 + 4.3148;// 调试所得值
1 h- Z4 c9 Q; K7 q9 c% Y - * e, F# c# N2 M
- //display the size input5 x! r+ q+ w! E5 w/ o
- LCD.drawString("L:"+ String.valueOf(leftD), 0, 0);
[9 v, e9 r: }2 w! U( f - LCD.drawString("R:"+ String.valueOf(rightD), 0, 1);" @! K1 T* ^/ ^; I( s$ M
- Delay.msDelay(100);
; J/ D* Y3 U! q$ L - LCD.clear();
$ j4 o) j: U6 Q* a4 u - }8 s) U+ s/ A# V1 n. ?) {2 V
- ; P; _( ?6 Z3 K; H
- }
S6 H- T+ l/ p2 ~( e
6 C; n) O7 F3 d9 C9 \% O, W- publicvoid go() {. K6 I% g0 T% q# ~ Y) J- I8 H7 }6 H
- //准备起步3 k3 \* l5 t4 J" W# O
- //wait for release
9 }3 r( h; l: B0 c$ v" M: k - while(Button.readButtons() > 0)
# p6 v7 _5 L! `( K; V - ;% P( H) w, ^1 l \7 Y4 ~3 l
- System.out.println("pressto go");2 n& g& Y- W8 z$ c
- 3 X8 |3 E6 d0 Z [
- Button.waitForAnyPress();4 ~+ m, }3 i7 f- O7 F
- LCD.clear();
- {8 ?+ N) Z% U2 l3 \
+ c b9 z4 }, f9 M. ?4 b$ \- //初始化
$ {' n4 y+ g$ n( o1 h0 U - pilot= new DifferentialPilot(rightD, leftD, 13.5, Motor.A, Motor.B, true);. k2 U0 b- e- I' ?- b
- pilot.reset();6 x: L4 E2 G1 ]. F# F1 K
. ]! @% e" Z! Q8 z- Delay.msDelay(3000);
7 ]8 N3 g$ _' j! x3 s s9 h0 h: L: r - % P4 e6 o! Y) U# e |6 y
- doublespeed = 10;
# O* Z/ G1 ~: N - doubledistance = 0;
! {+ G; X. Z4 `) H8 o" y8 n
3 U! R2 ~' I/ ^; H* k" X- //起步加速
) c K( u' B# y6 F/ S" g - pilot.travel(300,true);$ E% H A/ A P3 A' B \
- - n& s6 o2 q/ t9 @! F% C! P& f% \
- while(distance < 20) {
7 b; G* F7 I. v2 g }* E - distance= pilot.getMovement().getDistanceTraveled();) e: J3 x1 ~' a M/ h3 {
- speed= distance * 5 + 10;
1 s; u. @1 s7 ~0 J1 ^. Q - pilot.setRotateSpeed(speed);3 k. J; Q6 Y! {
- Delay.msDelay(100);& P) N' Q2 G; f
- }' I! `9 g# V3 T7 ?3 S& j) h, N
- for(int i = 0; i < 10; i++) {
# k( O% Y7 E% R! m4 E% r8 b. r! a2 l - speed+= 5;
. u7 K; V( r( V# U0 a - pilot.setRotateSpeed(speed);, {$ t* |0 N3 z7 G
- Delay.msDelay(200);. i- T/ J1 T' p" C6 _+ M& ]
- }
, H5 y2 x4 y* H( C# w: O6 ^
1 W) y+ r) a5 h, \; n- //TODO 减速
3 m7 Q& [1 X, C0 p6 {) x - * f/ l* @( \4 \+ j c
- //停止机能
- w8 P9 D7 [- P4 Z; F0 c - while(pilot.isMoving()) {
3 O5 v% z% @/ [0 q" } - if(Button.readButtons() > 0)
- z( h6 @9 m1 _8 G1 ?& s - pilot.stop();* Q6 Z8 W/ e4 }& W) q3 `. f: E
- }- C9 I2 _! t3 b, r6 B
- ; [5 i8 O3 _/ _' G; N
- System.out.println("" + pilot.getMovement().getDistanceTraveled());
- P0 P) h# [2 y - System.out.println(-Motor.A.getTachoCount());$ u) P/ c$ \9 I1 n
- System.out.println(-Motor.B.getTachoCount());8 A7 L( z7 Q- ~; t- x; H: `
- Button.waitForAnyPress();* R' f# x S& p5 ]$ c- Q
- }/ s- s; g0 [4 ~ d" q/ `
- ( i5 h. m8 m* Q
- publicstatic void main(String[] args) {
9 y" w% j q$ P d- z - Straighttraveler = new Straight();
! G+ }& g" R% f - 9 w& ]8 j- @' q6 w. j: u/ k6 K
- traveler.adjust(); h# Q/ z% y1 A u# ]
- traveler.go();
( E, U4 m9 W+ @" h0 n - }
' P7 X+ h' a# Y - }
复制代码 ; N2 {# r- Q, L) H# C( x1 ~. r- o
|