mem 380/800: autonomous vehicle control ihgk22/courses/mem380_800... · mem 380/800: autonomous...
TRANSCRIPT
MEM 380/800: Autonomous Vehicle Control I Project Summary – December 4, 2008
Jason Collins, Ted Bieniosek, Jessica Snyder
Abstract An all‐terrain radio operated vehicle was modified both mechanically and electronically in order to perform the required task: travel autonomously through an unknown environment until an obstacle is encountered, then stop. To permit autonomous control, the vehicle’s radio link was disabled, a microcontroller was installed, and the vehicle’s steering servos and speed controller were placed under the microcontroller’s command. The microcontroller was programmed by an external microcomputer and permitted to communicate with the microcomputer via wireless Bluetooth® connection to allow for microcontroller program start and termination. The programming and electrical and mechanical modifications resulted in successful completion of the assigned task as well as early success in the secondary task of incorporating computer vision as a means of navigation.
Vehicle The team was supplied with an E‐Maxx (Traxxas, Model 3906) electric all‐terrain truck. The stock truck includes the following features:
• Four‐wheel drive • Two Titan 550 brushless, fan cooled motors • EVX‐2 speed controller(forward/reverse/brake) • Two 7.2 V rechargeable batteries • Dual servo steering system • Drive gear ratio: 18.67 : 1; Top speed: 30 M.P.H. • Overall length: 518 mm; Overall width: 417 mm • Wheelbase: 335 mm; Overall height: 248 mm
Mechanical Modifications To make the truck less of a high‐speed racing machine and more stable, predictable and controllable, the following mechanical modifications were completed:
• Stock (red) springs were replaced with higher stiffness (orange) springs. This modification stabilized the chassis and body, permitting more stable sensor range measurements during acceleration.
• Drive gear was replaced; gear ratio increased. Lowering the gear ratio had the effect of lowering the truck’s top speed, decreasing the stopping distance, and providing smoother acceleration
• Body was raised to maximum level. The higher vantage point solved the problem of the range sensors detecting erroneous distance values (registering the floor).
Microcontroller and Electronics In addition to the vehicle and aftermarket replacement parts, the team was supplied with the following electronic devices:
• Propeller Starter Kit (Parallax, Model 32300) o Propeller microcontroller unit (Parallax,
Model P8X32A‐Q44) • Bluetooth® transceiver (Embedded Blue, Model
500‐SER) • Servo controller (Parallax, Model 28823) • Servo (Hitec, Model HS‐5645MG) • “PING)))” Ultrasonic sensor (Parallax, Model
28015) (5 units) • CMUcam2+ Vision sensor • Spare 7.2 V rechargeable battery (2 units) • 7.2 V battery charger • 4 × “AA” battery holder (2 units) • “AA” size batteries • Various lengths of wire
Electronic Modifications To allow the truck to be placed under the autonomous control of a program in operation on the Propeller microcontroller, the following modifications were made to the vehicle:
• The stock radio receiver was disconnected and removed. The ability of the truck to receive signals from the stock radio control unit served no purpose in this project.
• Four of the “PING” sensors were mounted on the plastic body of the truck; three forward
facing and one rear facing. The sensors were wired directly to the Propeller prototype board.
• The servo controller was wired to one PS/2 connector on the prototype board.
• The speed controller input and steering servos were wired to the servo controller output channels.
• The Bluetooth® transceiver was wired to the second PS/2 connector on the prototype board.
• The CMUcam2+ was mounted on the spare servo and output color tracking data to the Propeller microcontroller.
• The fifth “PING” sensor was mounted alongside the camera and wired to the Propeller board.
• An additional 7.2 V battery was mounted on the chassis to provide power for the CMUcam2+ and Propeller chip. A 4 × “AA” battery holder was added to supply power to the servo controller.
Programming Strategy To accomplish the goal of moving, identifying an obstacle, and halting in its proximity, simple heuristics were programmed on the Propeller chip to allow for autonomous control:
• Check the range sensors. • If all sensors indicate a clear path, drive ahead. • If a forward sensor indicates something at close
range, halt.
Successful implementation of these three steps was sufficient to complete the first task. In search of a better challenge, the team decided to explore the possibility of avoiding obstacles rather than simply stopping in front of them. The heuristics change to the following:
• Check the range sensors. • If all sensors indicate a clear path, drive ahead. • If the center forward sensor shows something
ahead, slow proportional to distance indicated. • If the right (left) front sensor shows something
in that direction, steer the opposite direction proportional to the range to that object.
• If the center forward sensor shows something very close, stop and turn around.
• Repeat indefinitely.
Lastly, the team explored the CMUcam2+ and potential implementation strategies. The CMUcam2+ has an on
board image microprocessor, capable of tracking color and other objects in multiple modes. The team was able to program the CMUcam2+ to track colored objects in its most basic mode. The heuristics are again updated, becoming still more complicated:
• Check the camera. • If the camera does not see the desired color,
rotate servo until color is found. • Check the range sensors. • If all sensors indicate a clear path, drive ahead. • If none of the rules below are broken, steer
towards the direction that the camera is facing. • If the center forward sensor shows something
ahead, slow proportional to distance indicated. • If the right (left) front sensor shows something
in that direction, steer the opposite direction proportional to the range to that object.
• If the center forward sensor shows something very close, stop and turn around.
• If the range sensor mounted on the camera indicates something very close, and the camera confirms the color, halt.
Conclusion At the conclusion of the ten week quarter, the team’s truck was able to complete a demonstration of the initial objective, as well as operate in more sophisticated modes of travel. With the implementation of the CMUcam2+, a variety of challenges can be completed and algorithms explored. In upcoming academic quarters, this team hopes to implement a better method of searching for colored objects rather than moving and looking randomly throughout the environment. Perhaps some methods of path planning and following can be explored. The success of the team can be largely attributed to an organized team effort, focus and time management during class time, setting and meeting small daily goals, and prior experience.
Appendix A: Spin Code Listing{{Truck.spin}} {{ 11-25-08 Control E-MAXX truck equiped with 5 Ping))) sensors and a CMUcam2+ }} Con _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 Th_Channel = 12 'servo control settings St_Channel = 7 Cam_Channel = 1 Rate = 1 MaxDist = 100 'ping range settings NeutralDist = 40 MinDist = 1 MaxForward = 135 'speed controller settings MinForward = 131 Neutral = 125 MinReverse = 122 MaxReverse = 115 ExtLeft = 190 'steering settings ExtRight = 40 MaxSteer = 50 Center = (ExtLeft + ExtRight) / 2 SensLim = 100 SteeringProportionalGain = 1 ConfidenceThreshold = 75 OBJ Servo : "PWM" Serial_PC : "FullDuplexSerial" Serial_CAM : "FullDuplexSerial" Num : "Numbers" Distance : "Ping" VAR Byte Throttle 'display values Byte Steering Byte Cam_angle Word D0 Word D1 Word D2 Word D3 Word D4 Byte mx 'camera values Byte my Byte x1 Byte y1 Byte x2 Byte y2 Byte pixels Byte confidence Byte r1 Byte r2 Byte TargetAquired Byte CrMean Byte YMean Byte CbMean Byte CrDeviation Byte YDeviation Byte CbDeviation PUB Main BTSetup 'setup bluetooth connection CAM_init 'setup camera Throttle := Neutral Steering := 115 Cam_Angle := 125 r1 := 0 r2 := 0 repeat 'main loop UserIn UserOut if Cam_Angle > 230 CAM_Angle := 230 elseif Cam_Angle < 35 CAM_Angle := 35
Servo.Send(Th_Channel, Rate, Throttle) Servo.Send(St_Channel, Rate, Steering) Servo.Send(Cam_Channel, Rate, Cam_Angle) PUB Track | center2 CAM_Get if Confidence > ConfidenceThreshold TargetAquired := 1 if my < center2 'center2 has no initial value... is it required at all? Cam_Angle := Cam_Angle + (75-my)/3 elseif my > center2 Cam_Angle := Cam_Angle - (my-75)/3 else TargetAquired := 0 Cam_Angle := Cam_Angle + 50 PUB UserOut serial_PC.tx(13) if Throttle serial_PC.str(string("Throttle:")) serial_PC.str(Num.ToStr(Throttle, Num#DDEC)) if Steering serial_PC.str(string(" Steering:")) serial_PC.str(Num.ToStr(Steering, Num#DDEC)) if Cam_angle serial_PC.str(string(" CAM:")) serial_PC.str(Num.ToStr(Cam_angle, Num#DDEC)) if D0 serial_PC.str(string(" D0:")) serial_PC.str(Num.ToStr(D0, Num#DDEC)) if D1 serial_PC.str(string(" D1:")) serial_PC.str(Num.ToStr(D1, Num#DDEC)) if D2 serial_PC.str(string(" D2:")) serial_PC.str(Num.ToStr(D2, Num#DDEC)) if D3 serial_PC.str(string(" D3:")) serial_PC.str(Num.ToStr(D3, Num#DDEC)) if D4 serial_PC.str(string(" D4:")) serial_PC.str(Num.ToStr(D4, Num#DDEC)) serial_PC.tx(13) PUB UserIn | input input := serial_PC.rx Sample if input == "w" 'forward Throttle := Throttle + 3 elseif input == "s" 'reverse Throttle := Throttle - 3 elseif input == "a" 'turn wheels left Steering := Steering + 10 elseif input == "d" 'turn wheels right Steering := Steering - 10 elseif input == "q" 'turn camera left Cam_angle := Cam_angle - 5 elseif input == "e" 'turn camera right Cam_angle := Cam_angle + 5 elseif input == "t" 'run the tracking code Track elseif input == "i" 'get tracking sample CAM_Set elseif input == "u" 'PC-CAM serial pass thru mode PCtoCAM elseif input == " " 'all stop Throttle := Neutral Steering := 115 Cam_angle := 125 elseif input == "c" 'start both controllers serial_PC.rxflush repeat if serial_PC.rxcheck <> -1 quit ThrottleController SteeringController UserOut 'temp added for loop Servo.Send(Th_Channel, Rate, Throttle) Servo.Send(St_Channel, Rate, Steering) Servo.Send(Cam_Channel, Rate, Cam_Angle) sample
if D4 < 5 quit throttle := Neutral Steering := 115 Cam_angle := 125 elseif input == "x" 'start the Throttle controller ThrottleController elseif input == "f" 'start the Steering controller SteeringController else serial_PC.tx(13) serial_PC.str(string("unknown")) PUB ThrottleController if D1 > MaxDist 'D1 = the forward ping sensor Throttle := MaxForward Serial_PC.str(string("Max")) elseif D1 > NeutralDist Throttle := MinForward + (D1 - NeutralDist) * (MaxForward - MinForward)/ (MaxDist - NeutralDist) Serial_PC.str(string("Forward")) elseif D3 > NeutralDist Throttle := MinReverse - (NeutralDist - D1) * (MinReverse - MaxReverse)/ (NeutralDist - MinDist) Serial_PC.str(string("Reverse")) if r1 == D1 if r2 == D1 Throttle := Neutral Servo.Send(Th_Channel, Rate, Throttle) r1 := 0 r2 := 0 waitcnt(clkfreq/10 + cnt) return else r2 := D1 else r1 := D1 else Throttle := Neutral Serial_PC.str(string("Stop")) PUB SteeringController track 'limit sensor readings to SensLim constant if D0 > SensLim D0 := SensLim if D2 > SensLim D2 := SensLim serial_PC.str(Num.ToStr((D2 - D0), Num#DDEC)) if Throttle > 124 if D0 + D2 == SensLim * 2 'sensors see nothing in range steering := 250 - Cam_Angle if TargetAquired == 0 Steering := Center 'add drive search here if desired elseif(D2>D0+5) 'object on ritght Steering := Center-(D2^2-D0^2)^0.5*SteeringProportionalGain elseif(D0>D2+5) 'object of left Steering := Center-(D2^2-D0^2)^0.5*SteeringProportionalGain else 'objects at aproximately equal distances Steering := Center if(Steering > ExtLeft) Steering := ExtLeft 'serial_PC.str(Num.ToStr(Steering, Num#DDEC)) if(Steering < ExtRight) Steering := ExtRight 'serial_PC.str(Num.ToStr(Steering, Num#DDEC)) else if(D2>D0+5) Steering := Center+(D2^2-D0^2)^0.5*SteeringProportionalGain if(Steering > ExtLeft) Steering := ExtLeft 'serial_PC.str(Num.ToStr(Steering, Num#DDEC)) elseif(D0>D2+5) Steering := Center+(D2^2-D0^2)^0.5*SteeringProportionalGain if(Steering < ExtRight) Steering := ExtRight
'serial_PC.str(Num.ToStr(Steering, Num#DDEC)) else Steering := Center + 30 PUB Sample D0 := Distance.Centimeters(0) 'only enable pins with a ping attached or code will hang waitcnt(clkfreq/1000 + cnt) D1 := Distance.Centimeters(1) waitcnt(clkfreq/1000 + cnt) D2 := Distance.Centimeters(2) waitcnt(clkfreq/1000 + cnt) D3 := Distance.Centimeters(3) waitcnt(clkfreq/1000 + cnt) D4 := Distance.Centimeters(4) waitcnt(clkfreq/1000 + cnt) PUB BTSetup Serial_PC.start(24, 25, 0, 9600) 'if bluetooth card is in 9600 mode change it to 115200 Serial_PC.str(string("set baud 115200 *", 13)) waitcnt(clkfreq/10 + cnt) Serial_PC.start(24, 25, 0, 115200) 'talk to bt card at 115200 serial_PC.str(string("con 00:22:69:D0:72:70", 13)) 'start bt connection with class dell laptop waitcnt(clkfreq/10 + cnt) PUB PCtoCAM | ToCAM, ToPC Serial_CAM.tx(13) Serial_PC.tx(13) 'Serial_PC.str(":") repeat 'relay from PC to CAM ToCAM := Serial_PC.rx Serial_CAM.tx(ToCAM) while ToCAM <> 13 'not equal repeat 'relay from CAM to PC ToPC := Serial_CAM.rx Serial_PC.tx(ToPC) while ToPC <> ":" 'not equal PUB CAM_init Serial_CAM.start(5, 6, 0, 115200) 'set camera serial settings waitcnt(clkfreq/10 + cnt) Serial_CAM.tx(13) 'new line waitcnt(clkfreq/10 + cnt) Serial_CAM.str(string("rs", 13)) 'reset waitcnt(clkfreq/10 + cnt) Serial_CAM.str(string("cr 18 36 19 33", 13)) 'set camera register: white balance on, auto gain on waitcnt(clkfreq/10 + cnt) Serial_CAM.str(string("pm 1", 13)) 'enable ping mode waitcnt(clkfreq/10 + cnt) Serial_CAM.str(string("tw", 13)) 'sample and set auto threshold waitcnt(clkfreq/10 + cnt) Serial_CAM.str(string("l1 1", 13)) 'LED waitcnt(clkfreq/10 + cnt) Serial_CAM.str(string("rm 1", 13)) 'set output to raw mode (butes instead of strings) waitcnt(clkfreq/10 + cnt) PUB CAM_Set Serial_CAM.str(string("cr 18 32 19 32", 13)) 'set camera register: white balance off, auto gain off waitcnt(clkfreq/10 + cnt) Serial_CAM.str(string("VW 35 65 45 75", 13)) 'set virtual window to central portion of screen waitcnt(clkfreq/10 + cnt) Serial_CAM.rxflush Serial_CAM.str(string("GM", 13)) 'get average color 'repeat 'Serial_PC.tx(Serial_CAM.rx) 'read values returned CrMean := Serial_CAM.rx YMean := Serial_CAM.rx CbMean := Serial_CAM.rx CrDeviation := Serial_CAM.rx YDeviation := Serial_CAM.rx CbDeviation := Serial_CAM.rx Serial_PC.str(Num.ToStr(CrMean, Num#DDEC)) 'use .dec insetead of .str(num... Serial_PC.str(Num.ToStr(YMean, Num#DDEC)) Serial_PC.str(Num.ToStr(CbMean, Num#DDEC)) Serial_PC.str(Num.ToStr(CrDeviation, Num#DDEC)) Serial_PC.str(Num.ToStr(YDeviation, Num#DDEC)) 'contirnue changing after test Serial_PC.str(Num.ToStr(CbDeviation, Num#DDEC)) Serial_CAM.str(string("VW", 13)) 'set virtual window to full size waitcnt(clkfreq/10 + cnt) Serial_CAM.str(string("ST ")) 'send tracking parameters Serial_CAM.dec(CrMean - 2 * CrDeviation) Serial_CAM.str(string(" ")) Serial_CAM.dec(CrMean + 2 * CrDeviation) Serial_CAM.str(string(" "))
Serial_CAM.dec(YMean - 5 * YDeviation) Serial_CAM.str(string(" ")) Serial_CAM.dec(YMean + 5 * YDeviation) Serial_CAM.str(string(" ")) Serial_CAM.dec(CbMean - 2 * CbDeviation) Serial_CAM.str(string(" ")) Serial_CAM.dec(CbMean + 2 * CbDeviation) Serial_CAM.tx(13) waitcnt(clkfreq/10 + cnt) PUB CAM_Get Serial_CAM.rxflush Serial_CAM.str(string("tc", 13)) repeat 6 Serial_PC.tx(Serial_CAM.rx) 'use rxtime(ms) later mx := Serial_CAM.rx my := Serial_CAM.rx x1 := Serial_CAM.rx y1 := Serial_CAM.rx x2 := Serial_CAM.rx y2 := Serial_CAM.rx pixels := Serial_CAM.rx confidence := Serial_CAM.rx Serial_PC.str(Num.ToStr(mx, Num#DDEC)) 'use .dec insetead of .str(num... Serial_PC.str(Num.ToStr(my, Num#DDEC)) Serial_PC.str(Num.ToStr(x1, Num#DDEC)) Serial_PC.str(Num.ToStr(y1, Num#DDEC)) Serial_PC.str(Num.ToStr(x2, Num#DDEC)) Serial_PC.str(Num.ToStr(y2, Num#DDEC)) Serial_PC.str(Num.ToStr(pixels, Num#DDEC)) Serial_PC.str(Num.ToStr(confidence, Num#DDEC)) Serial_PC.str(string(13, ":")) waitcnt(clkfreq/100 + cnt)
Appendix B: Vehicle Photos
Appendix C: Daily Log