1 /*
  2  * Interface to the Finch control methods
  3  * 
  4  * Copyright (c) 2011 Derrell Lipman
  5  * 
  6  * License:
  7  *   LGPL: http://www.gnu.org/licenses/lgpl.html 
  8  *   EPL: http://www.eclipse.org/org/documents/epl-v10.php
  9  */
 10     /**
 11      * Get and save a new finch object, or return the existing one.
 12      */
 13     _getFinch : function()
 14     {
 15       // Get a reference to our Finch
 16       var finch = this.__finch;
 17 
 18       // Disconnect from the finch
 19       if (finch != null)
 20       {
 21           return finch;
 22       }
 23 
 24       // Reconnect with a new Finch object
 25       try
 26       {
 27         // Obtain a finch object
 28         this.__finch =
 29           new Packages.edu.cmu.ri.createlab.terk.robot.finch.Finch();
 30 
 31         // Indicate success 
 32         return this.__finch;
 33       }
 34       catch (e)
 35       {
 36         // Some unknown error. Wrap its text in our own error
 37         throw new JsonRpcError(this.constructor.Error_Finch,
 38                                "Finch: " + e.toString(), e);
 39       }
 40     },
 41 
 42     /**
 43      * Reset the Finch by disconnecting. The next request will reconnect.
 44      * 
 45      * @return 0, always.
 46      */
 47     reset : function()
 48     {
 49       // If we're connected to the finch...
 50       if (this.__finch != null)
 51       {
 52         // ... then disconnect from it, ...
 53         this.__finch.quit();
 54 
 55         // ... and note that we're no longer connected.
 56         this.__finch = null;
 57       }
 58 
 59       // Indicate success
 60       return 0;
 61     },
 62 
 63     /**
 64      * Play a tone at a specified frequency for a specified duration, on the
 65      * Finch's internal buzzer.
 66      *
 67      * Note that this is non-blocking, so a subsequent call before an initial
 68      * call has completed the specified duration will stop the initial tone and
 69      * begin the newly-requested one.
 70      *
 71      * @param frequency
 72      *   The frequency, in Hertz, of the tone to play. Middle C is about
 73      *   262Hz. See http://www.phy.mtu.edu/~suits/notefreqs.html for
 74      *   frequencies of musical notes.
 75      *
 76      * @param duration
 77      *   The duration, in milliseconds, for which the tone should play.
 78      *
 79      * @return
 80      *   0, always
 81      *   
 82      * @throws JsonRpcError
 83      */
 84     playTone : function(frequency, duration)
 85     {
 86       // Make him buzz
 87       this._getFinch().buzz(parseInt(frequency, 10), parseInt(duration, 10));
 88 
 89       // Indicate success
 90       return 0;
 91     },
 92 
 93     /**
 94      * Obtain the current accelerometer values. Acceleration values will be in
 95      * the range [-1.5, +1.5]. When the Finch is level, the x and y values
 96      * should show close to 0.0, and the z value close to +1.0
 97      * 
 98      * @return A map containing the x, y, and z accelerometer values.
 99      * @throws JsonRpcError
100      */
101     getAccelerations : function()
102     {
103       // Get the current acceleration values
104       var accelerations = this._getFinch().getAccelerations();
105 
106       // Convert them to object format
107       return(
108         {
109           x : accelerations[0],
110           y : accelerations[1],
111           z : accelerations[2]
112         });
113     },
114 
115     /**
116      * Get the current light sensor values. Values are in the range [0, 255]
117      * with higher values indicating more light being detected.
118      * 
119      * @return A map containing the "left" and "right" light sensor values
120      * @throws JsonRpcError
121      */
122     getLightSensors : function()
123     {
124       // Get the current light sensor values
125       var sensors = this._getFinch().getLightSensors();
126 
127       // Convert them to object format
128       return(
129         {
130           left  : sensors[0],
131           right : sensors[1]
132         });
133     },
134 
135     /**
136      * Get the current obstacle sensor values. Values are boolean, with true
137      * indicating that an obstacle is detected.
138      * 
139      * @return A map containing the left and right sensor values
140      * @throws JsonRpcError
141      */
142     getObstacleSensors : function()
143     {
144       // Get the current obstacle sensor values
145       var sensors = this._getFinch().getObstacleSensors();
146 
147       // Convert them to object format
148       return(
149         {
150           left  : sensors[0],
151           right : sensors[1]
152         });
153     },
154 
155     /**
156      * Get the current temperature sensor value. The value is measured in
157      * degrees Celsius.
158      * 
159      * @return The temperature sensor value.
160      * @throws JsonRpcError
161      */
162     getTemperature : function()
163     {
164       // Get and return the current temperature sensor value
165       return this._getFinch().getTemperature();
166     },
167 
168     /**
169      * Get the values of all sensors.
170      * 
171      * See the individual sensor methods for details of values.
172      * 
173      * @return A map containing an "accelerometer" map, a "light" map, an
174      *         "obstacle" map, and a "temperature" value.
175      * @throws JsonRpcError
176      */
177     getAllSensors : function()
178     {
179       var             ret = {};
180 
181       // Get a reference to our Finch
182       var finch = this._getFinch();
183 
184       // Get the current acceleration values
185       var accelerations = finch.getAccelerations();
186 
187       // Add the accelerometer values to the temp object, and add the temp
188       // object to the return object
189       ret.accelerometer =
190         {
191           x : accelerations[0],
192           y : accelerations[1],
193           z : accelerations[2]
194         };
195 
196       // Get the current light sensor values
197       var lightSensors = finch.getLightSensors();
198 
199       // Add the light sensor values to the temp object, and add the temp
200       // object to the return object
201       ret.light =
202         {
203           left  : lightSensors[0],
204           right : lightSensors[1]
205         };
206 
207       // Get the current obstacle sensor values
208       var obstacleSensors = finch.getObstacleSensors();
209 
210       // Add the obstacle sensor values to the temp object, and add the temp
211       // object to the return object
212       ret.obstacle =
213         {
214           left  : obstacleSensors[0],
215           right : obstacleSensors[1]
216         };
217 
218       // Get the temperature sensor value and add it to the return object
219       ret.temperature = finch.getTemperature();
220 
221       // Give 'em the whole kit and kaboodle!
222       return ret;
223     },
224 
225     /**
226      * Set Finch's beak LED to a specified color. If any color value is out of
227      * range, it is set to the closest extreme value of the legal range.
228      * 
229      * @param r
230      *        The intensity of red, in the range [0, 255]
231      * 
232      * @param g
233      *        The intensity of green, in the range [0, 255]
234      * 
235      * @param b
236      *        The intensity of blue, in the range [0, 255]
237      * 
238      * @return 0, always
239      * @throws JsonRpcError
240      */
241     setLED : function(r, g, b)
242     {
243       // Ensure that all intensity values are within range
244       // First red...
245       if (r < 0)
246       {
247           r = 0;
248       }
249       else if (r > 255)
250       {
251           r = 255;
252       }
253 
254       // then green...
255       if (g < 0)
256       {
257           g = 0;
258       }
259       else if (g > 255)
260       {
261           g = 255;
262       }
263 
264       // and finally blue.
265       if (b < 0)
266       {
267           b = 0;
268       }
269       else if (b > 255)
270       {
271           b = 255;
272       }
273 
274       // Set the LED intensity
275       this._getFinch().setLED(r, g, b);
276 
277       // Indicate success
278       return 0;
279     },
280 
281     /**
282      * Set the power level for each wheel. Power levels range from [-255, 255]
283      * with negative values reversing the direction the wheel turns.
284      * 
285      * @param leftPower
286      *        Power level to apply to the left wheel
287      * 
288      * @param rightPower
289      *        Power level to apply to the right wheel
290      * 
291      * @return 0, always
292      * @throws JsonRpcError
293      */
294     setWheelPower : function(leftWheelPower, rightWheelPower)
295     {
296       var     leftPower = leftWheelPower;
297       var     rightPower = rightWheelPower;
298 
299       // If either value is out of range, map it to the closest extreme legal
300       // value. First the left wheel power...
301       if (leftPower < -255)
302       {
303           leftPower = -255;
304       }
305       else if (leftPower > 255)
306       {
307           leftPower = 255;
308       }
309 
310       // ... and now the right wheel power.
311       if (rightPower < -255)
312       {
313           rightPower = -255;
314       }
315       else if (rightPower > 255)
316       {
317           rightPower = 255;
318       }
319 
320       // The Finch API calls this "wheel velocity" but is implemented as wheel
321       // power. We may try to implement a velocity function based on power
322       // duty cycle, at some point.
323       this._getFinch().setWheelVelocities(leftPower, rightPower);
324 
325       // Indicate success
326       return 0;
327     }
328 
329