Show raster_scan.c syntax highlighted
/*
*
* Copyright (c) 2003 The Regents of the University of California. All
* rights reserved.
*
* 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.
*
* - Neither the name of the 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 REGENTS 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 REGENTS 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.
*
*/
/*
* Raster scan: for data collection
* Input:
* bounding box which the raster scan operates on
* incr resolution in horizontal and vertical direction respectively
* motor device name, various sensor device names in the vertical node.
* Output:
* log files in human readable format which logs the timestamp, location
* stamp, and sensor value;
* matrix file: only logs sensor data value, but in Matlab matrix format.
*/
#include <libdev/include/query_client.h>
#include "mobility_control.h"
#include "libdev/sensor_client.h"
//change the following line based on the actual sensor data type.
typedef float NimsSensorDataType;
#define __GNU_SOURCE
#include <getopt.h>
#define MAX_TEST_POINTS 20
buf_t *log_buf=NULL;
typedef struct motor_client_state {
char device_name[100];
char status_device_name[100];
int staytime; // in terms of ms
int binary_mode_;
status_client_context_t * sc_ref;
//current point
int pt_x;
int pt_y;
int total_pts;
query_client_ctx_t * qc;
//current motor position:
int curx;
int cury;
// raster scan region
int xmin;
int xmax;
int ymin;
int ymax;
int xres;
int yres;
//sensor device names:
char par_sdev_name[100];
char humidity_sdev_name[100];
char temp_sdev_name[100];
FILE * flog;
FILE * log_file[3];
FILE * matrix_file[3];
} motor_client_state_t;
#define PAR 0
#define HUMIDITY 1
#define TEMP 2
/*
* clients for regression test driver
*/
static void take_sample( motor_client_state_t * mc );
static int retrieve_humidity_sample_value(void *arg, sc_sample_t * one_sample);
static int retrieve_temp_sample_value(void *arg, sc_sample_t * one_sample);
static int retrieve_par_sample_value(void *arg, sc_sample_t * one_sample);
static void goto_next_point( motor_client_state_t * mc);
void log_data( motor_client_state_t * mc, int sensor_type, NimsSensorDataType val);
void install_monitor_motor_client(motor_client_state_t *mcs);
void setup_timer(motor_client_state_t * mcs, int timeout);
static
void raster_scan_usage(char *n)
{
fprintf(stderr, "%s -a [xmin] -b [xmax] -c [ymin] -d [ymax] -x [x_dir_resolution] -y [y_dir_resolution] -m /dev/motor/command_motor -h [humidity-sensor-device-name] -t [temprature-sensor-device-name] -p [par-sensor-device-name]\n", n);
exit(1);
}
static
void move_motor( motor_client_state_t * m_client, float x, float y);
int move_motor_resp(query_client_ctx_t *qc, int retval, buf_t *response)
{
motor_cmd_return_state_t * ret;
motor_client_state_t * mcs = (motor_client_state_t * )query_client_data( qc );
if (retval) {
elog( LOG_ERR, "got error: %s\n", strerror(retval));
exit(1);
}
if (response) {
ret = ( motor_cmd_return_state_t * ) response->buf;
if ( (! ret) || (ret->state != MOTOR_SUCCESS) )
elog( LOG_NOTICE, "FAIL: check command again\n");
else if ( ret->state == MOTOR_SUCCESS )
{
elog( LOG_NOTICE, "SUCCESS: reaching (%.2f, %.2f), now move to the next\n", ret->cx, ret->cy);
if (mcs->flog)
{
fprintf(mcs->flog, "%lf, %lf\n", ret->cx, ret->cy );
fflush( mcs->flog );
}
mcs->total_pts ++;
take_sample( mcs );
setup_timer(mcs, mcs->staytime);
}
buf_free(response);
}
return EVENT_RENEW;
}
void take_sample( motor_client_state_t * mc )
{
//take samples.
if (strlen(mc->humidity_sdev_name) > 1)
sc_get_next_sample( mc->humidity_sdev_name, 0,
retrieve_humidity_sample_value, mc, NULL);
if (strlen(mc->temp_sdev_name) > 1)
sc_get_next_sample( mc->temp_sdev_name, 0,
retrieve_temp_sample_value, mc, NULL);
if (strlen(mc->par_sdev_name) > 1)
sc_get_next_sample( mc->par_sdev_name, 0,
retrieve_par_sample_value, mc, NULL);
//Else goto_next_point( mc );
}
void move_motor( motor_client_state_t * m_client, float x, float y )
{
static consistent_query_client_t * qobj= NULL;
char cmd[256];
char device[50];
sprintf( cmd, "%s:x=%f:y=%f", MOTOR_MOVE_CMD, x, y );
elog( LOG_ERR, "%s", cmd );
sprintf(device, "%s", m_client->device_name);
if (qobj == NULL)
qobj = consistent_query_client_new(m_client, cmd, move_motor_resp, device);
consistent_query_client_issue_cmd( qobj, cmd );
return;
}
int main(int argc, char **argv)
{
/*
* check options
*/
motor_client_state_t m_client={};
char * key;
char fname[256];
if ((key = misc_parse_out_option(&argc, argv, "help", '?'))) {
raster_scan_usage( argv[0] );
exit(1);
}
if ((key = misc_parse_out_option(&argc, argv, "xmin", 'a'))) {
m_client.xmin = atoi( key );
}
else {
elog(LOG_ERR,"No xmin is specified for the raster scan region!\n");
exit(1);
}
if ((key = misc_parse_out_option(&argc, argv, "xmax", 'b'))) {
m_client.xmax = atoi( key );
}
else {
elog(LOG_ERR,"No xmax is specified for the raster scan region!\n");
exit(1);
}
if ((key = misc_parse_out_option(&argc, argv, "ymin", 'c'))) {
m_client.ymin = atoi( key );
}
else {
elog(LOG_ERR,"No ymin is specified for the raster scan region!\n");
exit(1);
}
if ((key = misc_parse_out_option(&argc, argv, "ymax", 'd'))) {
m_client.ymax = atoi( key );
}
else {
elog(LOG_ERR,"No ymax is specified for the raster scan region!\n");
exit(1);
}
if ((key = misc_parse_out_option(&argc, argv, "xres", 'x'))) {
m_client.xres = atoi( key );
}
else {
elog(LOG_ERR,"No xres is specified for the raster scan region!\n");
exit(1);
}
if ((key = misc_parse_out_option(&argc, argv, "yres", 'y'))) {
m_client.yres = atoi( key );
}
else {
elog(LOG_ERR,"No y-resolution is specified for the raster scan region!\n");
exit(1);
}
if ((key = misc_parse_out_option(&argc, argv, "timeout", 'q'))) {
m_client.staytime = atoi( key );
}
else {
elog(LOG_ERR,"No y-resolution is specified for the raster scan region!\n");
exit(1);
}
//extract various device name from the command line options.
//motor device
strcpy( m_client.device_name, "\0") ;
strcpy( m_client.humidity_sdev_name, "\0") ;
strcpy( m_client.temp_sdev_name, "\0") ;
strcpy( m_client.par_sdev_name, "\0") ;
if ((key = misc_parse_out_option(&argc, argv, "motor-device-name", 'm'))) {
strcpy(m_client.device_name, key );
}
else {
elog(LOG_ERR,"No motor device is specified for the motor driver!\n");
exit(1);
}
if ((key = misc_parse_out_option(&argc, argv, "motor-status-device-name", 's'))) {
strcpy(m_client.status_device_name, key );
}
else {
elog(LOG_ERR,"No motor status device is specified for the motor driver!\n");
exit(1);
}
if ((key = misc_parse_out_option(&argc, argv, "humidity-sensor-device-name", 'h'))) {
strcpy(m_client.humidity_sdev_name, key );
}
else {
elog(LOG_ERR,"No humidity sensor device is specified!\n");
}
if ((key = misc_parse_out_option(&argc, argv, "temprature-sensor-device-name", 't'))) {
strcpy(m_client.temp_sdev_name, key );
}
else {
elog(LOG_ERR,"No temprature sensor device is specified!\n");
}
if ((key = misc_parse_out_option(&argc, argv, "par-sensor-device-name", 'p'))) {
strcpy(m_client.par_sdev_name, key );
}
else {
elog(LOG_ERR,"No temprature sensor device is specified!\n");
}
if ( strlen( m_client.par_sdev_name ) > 1 )
{
sprintf( fname, "%s.log", m_client.par_sdev_name );
m_client.log_file[PAR] = fopen( fname, "w" );
if (m_client.log_file[PAR] == NULL) {
elog( LOG_ERR, "failed opening file %s\n", fname);
return (-1);
}
}
if ( strlen( m_client.par_sdev_name ) > 1 )
{
sprintf( fname, "%s.matrix", m_client.par_sdev_name );
m_client.matrix_file[PAR] = fopen( fname, "w" );
if (m_client.matrix_file[PAR] == NULL) {
elog( LOG_ERR, "failed opening file %s\n", fname);
return (-1);
}
}
if ( strlen( m_client.humidity_sdev_name ) > 1 )
{
sprintf( fname, "%s.log", m_client.humidity_sdev_name );
m_client.log_file[HUMIDITY] = fopen( fname, "w" );
if (m_client.log_file[HUMIDITY] == NULL) {
elog( LOG_ERR, "failed opening file %s\n", fname);
return (-1);
}
}
if ( strlen( m_client.humidity_sdev_name ) > 1 )
{
sprintf( fname, "%s.matrix", m_client.humidity_sdev_name );
m_client.matrix_file[HUMIDITY] = fopen( fname, "w" );
if (m_client.matrix_file[HUMIDITY] == NULL) {
elog( LOG_ERR, "failed opening file %s\n", fname);
return (-1);
}
}
if ( strlen( m_client.temp_sdev_name ) > 1 )
{
sprintf( fname, "%s.log", m_client.temp_sdev_name );
m_client.log_file[TEMP] = fopen( fname, "w" );
if (m_client.log_file[TEMP] == NULL) {
elog( LOG_ERR, "failed opening file %s\n", fname);
return (-1);
}
}
if ( strlen( m_client.temp_sdev_name ) > 1 )
{
sprintf( fname, "%s.matrix", m_client.temp_sdev_name );
m_client.matrix_file[TEMP] = fopen( fname, "w" );
if (m_client.matrix_file[TEMP] == NULL) {
elog( LOG_ERR, "failed opening file %s\n", fname);
return (-1);
}
}
m_client.flog = fopen("locations", "w");
if (m_client.flog == NULL)
elog(LOG_ERR, "open location log file error" );
m_client.binary_mode_ = 1;
install_monitor_motor_client( &m_client);
//go to the first point.
goto_next_point( & m_client );
g_main();
return 0;
}
static
int retrieve_humidity_sample_value(void *arg, sc_sample_t * one_sample)
{
motor_client_state_t *state = (motor_client_state_t *)arg;
if ( sizeof(NimsSensorDataType) != one_sample->data->len )
{
elog( LOG_ERR, "Invalid sample size: %d\n", one_sample->data->len );
exit(-1);
}
NimsSensorDataType value = * (NimsSensorDataType *) one_sample->data->buf;
log_data(state, HUMIDITY, value);
return 0;
}
static
int retrieve_temp_sample_value(void *arg, sc_sample_t * one_sample)
{
motor_client_state_t *state = (motor_client_state_t *)arg;
if ( sizeof(NimsSensorDataType) != one_sample->data->len )
{
elog( LOG_ERR, "Invalid sample size: %d\n", one_sample->data->len );
exit(-1);
}
NimsSensorDataType value = * (NimsSensorDataType *) one_sample->data->buf;
log_data(state, TEMP, value);
return 0;
}
static
int retrieve_par_sample_value(void *arg, sc_sample_t * one_sample)
{
motor_client_state_t *state = (motor_client_state_t *)arg;
if ( sizeof(NimsSensorDataType) != one_sample->data->len )
{
elog( LOG_ERR, "Invalid sample size: %d\n", one_sample->data->len );
exit(-1);
}
NimsSensorDataType value = * (NimsSensorDataType *) one_sample->data->buf;
log_data(state, PAR, value);
return 0;
}
static
void goto_next_point( motor_client_state_t * mc)
{
int cx, cy;
elog( LOG_ERR, "cur position: %d %d : total # of points: %d, bounding box:(%d, %d), (%d, %d)\n", mc->pt_x, mc->pt_y, mc->total_pts, mc->xmin, mc->xmax, mc->ymin, mc->ymax );
if ( mc->total_pts == 0 )
{
cx = mc->xmin;
cy = mc->ymin;
goto done;
}
cx = mc->pt_x;
cy = mc->pt_y;
cy += mc->yres;
if ( cy > mc->ymax )
{
cy = mc->ymin;
cx += mc->xres;
if ( cx > mc->xmax )
{
elog( LOG_ERR, "done!\n" );
exit(0);
}
}
done:
mc->pt_x = cx;
mc->pt_y = cy;
move_motor( mc, cx, cy );
}
void log_data( motor_client_state_t * mc, int sensor_type, NimsSensorDataType val)
{
struct timeval t;
int py = mc->pt_y + mc->yres;
gettimeofday(&t,NULL);
fprintf(mc->log_file[sensor_type], "%s (%d, %d) %f\n", misc_print_date(&t), mc->curx, mc->cury, val);
fprintf( mc->matrix_file[sensor_type], "%f ", val );
if ( py > mc->ymax )
{
fprintf( mc->matrix_file[sensor_type], "\n" );
}
fflush(mc->log_file[sensor_type]);
fflush(mc->matrix_file[sensor_type]);
}
int stay_still_timeout(void *data, int interval, g_event_t *event)
{
motor_client_state_t *mcs = (motor_client_state_t *) data;
goto_next_point( mcs );
return TIMER_DONE;
}
void setup_timer(motor_client_state_t * mcs, int timeout)
{
if (g_timer_add(timeout, stay_still_timeout, mcs, NULL, NULL) < 0) {
elog(LOG_CRIT, "Failed to install timer: %m");
}
}
static
int status_print_bin_output(void *new_buffer, size_t size, void *data)
{
motor_client_state_t *state = (motor_client_state_t *) data;
motor_cmd_return_state_t * ret;
if (size > 1)
{
ret = (motor_cmd_return_state_t *) new_buffer;
state->curx= ret->cx;
state->cury= ret->cy;
}
else {
free(new_buffer);
elog(LOG_ERR, "g_status_client_destroy(state->sc_ref);\n" );
g_status_client_destroy(state->sc_ref);
}
return EVENT_RENEW;
}
static
int status_print_ascii_output(void *new_buffer, size_t size, void *data)
{
elog(LOG_ERR, "received status update: ascii: %s, size = %d\n", (char *) new_buffer, size);
return EVENT_RENEW;
}
void install_monitor_motor_client(motor_client_state_t *mcs)
{
status_client_opts_t opts = {};
opts.devname = mcs->status_device_name;
opts.private_data = mcs;
// opts.crashed = handle_crash;
// opts.destroy = destroy_private_data;
opts.read_as_ascii = ! mcs->binary_mode_;
if (mcs->binary_mode_ == 1) {
opts.handler = status_print_bin_output;
} else {
opts.handler = status_print_ascii_output;
}
g_status_client_full(&opts, &mcs->sc_ref);
}
See more files for this project here