/* * This file is part of CBCJVM. * CBCJVM is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CBCJVM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with CBCJVM. If not, see <http://www.gnu.org/licenses/>. */ package cbccore.sensors.vision; import cbccore.Device; /** * Access to the CBC-C Camera Libraries through a cleaner API<p> * Documentation stolen from the KISS-C documentation * * @author Benjamin Woodruff * @see cbccore.low.Camera */ public class Camera { private cbccore.low.Camera lowCamera = Device.getLowCameraController(); private static int updateLocks = 0; //we want this to be global private static boolean initialized = false; public Camera() { if(!initialized) { initialized = true; init(); } update(); } /** * Initializes the camera the necessity of this function has been questioned * (although that was back on the XBC) and thus I am unsure if it is * required. But give it a try anyways. Call this first! */ private static void init() { Device.getLowCameraController().track_init(); } /** * If there is a lock, it will keep the update method from being called in * another thread (or the current thread for that matter). <u>To avoid * bad locking (program freezing up), always unlock before exiting your * function or calling update.</u><p> * If you are not using threads, <u><b>DO NOT CALL THIS FUNCTION</b></u>. If * you do not know what threading is, <u><b>DO NOT CALL THIS * FUNCTION</b></u>. It is better to not call this function than to call it * and mess it up. (although it is prefered that you use this function * correctly) This function is so very dangerous to use incorrectly that it * is hard to explain in words.<p> * ALWAYS FOLLOW THIS FUNCTION WITH <code>removeUpdateLock();</code> * */ public void addUpdateLock() { ++updateLocks; } /** * */ public void removeUpdateLock() { --updateLocks; } public boolean isLocked() { return updateLocks > 0; } /** * Determine if tracking data is available which is newer than the data processed by the last call to <code>update()</code>. * * @return True if new value is available, false otherwise */ public boolean isNewDataAvailable() { return lowCamera.track_is_new_data_available() != 0; } /** * Process tracking data for a new frame and make it available for retrieval by the other methods. * * @see #isNewDataAvailable */ public void update() { //we will syncronize this ourselves if(!isNewDataAvailable()) { return; } long startTime = System.currentTimeMillis(); while(updateLocks > 0) { if(System.currentTimeMillis() - startTime > 10000l) { System.out.println("Camera has been locked for over 10 seconds. It appears that you may have called addUpdateLock without calling removeUpdateLock."); startTime += 5000l; } Thread.yield(); } addUpdateLock(); lowCamera.track_update(); removeUpdateLock(); } /** * Use to return value is the frame number used to generate the tracking data. * * @return the frame number used to genenerate the tracking code * @see #update * @see #getCaptureTime */ public int getFrameNumber() { addUpdateLock(); int val = lowCamera.track_get_frame(); removeUpdateLock(); return val; } /** * Use to return the number of blobs available for the channel ch, which is a color channel numbered 0 through 3. * * @param ch from channel (range 0-3) * @see #init * @see #update */ public int getAvailableBlobLength(int ch) { addUpdateLock(); int val = lowCamera.track_count(ch); removeUpdateLock(); return val; } /** * Gets blob at the specified index. This is essentially the same as * making a new BlobList from this Camera and calling get on it. * * @param blob the index of the desired blob */ public Blob getBlob(int ch, int blob) { addUpdateLock(); Blob val = new Blob(this, ch, blob); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public int __getBlobSize(int ch, int i) { addUpdateLock(); int val = lowCamera.track_size(ch, i); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public int __getBlobX(int ch, int i) { addUpdateLock(); int val = lowCamera.track_x(ch, i); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public int __getBlobY(int ch, int i) { addUpdateLock(); int val = lowCamera.track_y(ch, i); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public int __getBlobConfidence(int ch, int i) { addUpdateLock(); int val = lowCamera.track_confidence(ch, i); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public int __getBlobBboxLeft(int ch, int i) { addUpdateLock(); int val = lowCamera.track_bbox_left(ch, i); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public int __getBlobBboxRight(int ch, int i) { addUpdateLock(); int val = lowCamera.track_bbox_right(ch, i); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public int __getBlobBboxTop(int ch, int i) { addUpdateLock(); int val = lowCamera.track_bbox_top(ch, i); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public int __getBlobBboxBottom(int ch, int i) { addUpdateLock(); int val = lowCamera.track_bbox_bottom(ch, i); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public int __getBlobWidth(int ch, int i) { addUpdateLock(); int val = lowCamera.track_bbox_width(ch, i); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public int __getBlobHeight(int ch, int i) { addUpdateLock(); int val = lowCamera.track_bbox_height(ch, i); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public float __getBlobAngle(int ch, int i) { addUpdateLock(); float val = lowCamera.track_angle(ch, i); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public int __getBlobMajorAxis(int ch, int i) { addUpdateLock(); int val = lowCamera.track_major_axis(ch, i); removeUpdateLock(); return val; } /** * Don't call this function. Use Blob and BlobList classes * * @see #getBlob * @see BlobList * @see Blob */ public int __getBlobMinorAxis(int ch, int i) { addUpdateLock(); int val = lowCamera.track_minor_axis(ch, i); removeUpdateLock(); return val; } /** * Gets the timestamp (in milliseconds) of the current frame * * @return The timestamp (in milliseconds) of the current frame * @see #getFrameNumber * @see #getPreviousCaptureTime */ public int getCaptureTime() { addUpdateLock(); int val = lowCamera.track_capture_time(); removeUpdateLock(); return val; } /** * Return the timestamp (in milliseconds) of the previous frame, as captured * by vision hardware. This is not necessarily the same as * <code>captureTime</code> from the prevous track_update in the case where * <code>update</code> was called less quickly than frames were captured and * thus skipped one or more frame captures. * * @return The timestamp (in milliseconds) of the current frame * @see #getFrameNumber * @see #getCaptureTime */ public int getPreviousCaptureTime() { addUpdateLock(); int val = lowCamera.track_previous_capture_time(); removeUpdateLock(); return val; } }