|
From: <mor...@us...> - 2008-03-28 02:05:39
|
Revision: 57
http://personalrobots.svn.sourceforge.net/personalrobots/?rev=57&view=rev
Author: morgan_quigley
Date: 2008-03-27 19:05:43 -0700 (Thu, 27 Mar 2008)
Log Message:
-----------
major changes to axis_cam to bring in functionality first implemented by jeremy: get/set focus and get/set iris, as well as using libcurl for everything (prior to today it was using wget for ptz)
Modified Paths:
--------------
pkg/trunk/axis_cam/include/axis_cam/axis_cam.h
pkg/trunk/axis_cam/manifest.xml
pkg/trunk/axis_cam/src/axis_cam/axis_cam.cpp
pkg/trunk/axis_cam/src/libaxis_cam/axis_cam.cpp
Added Paths:
-----------
pkg/trunk/axis_cam/test/test_camcontrol/
pkg/trunk/axis_cam/test/test_camcontrol/Makefile
pkg/trunk/axis_cam/test/test_camcontrol/kbhit.cpp
pkg/trunk/axis_cam/test/test_camcontrol/kbhit.h
pkg/trunk/axis_cam/test/test_camcontrol/test_camcontrol.cpp
Modified: pkg/trunk/axis_cam/include/axis_cam/axis_cam.h
===================================================================
--- pkg/trunk/axis_cam/include/axis_cam/axis_cam.h 2008-03-28 01:57:04 UTC (rev 56)
+++ pkg/trunk/axis_cam/include/axis_cam/axis_cam.h 2008-03-28 02:05:43 UTC (rev 57)
@@ -32,6 +32,7 @@
#include <curl/curl.h>
#include <string>
+#include <sstream>
using namespace std;
class AxisCam
@@ -41,19 +42,30 @@
~AxisCam();
bool get_jpeg(uint8_t ** const fetch_jpeg_buf, uint32_t *fetch_buf_size);
- bool ptz(double pan, double tilt, double zoom);
+ bool set_ptz(double pan, double tilt, double zoom, bool relative = false);
+ bool set_focus(int focus = 0, bool relative = false); // zero for autofocus
+ int get_focus();
+ bool set_iris(int iris = 0, bool relative = false); // zero for autoiris
+ int get_iris();
private:
string ip;
uint8_t *jpeg_buf;
uint32_t jpeg_buf_size, jpeg_file_size;
- CURL *jpeg_curl;
+ CURL *jpeg_curl, *getptz_curl, *setptz_curl;
+ char *image_url, *ptz_url;
+ stringstream ptz_ss; // need to mutex this someday...
inline double clamp(double d, double low, double high)
{
return (d < low ? low : (d > high ? high : d));
}
static size_t jpeg_write(void *buf, size_t size, size_t nmemb, void *userp);
- char *image_url;
+ static size_t ptz_write(void *buf, size_t size, size_t nmemb, void *userp);
+ bool send_params(string params);
+ bool query_params();
+ int last_iris, last_focus;
+ double last_pan, last_tilt, last_zoom;
+ bool last_autofocus_enabled, last_autoiris_enabled;
};
#endif
Modified: pkg/trunk/axis_cam/manifest.xml
===================================================================
--- pkg/trunk/axis_cam/manifest.xml 2008-03-28 01:57:04 UTC (rev 56)
+++ pkg/trunk/axis_cam/manifest.xml 2008-03-28 02:05:43 UTC (rev 57)
@@ -13,5 +13,6 @@
<url>http://stair.stanford.edu</url>
<depend package="common_flows"/>
<depend package="image_viewer"/>
+<depend package="string_utils"/>
</package>
Modified: pkg/trunk/axis_cam/src/axis_cam/axis_cam.cpp
===================================================================
--- pkg/trunk/axis_cam/src/axis_cam/axis_cam.cpp 2008-03-28 01:57:04 UTC (rev 56)
+++ pkg/trunk/axis_cam/src/axis_cam/axis_cam.cpp 2008-03-28 02:05:43 UTC (rev 57)
@@ -28,10 +28,10 @@
// POSSIBILITY OF SUCH DAMAGE.
#include "ros/ros_slave.h"
-#include "image_flows/FlowImage.h"
+#include "common_flows/FlowImage.h"
#include "axis_cam/axis_cam.h"
-class AxisCamWget : public ROS_Slave
+class AxisCamNode : public ROS_Slave
{
public:
FlowImage *image;
@@ -39,7 +39,7 @@
AxisCam *cam;
int frame_id;
- AxisCamWget() : ROS_Slave(), cam(NULL), frame_id(0)
+ AxisCamNode() : ROS_Slave(), cam(NULL), frame_id(0)
{
register_source(image = new FlowImage("image"));
if (!get_string_param(".host", axis_host))
@@ -52,7 +52,7 @@
cam = new AxisCam(axis_host);
printf("package path is [%s]\n", get_my_package_path().c_str());
}
- virtual ~AxisCamWget()
+ virtual ~AxisCamNode()
{
if (cam)
delete cam;
@@ -80,7 +80,7 @@
int main(int argc, char **argv)
{
- AxisCamWget a;
+ AxisCamNode a;
while (a.happy())
if (!a.take_and_send_image())
{
Modified: pkg/trunk/axis_cam/src/libaxis_cam/axis_cam.cpp
===================================================================
--- pkg/trunk/axis_cam/src/libaxis_cam/axis_cam.cpp 2008-03-28 01:57:04 UTC (rev 56)
+++ pkg/trunk/axis_cam/src/libaxis_cam/axis_cam.cpp 2008-03-28 02:05:43 UTC (rev 57)
@@ -29,7 +29,9 @@
// POSSIBILITY OF SUCH DAMAGE.
#include <sstream>
+#include <iostream>
#include "axis_cam/axis_cam.h"
+#include "string_utils/string_utils.h"
AxisCam::AxisCam(string ip) : ip(ip)
{
@@ -42,12 +44,34 @@
image_url = new char[oss.str().length()+1];
strcpy(image_url, oss.str().c_str());
+ oss.str(""); // clear it
+ oss << "http://" << ip << "/axis-cgi/com/ptz.cgi";
+ ptz_url = new char[oss.str().length()+1];
+ strcpy(ptz_url, oss.str().c_str());
+
jpeg_curl = curl_easy_init();
curl_easy_setopt(jpeg_curl, CURLOPT_URL, image_url);
curl_easy_setopt(jpeg_curl, CURLOPT_WRITEFUNCTION, AxisCam::jpeg_write);
curl_easy_setopt(jpeg_curl, CURLOPT_WRITEDATA, this);
- printf("Getting images from [%s]", oss.str().c_str());
+ getptz_curl = curl_easy_init();
+ curl_easy_setopt(getptz_curl, CURLOPT_URL, ptz_url);
+ curl_easy_setopt(getptz_curl, CURLOPT_WRITEFUNCTION, AxisCam::ptz_write);
+ curl_easy_setopt(getptz_curl, CURLOPT_WRITEDATA, this);
+ curl_easy_setopt(getptz_curl, CURLOPT_POSTFIELDS, "query=position");
+
+ setptz_curl = curl_easy_init();
+ curl_easy_setopt(setptz_curl, CURLOPT_URL, ptz_url);
+ curl_easy_setopt(setptz_curl, CURLOPT_WRITEFUNCTION, AxisCam::ptz_write);
+ curl_easy_setopt(setptz_curl, CURLOPT_WRITEDATA, this);
+
+ printf("Getting images from [%s]\n", oss.str().c_str());
+ if (!query_params())
+ printf("sad! I couldn't query the camera parameters.\n");
+ if (!query_params())
+ printf("sad! I couldn't query the camera parameters.\n");
+ if (!query_params())
+ printf("sad! I couldn't query the camera parameters.\n");
}
AxisCam::~AxisCam()
@@ -101,45 +125,121 @@
a->jpeg_file_size += size*nmemb;
return size*nmemb;
}
+
+size_t AxisCam::ptz_write(void *buf, size_t size, size_t nmemb, void *userp)
+{
+ if (size * nmemb == 0)
+ return 0;
+ AxisCam *a = (AxisCam *)userp;
+ a->ptz_ss << string((char *)buf, size*nmemb);
+ printf("%d bytes\n", size*nmemb);
+ //cout << string((char *)buf, size*nmemb);
+ return size*nmemb;
+}
+
+bool AxisCam::set_ptz(double pan, double tilt, double zoom, bool relative)
+{
+ ostringstream oss;
+ if (relative)
+ oss << "rpan=" << pan
+ << "&rtilt=" << tilt
+ << "&rzoom=" << zoom;
+ else
+ oss << "pan=" << clamp(pan, -175, 175)
+ << "&tilt=" << clamp(tilt, -45, 90)
+ << "&zoom=" << clamp(zoom, 0, 50000); // not sure of upper bound
+ return send_params(oss.str());
+}
+
+int AxisCam::get_focus()
+{
+ if (last_autofocus_enabled)
+ {
+ set_focus(0, true); // manual focus but don't move it
+ query_params();
+ set_focus(0); // re-enable autofocus
+ return last_focus;
+ }
+ query_params();
+ return last_focus;
+}
- /*
- if (jpeg_file_size > jpeg_buf_size)
+bool AxisCam::set_focus(int focus, bool relative)
+{
+ ostringstream oss;
+ if (focus == 0 && !relative)
+ oss << string("autofocus=on");
+ else
{
- if (jpeg_buf)
- delete[] jpeg_buf;
- jpeg_buf_size = (uint32_t)(1.5*jpeg_file_size);
- jpeg_buf = new uint8_t[jpeg_buf_size]; // go big to save reallocs
+ last_autofocus_enabled = false;
+ oss << string("autofocus=off&")
+ << (relative ? "r" : "") << string("focus=") << focus;
}
- size_t bytes_read = fread(jpeg_buf, 1, jpeg_file_size, jpeg_file);
- if (bytes_read != jpeg_file_size)
+ return send_params(oss.str());
+}
+
+bool AxisCam::set_iris(int iris, bool relative)
+{
+ ostringstream oss;
+ if (iris == 0)
+ oss << "autoiris=on";
+ else
+ oss << string("autoiris=off&")
+ << (relative ? "r" : "") << string("iris=") << iris;
+ return send_params(oss.str());
+}
+
+bool AxisCam::send_params(string params)
+{
+ ptz_ss.str("");
+ curl_easy_setopt(setptz_curl, CURLOPT_POSTFIELDS, params.c_str());
+ CURLcode code;
+ if (code = curl_easy_perform(setptz_curl))
{
- printf("couldn't read entire jpeg file\n");
+ printf("woah! curl error: [%s]\n", curl_easy_strerror(code));
return false;
}
- fclose(jpeg_file);
- *fetch_jpeg_buf = jpeg_buf;
- *fetch_buf_size = jpeg_file_size;
- */
+ return true;
+}
-bool AxisCam::ptz(double pan, double tilt, double zoom)
+bool AxisCam::query_params()
{
- pan = clamp(pan, -175, 175);
- tilt = clamp(tilt, -45, 90);
- zoom = clamp(zoom, 0, 50000); // not sure of the real upper bound. units are rather magical.
- ostringstream oss;
- oss << string("wget -q -O/dev/null \"") << ip << string("/axis-cgi/com/ptz.cgi?camera=1&pan=") << pan
- << string("&tilt=") << tilt << string("&zoom=") << zoom << string("\"");
- //printf("about to execute: [%s]\n", oss.str().c_str());
- int retval = system(oss.str().c_str());
- if (retval > 0)
+ ptz_ss.str("");
+ CURLcode code;
+ if (code = curl_easy_perform(getptz_curl))
{
- printf("ahhh nonzero return value from wget during ptz: %d\n", retval);
+ printf("woah! curl error: [%s]\n", curl_easy_strerror(code));
return false;
}
- else if (retval < 0)
+ printf("response:\n%s\n", ptz_ss.str().c_str());
+ while (ptz_ss.good())
{
- // not sure what's happening here, but it appears to be benign.
- //printf("odd wget system retval = %d\n", retval);
+ string line;
+ getline(ptz_ss, line);
+ vector<string> tokens;
+ string_utils::split(line, tokens, "=");
+ if (tokens.size() != 2)
+ continue;
+ if (tokens[0] == string("pan"))
+ last_pan = atof(tokens[1].c_str());
+ else if (tokens[0] == string("tilt"))
+ last_tilt = atof(tokens[1].c_str());
+ else if (tokens[0] == string("zoom"))
+ last_zoom = atof(tokens[1].c_str());
+ else if (tokens[0] == string("focus"))
+ last_focus = atoi(tokens[1].c_str());
+ else if (tokens[0] == string("iris"))
+ last_iris = atoi(tokens[1].c_str());
+ else if (tokens[0] == string("autofocus"))
+ last_autofocus_enabled = (tokens[1] == string("on") ? true : false);
+ else if (tokens[0] == string("autoiris"))
+ last_autoiris_enabled = (tokens[1] == string("on") ? true : false);
+/*
+ printf("line has %d tokens:\n", tokens.size());
+ for (int i = 0; i < tokens.size(); i++)
+ printf(" [%s] ", tokens[i].c_str());
+ printf("\n");
+*/
}
return true;
}
Added: pkg/trunk/axis_cam/test/test_camcontrol/Makefile
===================================================================
--- pkg/trunk/axis_cam/test/test_camcontrol/Makefile (rev 0)
+++ pkg/trunk/axis_cam/test/test_camcontrol/Makefile 2008-03-28 02:05:43 UTC (rev 57)
@@ -0,0 +1,6 @@
+SRC = test_camcontrol.cpp kbhit.cpp
+OUT = test_camcontrol
+LFLAGS = -L../../lib -laxis_cam -lcurl -lstring_utils
+LIBDEPS = ../../lib/libaxis_cam.a
+PKG = axis_cam
+include $(shell $(ROS_ROOT)/rospack find roscpp)/make_include/node.mk
Added: pkg/trunk/axis_cam/test/test_camcontrol/kbhit.cpp
===================================================================
--- pkg/trunk/axis_cam/test/test_camcontrol/kbhit.cpp (rev 0)
+++ pkg/trunk/axis_cam/test/test_camcontrol/kbhit.cpp 2008-03-28 02:05:43 UTC (rev 57)
@@ -0,0 +1,51 @@
+#include "kbhit.h"
+#include <termios.h>
+#include <unistd.h>
+
+static struct termios initial_settings, new_settings;
+static int peek_character = -1;
+
+void init_keyboard()
+{
+ tcgetattr(0, &initial_settings);
+ new_settings = initial_settings;
+ new_settings.c_lflag &= ~ICANON;
+ new_settings.c_lflag &= ~ECHO;
+// new_settings.c_lflag &= ~ISIG;
+ new_settings.c_cc[VMIN] = 1;
+ new_settings.c_cc[VTIME] = 0;
+ tcsetattr(0, TCSANOW, &new_settings);
+}
+
+void close_keyboard()
+{
+ tcsetattr(0, TCSANOW, &initial_settings);
+}
+
+int _kbhit()
+{
+ unsigned char ch;
+ int nread;
+ new_settings.c_cc[VMIN] = 0;
+ tcsetattr(0, TCSANOW, &new_settings);
+ nread = read(0, &ch, 1);
+ new_settings.c_cc[VMIN] = 1;
+ tcsetattr(0, TCSANOW, &new_settings);
+ if (nread == 1)
+ {
+ peek_character = ch;
+ return 1;
+ }
+ else
+ {
+ peek_character = 0;
+ return 0;
+ }
+}
+
+char _getch()
+{
+ char c = peek_character;
+ peek_character = 0;
+ return c;
+}
Added: pkg/trunk/axis_cam/test/test_camcontrol/kbhit.h
===================================================================
--- pkg/trunk/axis_cam/test/test_camcontrol/kbhit.h (rev 0)
+++ pkg/trunk/axis_cam/test/test_camcontrol/kbhit.h 2008-03-28 02:05:43 UTC (rev 57)
@@ -0,0 +1,13 @@
+#ifndef KBHIT_H
+#define KBHIT_H
+
+// this code copied from linux-sys.org, where it was copied from "Beginning
+// Linux Programming" a book by Wrox Press
+
+void init_keyboard(void);
+void close_keyboard(void);
+int _kbhit(void);
+char _getch(void);
+
+#endif
+
Added: pkg/trunk/axis_cam/test/test_camcontrol/test_camcontrol.cpp
===================================================================
--- pkg/trunk/axis_cam/test/test_camcontrol/test_camcontrol.cpp (rev 0)
+++ pkg/trunk/axis_cam/test/test_camcontrol/test_camcontrol.cpp 2008-03-28 02:05:43 UTC (rev 57)
@@ -0,0 +1,91 @@
+///////////////////////////////////////////////////////////////////////////////
+// The axis_cam package provides a library that talks to Axis IP-based cameras
+// as well as ROS nodes which use these libraries
+//
+// This file 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 <cstdio>
+#include "axis_cam/axis_cam.h"
+#include "kbhit.h"
+
+int main(int argc, char **argv)
+{
+ AxisCam *axis = new AxisCam("192.168.1.90");
+
+ init_keyboard();
+ int focus = 2000, iris = 2000;
+ while (1)
+ {
+ if (_kbhit())
+ {
+ char c = _getch();
+ if (c == 'q')
+ break;
+ switch(c)
+ {
+ case 'F':
+ printf("enabling autofocus\n");
+ axis->set_focus(0);
+ break;
+ case 'f':
+ focus += 500;
+ printf("focus = %d\n", focus);
+ axis->set_focus(focus);
+ break;
+ case 'd':
+ focus -= 500;
+ printf("focus = %d\n", focus);
+ axis->set_focus(focus);
+ break;
+ case 'I':
+ printf("enabling autoiris\n");
+ axis->set_iris(0);
+ break;
+ case 'i':
+ iris += 500;
+ printf("iris = %d\n", iris);
+ axis->set_iris(iris);
+ break;
+ case 'u':
+ iris -= 500;
+ printf("iris = %d\n", iris);
+ axis->set_iris(iris);
+ break;
+ case '?':
+ printf("focus: [%d]\n", axis->get_focus());
+ break;
+ default:
+ printf("unknown char [%c]\n", c);
+ }
+ }
+ usleep(10000);
+ }
+ close_keyboard();
+
+ delete axis;
+ return 0;
+}
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|