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  }