|
|
Jump to this file's LXR Page |
|
|
File: [CENS] / emstar / devel / loc / ar / ar_table.c
(download)
/
(as text)
Revision: 1.7, Mon Apr 4 23:20:01 2005 UTC (4 years, 7 months ago) by girod Branch: MAIN CVS Tags: rdd_alpha_version_1, pregeonet, acoustic-05-18-06, PRE_TOSNIC_FIX, PRE_64BIT, MOTENIC_PRE_BUGFIX_20050415, LAURA_CALIBRATION_EXPERIMENTS, HEAD, ESS_RELEASE_3_5, ESS_RELEASE_3_4, ESS_RELEASE_3_2, ESS_RELEASE_3_1, ESS_RELEASE_3_0, ESS_RELEASE_2_0, ESS_CONNECTIVITY, ESS_CENTROUTE_TESTING, ESS2-CMS-V1_5_pretest, ESS2-CMS-V1_4cMergeSympathy, EMSTAR_RELEASE_2_5, CYCLOPS_RELEASE_CANDIDATE_2_0, CYCLOPS_PRERELEASE_STABLE, CENTROUTE_EMSTAR_SOCKETS, BG_1_0, BANGLADESH_ARSENIC_1_2, BANGLADESH_ARSENIC_1_1, AMARSS_JR_DEPLOYMENT_6_05_07 Changes since 1.6: +5 -3 lines multilat fixes.. now working |
/*
*
* Copyright (c) 2005 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.
*
*/
#include <ar.h>
QUEUE_FUNCTION_INSTANTIATIONS(ar_chirp_list,_,chirps,chirp_record_t,ar_state_t);
QUEUE_FUNCTION_INSTANTIATIONS(ar_neighbor_list,_,neighbors,range_neighbor_t,ar_state_t);
QUEUE_FUNCTION_INSTANTIATIONS(ar_result_list,_,results,chirp_result_t,range_neighbor_t);
/* lookup/create */
range_neighbor_t *ar_neighbor_lookup(ar_state_t *ar, node_id_t id, int create)
{
range_neighbor_t *ptr;
for (ptr=ar_neighbor_list_top(ar); ptr; ptr=ar_neighbor_list_next(ptr)) {
if (ptr->node == id)
return ptr;
}
if (create) {
ptr = g_new0(range_neighbor_t, 1);
ptr->node = id;
ar_neighbor_list_push(ar, ptr);
}
return ptr;
}
/*
* Local range status output
*/
static
void ar_entry_to_buf(buf_t *buf, range_entry_t *entry)
{
bufprintf(buf, "Range: %.3f[%.1f] %.1f azi, %.1f zen [%.1f], seqno=%d",
entry->distance / 1000.0,
entry->conf / 10.0,
entry->theta / 10.0,
entry->phi / 10.0,
entry->a_conf / 10.0,
entry->seqno % 256);
}
static
int ar_local_ranges_print(status_context_t *ctx, buf_t *buf)
{
ar_state_t *ar = (ar_state_t *)sd_data(ctx);
bufprintf(buf,
"Local Ranges:\n"
"-------------\n");
range_neighbor_t *n;
for (n=ar_neighbor_list_top(ar); n; n=ar_neighbor_list_next(n)) {
chirp_result_t *ptr;
bufprintf(buf, "Neighbor %s: %sPublished\n",
print_if_id(n->node), n->best ? "" : "Not ");
if (n->best && (n->node != my_node_id)) {
bufprintf(buf, " * ");
ar_entry_to_buf(buf, &(n->published));
bufprintf(buf, "\n");
}
for (ptr=ar_result_list_top(n); ptr; ptr=ar_result_list_next(ptr)) {
bufprintf(buf, " %c%d ", ptr->best ? 'B' : ' ', ptr->angle_group);
ar_entry_to_buf(buf, &(ptr->entry));
bufprintf(buf, " uncomb=%.3f status=%d\n",
(float)ptr->uncombined_range / 1000.0, ptr->status);
if (ptr->mode > 0) {
bufprintf(buf, " dist-mode=%.3f[%.1f], angle-avg=%.1f\n",
ptr->mode_value, ptr->mode, ptr->angle_value);
}
}
bufprintf(buf, "\n");
}
return STATUS_MSG_COMPLETE;
}
/*
* Publication interface to statesync
*/
void ar_republish(ar_state_t *ar)
{
g_status_dev_notify(ar->local_ranges);
range_neighbor_t *n;
buf_t *table = buf_new();
ar->published_count = 0;
for (n=ar_neighbor_list_top(ar); n; n=ar_neighbor_list_next(n)) {
if (n->best && (n->published.conf != 0 || n->node == my_node_id)) {
ar->published_count++;
range_entry_table_t entry = {
range_entry: n->published
};
bufcpy(table, &entry, sizeof(entry));
}
}
/* push table */
flow_id_t fid = {
src: my_node_id,
dst: LINK_BROADCAST,
max_hops: 10
};
if (range_entry_pub(SSYNC_MULTIHOP_PREFIX, (range_entry_table_t *)table->buf,
ar->published_count, &fid) < 0) {
elog(LOG_WARNING, "Failed to push local ranges to state sync: %m");
}
buf_free(table);
}
#define AR_ANGLE_SLIP 10 /* degrees */
#define AR_RANGE_SLIP 100 /* mm */
void ar_update_published(ar_state_t *ar, chirp_result_t *result)
{
chirp_result_t *ptr;
chirp_result_t *j;
chirp_result_t *k;
/* look up / create */
range_neighbor_t *n = ar_neighbor_lookup(ar, result->entry.source, 1);
n->best = NULL;
int inval_all = (result->entry.source == my_node_id);
/* toss any info from previous sequence numbers */
for (ptr=ar_result_list_top(n); ptr; ) {
chirp_result_t *tmp = ptr;
ptr=ar_result_list_next(ptr);
if (tmp->entry.seqno != result->entry.seqno || inval_all) {
elog(LOG_NOTICE, "Dropping result info for node %s, old seqno %d != %d",
print_if_id(result->entry.source), result->entry.seqno, tmp->entry.seqno);
ar_result_list_remove(n, tmp);
free(tmp);
}
else {
tmp->used = 0;
tmp->curr_angle = 0;
tmp->mode = 0;
tmp->mode_value = 0;
tmp->best = 0;
tmp->angle_group = 0;
/* skip over no conf data */
if (tmp->entry.conf == 0) tmp->used = 1;
}
}
/* push new entry */
ar_result_list_push(n, result);
/*
* recompute results
*/
/* process each angle class */
int angle_group = 0;
for (ptr=ar_result_list_top(n); ptr; ptr=ar_result_list_next(ptr)) {
if (ptr->used == 0) {
/* locate average of all angles in this class */
float angle = ((float)ptr->entry.theta / 10.0);
float angle_sum = angle;
int count = 1;
angle_group++;
ptr->angle_group = angle_group;
ptr->curr_angle = 1;
for (j=ar_result_list_next(ptr); j; j=ar_result_list_next(j))
if (j->used == 0) {
float this_angle = ((float)j->entry.theta / 10.0);
/* correct for wrap */
if ((this_angle - angle) > (360-AR_ANGLE_SLIP)) {
this_angle -= 360.0;
}
else if ((angle - this_angle) > (360-AR_ANGLE_SLIP)) {
this_angle += 360.0;
}
float angle_diff = (abs)(this_angle - angle);
if (angle_diff < AR_ANGLE_SLIP) {
angle_sum += this_angle;
count++;
j->curr_angle = 1;
j->angle_group = angle_group;
}
}
/* find approximate mode */
for (j=ptr; j; j=ar_result_list_next(j))
if (j->curr_angle) {
for (k=ptr; k; k=ar_result_list_next(k))
if (k->curr_angle) {
if (abs(k->entry.distance - j->entry.distance) < AR_RANGE_SLIP) {
/* $$$ could weight by conf */
j->mode++;
j->mode_value += k->entry.distance;
}
}
}
/* find min mode */
float min_value = -1;
k = NULL;
for (j=ptr; j; j=ar_result_list_next(j))
if (j->curr_angle && (j->mode > 0)) {
j->mode_value = j->mode_value / j->mode;
if (min_value < 0 || min_value > j->mode_value) {
k = j;
min_value = j->mode_value;
}
}
if (k) {
k->best = 1;
k->angle_value = (float)angle_sum / (float)count;
}
/* clear angles to used */
for (j=ptr; j; j=ar_result_list_next(j))
if (j->curr_angle) {
j->curr_angle = 0;
j->used = 1;
}
}
}
/* find best choice overall */
float min_value = -1;
k = NULL;
for (ptr=ar_result_list_top(n); ptr; ptr=ar_result_list_next(ptr)) {
if (ptr->best) {
if (min_value < 0 || min_value > ptr->mode_value) {
k = ptr;
min_value = ptr->mode_value;
}
}
}
/* update the published info */
memset(&(n->published), 0, sizeof(n->published));
if (k) {
n->published.source = n->node;
n->published.distance = k->mode_value;
if (k->angle_value < 0)
k->angle_value += 360.0;
if (k->angle_value >= 360.0)
k->angle_value -= 360.0;
n->published.theta = k->angle_value * 10;
n->published.phi = k->entry.phi;
n->published.a_conf = k->entry.a_conf;
n->published.conf = k->entry.conf;
n->published.seqno = k->entry.seqno;
n->best = k;
}
/* publish!! */
ar_republish(ar);
}
void ar_table_init(ar_state_t *ar)
{
/* create local ranges status dev */
status_dev_opts_t opts2 = {
device: {
devname: AR_LOCAL_RANGES_DEVICE,
device_info: ar
},
printable: ar_local_ranges_print
};
if (g_status_dev(&opts2, &(ar->local_ranges)) < 0) {
elog(LOG_CRIT, "Failed to create local ranges device: %m");
}
}
| CENS CVS Mailing List |
Powered by ViewCVS 0.9.2 |