本帖最后由 hello怪 于 2017-7-25 22:24 编辑
! b( \' r( C, G7 @7 a d0 I4 N4 }. Q: [6 i
(视频里面最终轮子与黑线的距离,都不超过6mm,最小距离只有2mm。虽然也有运气成分在里面,不过就结果来讲已经很令人满意了^_^)
优酷视频网址: http://v.youku.com/v_show/id_XMjkxOTU1MjEyNA==.html
6 T1 m- [( u5 S$ Q h- \
首先说说车子的设计思路,希望也能对大家有用。我想到的影响车子走直线的因素有以下几个方面:
5 P: t7 w/ s! V% v& u场地
6 p- l: f! P. I* {7 r# F2 i+ W1 C 水平度和光滑度
在家里当然瓷砖的效果是最好的7 n* Y, h) i; l& d
线的直度 虽然规则里说起点终点之间不能有黑线,但是因为没用光感,完全是开环控制,所以也无所谓了。这里就直接用了瓷砖上的黑线来说明车子走的直不直
/ x; O1 U r1 d. J/ r0 i) I z1 l4 ]/ q: B. t
车子结构
% o; Q. ?. S9 P 轮子间距
- D9 J& D) ^6 d0 _8 U) `9 e 轮子间距越大越好,稍微想一下便知
+ o6 v; D5 r- J) I0 G 轮子大小% J) O, ? M/ v# C
轮子直径越小越好,而且轮皮要尽量薄(我这里用的是nxt自带的轮子)9 m8 M* r: V; w4 r- E Z
随动轮的设计. K1 \3 ~5 h3 C
随动轮转动时对车子的影响应该尽量小。这里我自己想出了一个设计方案(当然我觉得别人也用过),让车子几乎不受随动轮的影响
+ m; o! m; K: W5 k 重心位置
8 O) e h; B. W/ @- a 重心应该稍稍靠近主动轮以增大主动轮的抓地能力。但是太靠近的话就会降低车子的稳定性,并且升级空间较小0 Z& L9 ~, x& p% j9 U/ a; \. S
结构稳定性 不用说,肯定是越结实越好。但是不能造成重量过大1 ~3 E }% I& t/ Y
轮子个数 有三种方案:平衡车(独轮或双轮),三轮车,四轮或以上。虽然很想做平衡车,但是无奈暂时不会用陀螺仪。四轮的话转角不好把控,而且结构复杂,所以就用了最简单的三轮车。(另外,我个人认为不能拐弯的车子就不能叫车子~叫火车或者轨道炮比较合适。。。)
4 e' b/ P: R9 { 驱动方式 这里我选择了直接由马达驱动轮子,不经过任何齿轮传动,一种简单准确的方式驱动: ]6 I$ ?" B. N( q8 h
% v0 }. `' K- ~+ K1 ^6 j
控制程序( N$ `, ?7 B8 l$ X
运动过程控制7 _9 P# T! I# V/ h3 M0 G
好的程序应该使轮子不打滑,车子运行平稳。由此采取平滑运动的控制方法,让车子开始时(近似)匀加速,直到速度足够(160度每秒)。在开始时,加速度甚至更小,可以参考我的程序(加速度增加->加速度不变->加速度为零)
* q' J& ?$ S- ]; _- |) C3 m9 }* \4 Y8 Z* S0 w$ m; {' h* [3 p6 K4 j6 Q4 \
调试与运行0 d$ a. A. D; S& C& W1 K
轮子转速调整(车轮大小的设定)' h) J4 B9 |( F) u% e
这个就没什么办法,只能硬着头皮调了。调整轮子的大小设置,实际上就是调马达转速,没有什么更有效的解决办法
& n: Q' q" f7 g8 c* c5 u& Y* x 起始位置车子正方向和直线间的夹角 C4 p$ D( H/ V2 @
一个非常重要的因素,可谓差之毫厘谬以千里。所以尽可能减小两者的方向差。顺带一提,开环控制的小车,如果最终结果差距在一厘米只内,就已经没有什么可比性了。一厘米之内运气成分占比很大,因为0.01rad(0.5度以内)的夹角足以造成差距一厘米的偏差。这就是开环控制的特点
g2 A Z- j- j4 v9 r
' F2 T, _/ Y1 A( e8 k0 i. j, ~. g( @1 R, i% f
然后上源代码: - * D% v% x& @* f2 G! @, z/ v
- importlejos.robotics.navigation.DifferentialPilot;
- H4 G0 X; `6 v" |, b* j - import lejos.util.Delay;
, T, x$ u' C$ D# k- A( \- H - * s5 C1 l7 t! e0 u- K
- /**+ ~: _4 Z% _1 _
- *Robot that stops if the buttons are presses before it completes its travel.
+ ^, ^2 v2 b# g. i3 T" O - */
# S5 ~( N& c! I5 \$ k - : l3 D5 E* v: \" B: n
& g* Y/ S6 h; n6 w! w4 I9 m- public class Straight {
: Q, s' B# a/ u - DifferentialPilotpilot;9 R4 N8 o2 J) l! @' z- p
- doubleleftD = 4.3, rightD = 4.3;! y# h. _" A- g* ]" ?" N r
- / r, ? e- r) }' C' @8 U
- publicvoid adjust() {- W9 V8 k8 W3 \2 T. l
- //wait for release: A, Y" D' `2 U8 }' w6 n
- while(Button.readButtons() > 0)! M1 i9 @0 P: _9 g2 N8 y
- ;/ | X) w6 x3 B% ?9 n
- while(Button.readButtons() == 0) {
5 ^- S W9 Y- Q6 D( V8 @4 z9 R4 L - //input size by adjusting the wheels
/ S7 p. ]# }( k+ N" w' j' Z) a, |) R - rightD= (double) (Motor.A.getTachoCount()) / 2160 + 4.3;7 T- E# I* o$ k4 ^+ L
- leftD= (double) (Motor.B.getTachoCount()) / 2160 + 4.3148;// 调试所得值
4 a% F' W% a }4 z
% ]! b6 k t0 t R) p; @) P; X- //display the size input
$ V& K$ `7 G4 R" z& Y3 r$ q - LCD.drawString("L:"+ String.valueOf(leftD), 0, 0);
# K# d+ {6 ]/ c8 ^" ?* S - LCD.drawString("R:"+ String.valueOf(rightD), 0, 1);9 R# l8 W6 B' d5 i& O* S) a
- Delay.msDelay(100);
9 I6 p( N; Q: i; Y0 \$ I - LCD.clear();
+ w8 [" D5 U" r- ?1 C; A - }* n2 D8 d0 @9 z: G( V9 V8 f# e
- & L0 ~3 Y# @# `
- }
& z! ? ~% k+ B8 w) n" w5 I. B( W. N3 L - $ T, u, E( s+ ~, w2 D
- publicvoid go() {
. U. v v% Z* x4 d: s - //准备起步. G9 T0 _9 h. ]) c- L3 q& K6 v
- //wait for release+ p" v0 g; G; e5 e8 Q3 y% B% }9 F
- while(Button.readButtons() > 0)" t7 r. h0 _. \
- ;8 O( f4 x% c9 b) q( p5 V# j
- System.out.println("pressto go");8 A- A7 _. ~0 m: ]" {9 `
- % x) U, G( W+ r# L: ?# H( S& _
- Button.waitForAnyPress();
* p6 C. K) U+ G8 H8 X - LCD.clear();+ W# W6 ]6 w* S6 K' f5 v7 V
- G. o) [4 H1 |+ M( @
- //初始化
! i. t& i8 e3 @: W; `0 u! T2 k - pilot= new DifferentialPilot(rightD, leftD, 13.5, Motor.A, Motor.B, true);' k9 u* V. `' K* F6 V) c
- pilot.reset();# a7 k5 e" V a O7 J: J9 `+ s
- 1 D- f; K3 i7 L$ c _
- Delay.msDelay(3000);! l$ u" f+ C( q/ ]! @ ?$ b3 q
7 x# s' R$ ~& u8 n" s) _, e- doublespeed = 10;: X' n( H8 d5 S: u; {% V& ?
- doubledistance = 0;
7 Y R$ A8 D2 i# U% s/ ~ - # ]; t* y( V. p7 E! K
- //起步加速
2 s/ y9 C% C o6 @1 S) O4 L - pilot.travel(300,true);- r* i+ j( y& U
- ( v# G; j0 b' u/ g( O# s- S
- while(distance < 20) {
# {) Q5 t5 C5 ?# x U/ K - distance= pilot.getMovement().getDistanceTraveled();
3 Q# R8 H" ]: ]6 Y6 a; v - speed= distance * 5 + 10;
v! v% z1 {7 O8 } - pilot.setRotateSpeed(speed);+ C2 `( O t; y
- Delay.msDelay(100);
, M+ F2 ]$ j* c - }6 ]# t. g& N0 N% t8 g1 T
- for(int i = 0; i < 10; i++) {
. k0 t u; g9 X0 C( f) P+ j, W - speed+= 5;
2 j4 S* V" s s9 x+ M- q/ L. c - pilot.setRotateSpeed(speed); v3 s' ~* H: F d1 Y7 `
- Delay.msDelay(200);6 ~+ b6 g8 k: h8 B1 ~
- }' x6 v/ Y1 y- A1 W) S: Q
- 8 \/ `$ G1 k/ i, u& s5 T
- //TODO 减速
8 x2 D3 ^) G/ j8 G; Q9 q - % h6 p; D8 M' K3 S( c
- //停止机能7 [4 a; W G, P4 ~3 b
- while(pilot.isMoving()) {
# W5 ~ w2 }3 w8 X; y% K% Y - if(Button.readButtons() > 0). q5 K0 X/ d4 ? q* J1 l0 u
- pilot.stop();. \3 J) { W$ s+ { x9 e+ i
- }, c- G6 _; x2 x% F
6 F" A7 r# ?5 x: U6 J3 {- System.out.println("" + pilot.getMovement().getDistanceTraveled());) h& c6 v! e5 S0 ]. d
- System.out.println(-Motor.A.getTachoCount());
. o ~) q# O' p7 ^7 a - System.out.println(-Motor.B.getTachoCount());) E7 a9 o- w R5 [0 w/ {
- Button.waitForAnyPress();$ f4 O1 I1 T9 n) |; f' t
- }
% Z5 ?8 ^0 k$ g( L7 D* o
4 K8 I R% W1 K2 s7 j& i- publicstatic void main(String[] args) {& d# [) U! T$ E. P
- Straighttraveler = new Straight();$ T) b8 ~% s# Q
4 U' |$ v# v) `; b6 o6 U- traveler.adjust();
) d) g7 {+ }! k& h6 W! @7 J7 M f2 f - traveler.go();; D/ r$ K e# \
- }8 R, Q' t' C8 m, u# ?5 O
- }
复制代码
3 j$ f1 k9 l+ @ |