|
From: <jl...@us...> - 2008-04-16 21:16:12
|
Revision: 105
http://personalrobots.svn.sourceforge.net/personalrobots/?rev=105&view=rev
Author: jleibs
Date: 2008-04-16 14:16:16 -0700 (Wed, 16 Apr 2008)
Log Message:
-----------
Actual node to configure and spew out elphel jpeg images.
Modified Paths:
--------------
pkg/trunk/elphel_cam/build.yaml
pkg/trunk/elphel_cam/manifest.xml
pkg/trunk/elphel_cam/src/libelphel_cam/elphel_cam.cpp
pkg/trunk/elphel_cam/test/test_cam/test_cam.cpp
Added Paths:
-----------
pkg/trunk/elphel_cam/nodes/test_elphel_cam
pkg/trunk/elphel_cam/src/elphel_cam/
pkg/trunk/elphel_cam/src/elphel_cam/Makefile
pkg/trunk/elphel_cam/src/elphel_cam/elphel_cam.cpp
Modified: pkg/trunk/elphel_cam/build.yaml
===================================================================
--- pkg/trunk/elphel_cam/build.yaml 2008-04-16 01:35:21 UTC (rev 104)
+++ pkg/trunk/elphel_cam/build.yaml 2008-04-16 21:16:16 UTC (rev 105)
@@ -1,4 +1,5 @@
cpp:
make:
- src/libelphel_cam
+ - src/elphel_cam
- test/test_cam
Modified: pkg/trunk/elphel_cam/manifest.xml
===================================================================
--- pkg/trunk/elphel_cam/manifest.xml 2008-04-16 01:35:21 UTC (rev 104)
+++ pkg/trunk/elphel_cam/manifest.xml 2008-04-16 21:16:16 UTC (rev 105)
@@ -8,6 +8,6 @@
<url>http://pr.willowgarage.com</url>
<depend package="common_flows"/>
<depend package="thread_utils"/>
-<depend package="image_viewer"/>
+<depend package="simple_sdl_gui"/>
</package>
Added: pkg/trunk/elphel_cam/nodes/test_elphel_cam
===================================================================
--- pkg/trunk/elphel_cam/nodes/test_elphel_cam (rev 0)
+++ pkg/trunk/elphel_cam/nodes/test_elphel_cam 2008-04-16 21:16:16 UTC (rev 105)
@@ -0,0 +1,13 @@
+#!/usr/bin/env ruby
+require "#{`#{ENV['ROS_ROOT']}/rospack latest yamlgraph`}/lib/yamlgraph/ygl.rb"
+g = YAMLGraph.new
+g.param 'elphel_cam.host', '192.168.0.9'
+g.param 'elphel_cam.fps', '80'
+g.param 'elphel_cam.im_dec', '4'
+g.node 'elphel_cam/elphel_cam', {'launch'=>'xterm'}
+g.node 'simple_sdl_gui/gui', {'launch'=>'xterm'}
+#g.node 'vacuum/vacuum', {'launch' => 'valgrind'}
+g.flow 'elphel_cam:image', 'gui:image'
+#g.flow 'elphel_cam:image', 'vacuum:hose'
+YAMLGraphLauncher.new.launch g
+
Property changes on: pkg/trunk/elphel_cam/nodes/test_elphel_cam
___________________________________________________________________
Name: svn:executable
+ *
Added: pkg/trunk/elphel_cam/src/elphel_cam/Makefile
===================================================================
--- pkg/trunk/elphel_cam/src/elphel_cam/Makefile (rev 0)
+++ pkg/trunk/elphel_cam/src/elphel_cam/Makefile 2008-04-16 21:16:16 UTC (rev 105)
@@ -0,0 +1,4 @@
+SRC = elphel_cam.cpp
+OUT = ../../nodes/elphel_cam
+PKG = elphel_cam
+include $(shell $(ROS_ROOT)/rospack find roscpp)/make_include/node.mk
Added: pkg/trunk/elphel_cam/src/elphel_cam/elphel_cam.cpp
===================================================================
--- pkg/trunk/elphel_cam/src/elphel_cam/elphel_cam.cpp (rev 0)
+++ pkg/trunk/elphel_cam/src/elphel_cam/elphel_cam.cpp 2008-04-16 21:16:16 UTC (rev 105)
@@ -0,0 +1,134 @@
+///////////////////////////////////////////////////////////////////////////////
+// The axis_cam package provides a library that talks to Axis IP-based cameras
+// as well as ROS nodes which use these libraries
+//
+// Copyright (C) 2008, Morgan Quigley
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of Stanford University nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+#include "ros/ros_slave.h"
+#include "common_flows/FlowImage.h"
+#include "common_flows/ImageCodec.h"
+#include "elphel_cam/elphel_cam.h"
+
+class Elphel_Cam_Node : public ROS_Slave
+{
+public:
+ FlowImage *image;
+ ImageCodec<FlowImage> *codec;
+ string elphel_host;
+ Elphel_Cam *cam;
+ int frame_id;
+ double fps;
+ int im_dec;
+
+ Elphel_Cam_Node() : ROS_Slave(), cam(NULL), frame_id(0)
+ {
+ register_source(image = new FlowImage("image"));
+ codec = new ImageCodec<FlowImage>(image);
+
+ register_with_master();
+ if (!get_string_param(".host", elphel_host))
+ elphel_host = "192.168.0.9";
+ printf("elphel_cam host set to [%s]\n", elphel_host.c_str());
+
+ if (!get_int_param(".frame_id", &frame_id))
+ frame_id = -1;
+ printf("elphel_cam frame_id set to [%d]\n", frame_id);
+
+ if (!get_double_param(".fps", &fps))
+ fps = 20;
+ printf("elphel_cam fps set to [%d]\n", fps);
+
+ if (!get_int_param(".im_dec", &im_dec))
+ im_dec = 4;
+ printf("elphel_cam image decimation and binning set to [%d]\n", im_dec);
+
+ cam = new Elphel_Cam(elphel_host);
+
+ cam->init(fps, im_dec, im_dec);
+
+ cam->start();
+ }
+ virtual ~Elphel_Cam_Node()
+ {
+ if (cam)
+ delete cam;
+ }
+ bool take_and_send_image()
+ {
+ uint8_t *jpeg;
+ uint32_t jpeg_size;
+ if (!cam->next_jpeg(&jpeg, &jpeg_size))
+ {
+ log(ROS::ERROR, "Elphel_Cam::next_jpeg returned an error");
+ return false;
+ }
+
+ // Sometimes things break for no great reason. When this happens
+ // the http server returns a 1x1 GIF.
+ // Skip failures and re-init cam if we get too many of them
+ int failcount = 0;
+ while (jpeg[0] == 0x47 && jpeg[1] == 0x49) { //THIS IS A GIF
+ if (failcount++ > 10) {
+ printf("Received too many failures... restarting cam\n");
+ cam->init(fps, im_dec, im_dec);
+ cam->start();
+ failcount = 0;
+ }
+ if (!cam->next_jpeg(&jpeg, &jpeg_size))
+ {
+ log(ROS::ERROR, "Elphel_Cam::next_jpeg returned an error");
+ return false;
+ }
+ }
+
+ image->set_data_size(jpeg_size);
+ memcpy(image->data, jpeg, jpeg_size);
+
+ image->compression = "jpeg";
+ image->colorspace = "rgb24";
+
+ codec->extract_header_to_flow();
+
+ image->frame_id = frame_id;
+
+ printf("Sending %d x %d\n", image->width, image->height);
+
+ image->publish();
+ return true;
+ }
+};
+
+int main(int argc, char **argv)
+{
+ Elphel_Cam_Node a;
+ while (a.happy())
+ if (!a.take_and_send_image())
+ {
+ a.log(ROS::ERROR,"couldn't take image.");
+ break;
+ }
+ return 0;
+}
Modified: pkg/trunk/elphel_cam/src/libelphel_cam/elphel_cam.cpp
===================================================================
--- pkg/trunk/elphel_cam/src/libelphel_cam/elphel_cam.cpp 2008-04-16 01:35:21 UTC (rev 104)
+++ pkg/trunk/elphel_cam/src/libelphel_cam/elphel_cam.cpp 2008-04-16 21:16:16 UTC (rev 105)
@@ -38,22 +38,25 @@
jpeg_buf_size = 0;
curl_global_init(0);
+ //URL to get next image, and increment pointer
ostringstream oss;
oss << "http://" << ip << ":8081/torp/wait/img/next/save";
image_url = new char[oss.str().length()+1];
strcpy(image_url, oss.str().c_str());
-
+ //URL to initialize pointer
oss.str("");
- oss << "http://" << ip << ":8081/towp/save";
+ oss << "http://" << ip << ":8081/towp/wait/next/save";
towp_url = new char[oss.str().length()+1];
strcpy(towp_url, oss.str().c_str());
+ //URL to control camera adjustments
oss.str("");
oss << "http://" << ip << "/admin-bin/ccam.cgi?";
ccam_url = new char[oss.str().length()+1];
strcpy(ccam_url, oss.str().c_str());
+ //URL to turn on/off the hardware compressor
oss.str("");
oss << "http://" << ip << ":81/compressor.php?";
comp_url = new char[oss.str().length()+1];
@@ -65,10 +68,8 @@
curl_easy_setopt(jpeg_curl, CURLOPT_WRITEDATA, this);
config_curl = curl_easy_init();
- // curl_easy_setopt(config_curl, CURLOPT_URL, config_url);
curl_easy_setopt(config_curl, CURLOPT_WRITEFUNCTION, Elphel_Cam::config_write);
curl_easy_setopt(config_curl, CURLOPT_WRITEDATA, this);
-
}
@@ -127,8 +128,6 @@
char urlbuf[512];
strcpy(urlbuf, oss.str().c_str());
- // printf("Executing command: %s\n", urlbuf);
-
curl_easy_setopt(config_curl, CURLOPT_URL, urlbuf);
CURLcode code;
@@ -158,20 +157,26 @@
uint8_t *jpeg;
uint32_t jpeg_size;
- for (int i = 0; i < 2; i++) { //loop twice
+ // We loop twice here and grab 10 images per loop This is fairly
+ // heuristic and involves the fact that the autogain stuff doesn't
+ // work right until the camera is actually capturing images. We
+ // want this to work if the camera has just powered on without being
+ // manually configured.
+ for (int i = 0; i < 2; i++) {
if (!compressor_cmd("cmd=reset"))
return false;
- //magic incantation:
- //http://wiki.elphel.com/index.php?title=Ccam.cgi
+ //These are the dark fairly undocumented incantations that
+ //initialize the camera well:
+ //"Documentation" can be found at: http://wiki.elphel.com/index.php?title=Ccam.cgi
ostringstream oss;
oss << "opt=vhcxyu+!-"
<< "&dh=" << im_dec << "&dv=" << im_dec
<< "&bh=" << im_bin << "&bh=" << im_bin
<< "&iq=90"
- << "&fps=" << fps << "&fpslm=3"
- << "&kgm=6&sens=2&bit=8&gam=50&pxl=10&csb=200&csr=200&rscale=auto&bscale=auto";
+ << "&fps=" << fps << ".0&fpslm=3"
+ << "&sens=4&bit=8&gam=50&pxl=10&csb=200&csr=200&rscale=auto&bscale=auto";
if (!ccam_cmd(oss.str()))
return false;
@@ -197,12 +202,21 @@
bool Elphel_Cam::start() {
+
+ //We put in sleeps here (*cringe*) because otherwise if we start reading too fast things break.
+
+ usleep(100000);
+
if (!compressor_cmd("cmd=run"))
return false;
+ usleep(100000);
+
if (!towp())
return false;
+ usleep(100000);
+
return true;
}
@@ -221,7 +235,6 @@
{
// overalloc
a->jpeg_buf_size = 2 * (a->jpeg_file_size + (size*nmemb));
- //printf("jpeg_buf_size is now %d\n", a->jpeg_buf_size);
if (a->jpeg_buf)
delete[] a->jpeg_buf;
a->jpeg_buf = new uint8_t[a->jpeg_buf_size];
@@ -239,9 +252,6 @@
Elphel_Cam *a = (Elphel_Cam *)userp;
a->config_ss_mutex.lock();
a->config_ss << string((char *)buf, size*nmemb);
- //printf("writing %d bytes\n", size*nmemb);
- //cout << a->ptz_ss.str() << endl;
a->config_ss_mutex.unlock();
- //cout << string((char *)buf, size*nmemb);
return size*nmemb;
}
Modified: pkg/trunk/elphel_cam/test/test_cam/test_cam.cpp
===================================================================
--- pkg/trunk/elphel_cam/test/test_cam/test_cam.cpp 2008-04-16 01:35:21 UTC (rev 104)
+++ pkg/trunk/elphel_cam/test/test_cam/test_cam.cpp 2008-04-16 21:16:16 UTC (rev 105)
@@ -45,7 +45,7 @@
uint8_t* jpeg;
uint32_t jpeg_size;
- e.init(80, 4, 4);
+ e.init(20, 2, 2);
e.start();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|