gobot.io/x/gobot@v1.16.0/examples/bebop_ps3_video.go (about) 1 // +build example 2 // 3 // Do not build by default. 4 5 /* 6 This example will connect to the Parrot Bebop allowing you to control 7 it using a PS3 controller. 8 9 It also streams the drone video to a webpage via ffserver. 10 11 This requires you to have both ffmpeg and ffserver installed 12 on your computer. 13 14 In order to run this example you will first need to start ffserver with: 15 $ ffserver -f ff.conf 16 17 then in a separate terminal run this program: 18 $ go run bebop_ps3_video.go 19 20 You can view the video feed by navigating to 21 http://localhost:8090/bebop.mjpeg in a web browser. 22 *NOTE* firefox works best for viewing the video feed. 23 */ 24 package main 25 26 import ( 27 "fmt" 28 "io" 29 "io/ioutil" 30 "os/exec" 31 "sync/atomic" 32 "time" 33 34 "gobot.io/x/gobot" 35 "gobot.io/x/gobot/platforms/joystick" 36 "gobot.io/x/gobot/platforms/parrot/bebop" 37 ) 38 39 type pair struct { 40 x float64 41 y float64 42 } 43 44 var leftX, leftY, rightX, rightY atomic.Value 45 46 const offset = 32767.0 47 48 func ffmpeg() (stdin io.WriteCloser, stderr io.ReadCloser, err error) { 49 ffmpeg := exec.Command("ffmpeg", "-i", "pipe:0", "http://localhost:8090/bebop.ffm") 50 51 stderr, err = ffmpeg.StderrPipe() 52 53 if err != nil { 54 return 55 } 56 57 stdin, err = ffmpeg.StdinPipe() 58 59 if err != nil { 60 return 61 } 62 63 if err = ffmpeg.Start(); err != nil { 64 return 65 } 66 67 go func() { 68 for { 69 buf, err := ioutil.ReadAll(stderr) 70 if err != nil { 71 fmt.Println(err) 72 } 73 if len(buf) > 0 { 74 fmt.Println(string(buf)) 75 } 76 } 77 }() 78 79 return stdin, stderr, nil 80 } 81 82 func main() { 83 joystickAdaptor := joystick.NewAdaptor() 84 stick := joystick.NewDriver(joystickAdaptor, "dualshock3") 85 86 bebopAdaptor := bebop.NewAdaptor() 87 drone := bebop.NewDriver(bebopAdaptor) 88 89 work := func() { 90 drone.VideoEnable(true) 91 video, _, _ := ffmpeg() 92 93 go func() { 94 for { 95 if _, err := video.Write(<-drone.Video()); err != nil { 96 fmt.Println(err) 97 return 98 } 99 } 100 }() 101 102 leftX.Store(float64(0.0)) 103 leftY.Store(float64(0.0)) 104 rightX.Store(float64(0.0)) 105 rightY.Store(float64(0.0)) 106 107 recording := false 108 109 stick.On(joystick.CirclePress, func(data interface{}) { 110 if recording { 111 drone.StopRecording() 112 } else { 113 drone.StartRecording() 114 } 115 recording = !recording 116 }) 117 118 stick.On(joystick.SquarePress, func(data interface{}) { 119 drone.HullProtection(true) 120 drone.TakeOff() 121 }) 122 stick.On(joystick.TrianglePress, func(data interface{}) { 123 drone.Stop() 124 }) 125 stick.On(joystick.XPress, func(data interface{}) { 126 drone.Land() 127 }) 128 stick.On(joystick.LeftX, func(data interface{}) { 129 val := float64(data.(int16)) 130 leftX.Store(val) 131 }) 132 133 stick.On(joystick.LeftY, func(data interface{}) { 134 val := float64(data.(int16)) 135 leftY.Store(val) 136 }) 137 138 stick.On(joystick.RightX, func(data interface{}) { 139 val := float64(data.(int16)) 140 rightX.Store(val) 141 }) 142 143 stick.On(joystick.RightY, func(data interface{}) { 144 val := float64(data.(int16)) 145 rightY.Store(val) 146 }) 147 148 gobot.Every(10*time.Millisecond, func() { 149 leftStick := getLeftStick() 150 151 switch { 152 case leftStick.y < -10: 153 drone.Forward(bebop.ValidatePitch(leftStick.y, offset)) 154 case leftStick.y > 10: 155 drone.Backward(bebop.ValidatePitch(leftStick.y, offset)) 156 default: 157 drone.Forward(0) 158 } 159 160 switch { 161 case leftStick.x > 10: 162 drone.Right(bebop.ValidatePitch(leftStick.x, offset)) 163 case leftStick.x < -10: 164 drone.Left(bebop.ValidatePitch(leftStick.x, offset)) 165 default: 166 drone.Right(0) 167 } 168 }) 169 170 gobot.Every(10*time.Millisecond, func() { 171 rightStick := getRightStick() 172 switch { 173 case rightStick.y < -10: 174 drone.Up(bebop.ValidatePitch(rightStick.y, offset)) 175 case rightStick.y > 10: 176 drone.Down(bebop.ValidatePitch(rightStick.y, offset)) 177 default: 178 drone.Up(0) 179 } 180 181 switch { 182 case rightStick.x > 20: 183 drone.Clockwise(bebop.ValidatePitch(rightStick.x, offset)) 184 case rightStick.x < -20: 185 drone.CounterClockwise(bebop.ValidatePitch(rightStick.x, offset)) 186 default: 187 drone.Clockwise(0) 188 } 189 }) 190 } 191 192 robot := gobot.NewRobot("bebop", 193 []gobot.Connection{joystickAdaptor, bebopAdaptor}, 194 []gobot.Device{stick, drone}, 195 work, 196 ) 197 198 robot.Start() 199 } 200 201 func getLeftStick() pair { 202 s := pair{x: 0, y: 0} 203 s.x = leftX.Load().(float64) 204 s.y = leftY.Load().(float64) 205 return s 206 } 207 208 func getRightStick() pair { 209 s := pair{x: 0, y: 0} 210 s.x = rightX.Load().(float64) 211 s.y = rightY.Load().(float64) 212 return s 213 }