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