Commit ac002757 authored by Éric Thiébaut's avatar Éric Thiébaut
Browse files

Add methods for configuring a wavefront sensor

parent 6b70a022
......@@ -422,6 +422,7 @@ const char* FUNC(
CASE(TAO_NOT_ACQUIRING, "Acquisition not started");
CASE(TAO_MUST_RESET, "Device must be reset");
CASE(TAO_MISSING_SEPARATOR, "Separator missing");
CASE(TAO_FORBIDDEN_CHANGE, "Forbidden change of parameter(s)");
CASE(TAO_EXHAUSTED, "Resource exhausted");
CASE(TAO_DESTROYED, "Resource has been destroyed");
CASE(TAO_CORRUPTED, "Corrupted structure");
......
......@@ -29,17 +29,55 @@ static inline size_t round_size(
return TAO_ROUND_UP(size, align);
}
static inline tao_remote_sensor_config* primary_config(
tao_remote_sensor* wfs)
{
return &wfs->config;
}
#define ENCODE(out, func, inp, getter) \
static inline out* func##_rw(inp* arg_1) { \
return getter(arg_1); \
} \
static inline const out* func##_ro(const inp* arg_1) { \
return getter(arg_1); \
}
static inline tao_remote_sensor_config* secondary_config(
tao_remote_sensor* wfs)
{
return TAO_COMPUTED_ADDRESS(wfs, wfs->config2_offset);
}
#define PRIMARY_CONFIG(wfs) (&(wfs)->config)
ENCODE(tao_remote_sensor_config, primary_config,
tao_remote_sensor, PRIMARY_CONFIG);
#define primary_config(wfs) _Generic( \
(wfs), \
tao_remote_sensor *: primary_config_rw, \
tao_remote_sensor const*: primary_config_ro)(wfs)
#define SECONDARY_CONFIG(wfs) TAO_COMPUTED_ADDRESS((wfs),(wfs)->config2_offset)
ENCODE(tao_remote_sensor_config, secondary_config,
tao_remote_sensor, SECONDARY_CONFIG);
#define secondary_config(wfs) _Generic( \
(wfs), \
tao_remote_sensor *: secondary_config_rw, \
tao_remote_sensor const*: secondary_config_ro)(wfs)
#define CONFIG_GET_INDS(cfg) (cfg)->inds
ENCODE(long, config_get_inds,
tao_remote_sensor_config, CONFIG_GET_INDS);
#define config_get_inds(cfg) _Generic( \
(cfg), \
tao_remote_sensor_config *: config_get_inds_rw, \
tao_remote_sensor_config const*: config_get_inds_ro)(cfg)
#define CONFIG_GET_SUBS(cfg) TAO_COMPUTED_ADDRESS((cfg), (cfg)->subs_offset)
ENCODE(tao_subimage, config_get_subs,
tao_remote_sensor_config, CONFIG_GET_SUBS);
#define config_get_subs(cfg) _Generic( \
(cfg), \
tao_remote_sensor_config *: config_get_subs_rw, \
tao_remote_sensor_config const*: config_get_subs_ro)(cfg)
#undef ENCODE //---------------------------------------------------------------
extern tao_remote_sensor* tao_remote_sensor_create(
const char* owner,
......@@ -125,31 +163,67 @@ extern tao_remote_sensor* tao_remote_sensor_create(
return wfs;
}
tao_status tao_remote_sensor_check_config(
const tao_remote_sensor* wfs,
const tao_remote_sensor_config* cfg,
const long* inds,
const tao_subimage* subs)
#define ENCODE(T, what, path, defval) \
T tao_remote_sensor_get_##what( \
const tao_remote_sensor* wfs) \
{ \
return (wfs == NULL) ? (defval) : wfs->path; \
}
ENCODE(long, nsubs, config.base.nsubs, 0);
ENCODE(long, max_ninds, config.max_ninds, 0);
ENCODE(long, max_nsubs, config.max_nsubs, 0);
ENCODE(const char*, camera_owner, config.camera.owner, "");
ENCODE(long, camera_width, config.camera.width, 0);
ENCODE(long, camera_height, config.camera.height, 0);
ENCODE(tao_shmid, camera_shmid, config.camera.shmid, TAO_BAD_SHMID);
#undef ENCODE
long tao_remote_sensor_get_ninds(
const tao_remote_sensor* wfs)
{
if (wfs == NULL || cfg == NULL || inds == NULL || subs == NULL) {
tao_store_error(__func__, TAO_BAD_ADDRESS);
return TAO_ERROR;
if (wfs == NULL) {
return 0;
} else {
return wfs->config.base.dims[0] * wfs->config.base.dims[1];
}
long width = wfs->config.camera.width;
long height = wfs->config.camera.height;
if (tao_shackhartmann_check_config(
&cfg->base, inds, subs, width, height) != TAO_OK) {
return TAO_ERROR;
}
const long* tao_remote_sensor_get_inds(
const tao_remote_sensor* wfs,
long* dims)
{
if (wfs == NULL) {
if (dims != NULL) {
dims[0] = 0;
dims[1] = 0;
}
return NULL;
} else {
if (dims != NULL) {
dims[0] = wfs->config.base.dims[0];
dims[1] = wfs->config.base.dims[1];
}
return config_get_inds(&wfs->config);
}
long dim1 = cfg->base.dims[0];
long dim2 = cfg->base.dims[1];
long ninds = dim1*dim2;
long nsubs = cfg->base.nsubs;
if (ninds > wfs->max_ninds || nsubs > wfs->max_nsubs) {
tao_store_error(__func__, TAO_OUT_OF_RANGE);
return TAO_ERROR;
}
const tao_subimage* tao_remote_sensor_get_subs(
const tao_remote_sensor* wfs,
long* nsubs)
{
if (wfs == NULL) {
if (nsubs != NULL) {
*nsubs = 0;
}
return NULL;
} else {
if (nsubs != NULL) {
*nsubs = wfs->config.base.nsubs;
}
return config_get_subs(&wfs->config);
}
return TAO_OK;
}
const char* tao_remote_sensor_get_camera(
......@@ -178,61 +252,158 @@ const char* tao_remote_sensor_get_camera(
}
}
tao_status tao_remote_sensor_copy_config(
tao_remote_sensor_config* dst,
const tao_remote_sensor_config* src)
tao_status tao_remote_sensor_check_config(
const tao_remote_sensor* wfs,
const tao_shackhartmann_config* cfg,
const char* camera_owner,
tao_shmid camera_shmid,
const long* inds,
const tao_subimage* subs)
{
if (dst == NULL || src == NULL) {
if (wfs == NULL || cfg == NULL || inds == NULL || subs == NULL) {
tao_store_error(__func__, TAO_BAD_ADDRESS);
return TAO_ERROR;
}
if (dst != src) {
long ninds = src->base.dims[0]*src->base.dims[1];
long nsubs = src->base.nsubs;
if (dst->max_ninds < ninds || dst->max_nsubs < nsubs) {
tao_store_error(__func__, TAO_BAD_SIZE);
return TAO_ERROR;
}
dst->base = src->base;
dst->camera = src->camera;
memcpy(dst->inds, src->inds, ninds*sizeof(long));
memcpy(TAO_COMPUTED_ADDRESS(dst, dst->subs_offset),
TAO_COMPUTED_ADDRESS(src, src->subs_offset),
nsubs*sizeof(tao_subimage));
if ((camera_owner != NULL && camera_owner[0] != '\0'
&& strncmp(
camera_owner, wfs->config.camera.owner, TAO_OWNER_SIZE) != 0) ||
(camera_shmid != TAO_BAD_SHMID
&& camera_shmid != wfs->config.camera.shmid)) {
// FIXME: Changing the camera is not yet supported.
tao_store_error(__func__, TAO_NOT_YET_IMPLEMENTED);
return TAO_ERROR;
}
long width = wfs->config.camera.width;
long height = wfs->config.camera.height;
if (tao_shackhartmann_check_config(
cfg, inds, subs, width, height) != TAO_OK) {
return TAO_ERROR;
}
long dim1 = cfg->dims[0];
long dim2 = cfg->dims[1];
long ninds = dim1*dim2;
long nsubs = cfg->nsubs;
if (ninds > wfs->max_ninds || nsubs > wfs->max_nsubs) {
tao_store_error(__func__, TAO_OUT_OF_RANGE);
return TAO_ERROR;
}
return TAO_OK;
}
tao_serial tao_remote_sensor_configure(
tao_status tao_remote_sensor_get_config(
const tao_remote_sensor* wfs,
tao_shackhartmann_config* cfg,
char* camera_owner,
tao_shmid* camera_shmid,
long* camera_dims,
long* inds,
long max_ninds,
tao_subimage* subs,
long max_nsubs)
{
// Check arguments.
if (wfs == NULL || cfg == NULL) {
tao_store_error(__func__, TAO_BAD_ADDRESS);
return TAO_ERROR;
}
const tao_shackhartmann_config* src_cfg = &wfs->config.base;
long ninds = src_cfg->dims[0]*src_cfg->dims[1];
long nsubs = src_cfg->nsubs;
if ((inds != NULL && max_ninds < ninds) ||
(subs != NULL && max_nsubs < nsubs)) {
tao_store_error(__func__, TAO_BAD_SIZE);
return TAO_ERROR;
}
// Copy the different parts of the configuration which are requested.
*cfg = *src_cfg;
if (camera_owner != NULL) {
memcpy(camera_owner, wfs->config.camera.owner, TAO_OWNER_SIZE);
}
if (camera_shmid != NULL) {
*camera_shmid = wfs->config.camera.shmid;
}
if (camera_dims != NULL) {
camera_dims[0] = wfs->config.camera.width;
camera_dims[1] = wfs->config.camera.height;
}
if (inds != NULL) {
memcpy(inds, config_get_inds(&wfs->config), ninds*sizeof(inds[0]));
}
if (subs != NULL) {
memcpy(subs, config_get_subs(&wfs->config), nsubs*sizeof(subs[0]));
}
return TAO_OK;
}
tao_status tao_remote_sensor_tune_config(
tao_remote_sensor* wfs,
const tao_remote_sensor_config* cfg,
double secs)
const tao_shackhartmann_config* cfg)
{
tao_store_error(__func__, TAO_NOT_YET_IMPLEMENTED);
return -1;
// Check arguments.
if (wfs == NULL || cfg == NULL) {
tao_store_error(__func__, TAO_BAD_ADDRESS);
return TAO_ERROR;
}
if (memcmp(&wfs->config.base, cfg, sizeof(*cfg)) != 0) {
if (tao_shackhartmann_tune_config(&wfs->config.base, cfg) != TAO_OK) {
return TAO_ERROR;
}
if (tao_remote_sensor_broadcast_condition(wfs) != TAO_OK) {
return TAO_ERROR;
}
}
return TAO_OK;
}
tao_serial tao_remote_sensor_set_camera(
tao_serial tao_remote_sensor_configure(
tao_remote_sensor* wfs,
tao_shmid shmid,
const tao_shackhartmann_config* cfg,
const char* camera_owner,
tao_shmid camera_shmid,
const long* inds,
const tao_subimage* subs,
double secs)
{
if (wfs == NULL) {
if (wfs == NULL || cfg == NULL) {
tao_store_error(__func__, TAO_BAD_ADDRESS);
return TAO_ERROR;
return -1;
}
if (shmid == TAO_BAD_SHMID) {
tao_store_error(__func__, TAO_BAD_SHMID);
return TAO_ERROR;
// Attempt to lock the remote sensor and wait for it becomes ready for a
// new command.
tao_serial num = tao_remote_object_lock_for_command(
tao_remote_object_cast(wfs), TAO_COMMAND_CONFIG, secs);
bool locked = (num > 0);
// If server was ready and resources have been locked, check the settings.
if (num > 0 && tao_remote_sensor_check_config(
wfs, cfg, camera_owner, camera_shmid, inds, subs) != TAO_OK) {
num = -1;
}
// If server was ready and resource has been locked, and configuration is
// valid, opy the different parts of the configuration that were specified.
if (num > 0) {
tao_remote_sensor_config* config2 = secondary_config(wfs);
tao_shackhartmann_config* dst_cfg = &config2->base;
*dst_cfg = *cfg;
long ninds = dst_cfg->dims[0]*dst_cfg->dims[1];
long nsubs = dst_cfg->nsubs;
if (inds != NULL) {
memcpy(config_get_inds(config2), inds, ninds*sizeof(inds[0]));
}
if (subs != NULL) {
memcpy(config_get_subs(config2), subs, nsubs*sizeof(subs[0]));
}
}
// Unlock the resources.
if (locked && tao_remote_sensor_unlock(wfs) != TAO_OK) {
num = -1;
}
const tao_remote_sensor_config* src = secondary_config(wfs);
tao_remote_sensor_config* dst = secondary_config(wfs);
tao_remote_sensor_copy_config(dst, src);
dst->camera.shmid = shmid;
dst->camera.owner[0] = 0;
dst->camera.width = 0;
dst->camera.height = 0;
return tao_remote_sensor_configure(wfs, dst, secs);
return num;
}
static tao_serial send_simple_command(
......@@ -244,7 +415,7 @@ static tao_serial send_simple_command(
// Check arguments.
if (wfs == NULL) {
tao_store_error(func, TAO_BAD_ADDRESS);
return TAO_ERROR;
return -1;
}
if (cmd == TAO_COMMAND_NONE) {
tao_store_error(__func__, TAO_BAD_COMMAND);
......
......@@ -15,6 +15,81 @@
#include "tao-layouts.h"
#include "tao-shackhartmann.h"
static tao_status check_forgetting_factor(
const char* func,
double val)
{
if (!isfinite(val) || val < 0) {
tao_store_error(func, TAO_BAD_FORGETTING_FACTOR);
return TAO_ERROR;
}
return TAO_OK;
}
static tao_status check_restoring_force(
const char* func,
double val)
{
if (!isfinite(val) || val < 0) {
tao_store_error(func, TAO_BAD_RESTORING_FORCE);
return TAO_ERROR;
}
return TAO_OK;
}
static tao_status check_max_excursion(
const char* func,
double val)
{
if (!isnan(val) || val < 0) {
tao_store_error(func, TAO_BAD_MAX_EXCURSION);
return TAO_ERROR;
}
return TAO_OK;
}
static tao_status check_algorithm(
const char* func,
tao_algorithm algorithm)
{
if (algorithm != TAO_CENTER_OF_GRAVITY &&
algorithm != TAO_LINEARIZED_MATCHED_FILTER) {
tao_store_error(func, TAO_BAD_ALGORITHM);
return TAO_ERROR;
}
return TAO_OK;
}
static tao_status check_bounding_box(
const char* func,
const tao_bounding_box* box,
long width,
long height)
{
if (box->xmin < 0 || box->xmin > box->xmax || box->xmax >= width ||
box->ymin < 0 || box->ymin > box->ymax || box->ymax >= height) {
tao_store_error(func, TAO_BAD_BOUNDING_BOX);
return TAO_ERROR;
}
return TAO_OK;
}
static tao_status check_subimage(
const char* func,
const tao_subimage* img,
long width,
long height)
{
if (check_bounding_box(func, &img->box, width, height) != TAO_OK) {
return TAO_ERROR;
}
if (!isfinite(img->ref.x) || !isfinite(img->ref.y)) {
tao_store_error(func, TAO_BAD_REFERENCE);
return TAO_ERROR;
}
return TAO_OK;
}
tao_status tao_shackhartmann_check_config(
const tao_shackhartmann_config* cfg,
const long* inds,
......@@ -42,34 +117,50 @@ tao_status tao_shackhartmann_check_config(
return TAO_ERROR;
}
for (long i = 0; i < nsubs; ++i) {
const tao_bounding_box* box = &subs[i].box;
if (box->xmin < 0 || box->xmin > box->xmax || box->xmax >= width ||
box->ymin < 0 || box->ymin > box->ymax || box->ymax >= height) {
tao_store_error(__func__, TAO_BAD_BOUNDING_BOX);
return TAO_ERROR;
}
const tao_position* ref = &subs[i].ref;
if (!isfinite(ref->x) || !isfinite(ref->y)) {
tao_store_error(__func__, TAO_BAD_REFERENCE);
if (check_subimage(__func__, &subs[i], width, height) != TAO_OK) {
return TAO_ERROR;
}
}
if (!isfinite(cfg->forgetting_factor) || cfg->forgetting_factor < 0) {
tao_store_error(__func__, TAO_BAD_FORGETTING_FACTOR);
if (check_forgetting_factor(__func__, cfg->forgetting_factor) != TAO_OK) {
return TAO_ERROR;
}
if (check_restoring_force(__func__, cfg->restoring_force) != TAO_OK) {
return TAO_ERROR;
}
if (check_max_excursion(__func__, cfg->max_excursion) != TAO_OK) {
return TAO_ERROR;
}
if (check_algorithm(__func__, cfg->algorithm) != TAO_OK) {
return TAO_ERROR;
}
return TAO_OK;
}
tao_status tao_shackhartmann_tune_config(
tao_shackhartmann_config* dst,
const tao_shackhartmann_config* src)
{
if (check_forgetting_factor(__func__, src->forgetting_factor) != TAO_OK) {
return TAO_ERROR;
}
if (check_restoring_force(__func__, src->restoring_force) != TAO_OK) {
return TAO_ERROR;
}
if (!isfinite(cfg->restoring_force) || cfg->restoring_force < 0) {
tao_store_error(__func__, TAO_BAD_RESTORING_FORCE);
if (check_max_excursion(__func__, src->max_excursion) != TAO_OK) {
return TAO_ERROR;
}
if (!isnan(cfg->max_excursion) || cfg->max_excursion < 0) {
tao_store_error(__func__, TAO_BAD_MAX_EXCURSION);
if (check_algorithm(__func__, src->algorithm) != TAO_OK) {
return TAO_ERROR;
}
if (cfg->algo != TAO_CENTER_OF_GRAVITY &&
cfg->algo != TAO_LINEARIZED_MATCHED_FILTER) {
tao_store_error(__func__, TAO_BAD_ALGORITHM);
if (src->algorithm != dst->algorithm ||
src->dims[0] != dst->dims[0] ||
src->dims[1] != dst->dims[1] ||
src->nsubs != dst->nsubs) {
tao_store_error(__func__, TAO_FORBIDDEN_CHANGE);
return TAO_ERROR;
}
dst->forgetting_factor = src->forgetting_factor;
dst->restoring_force = src->restoring_force;
dst->max_excursion = src->max_excursion;
return TAO_OK;
}
......@@ -120,24 +120,25 @@ typedef enum tao_error_code_ {
TAO_CORRUPTED = -44,///< Corrupted structure
TAO_DESTROYED = -45,///< Resource has been destroyed
TAO_EXHAUSTED = -46,///< Resource exhausted
TAO_MISSING_SEPARATOR = -47,///< Separator missing
TAO_MUST_RESET = -48,///< Device must be reset
TAO_NOT_ACQUIRING = -49,///< Acquisition not started
TAO_NOT_FOUND = -50,///< Item not found
TAO_NOT_LOCKED = -51,///< Resource not locked by caller
TAO_NOT_READY = -52,///< Device not ready
TAO_NOT_RUNNING = -53,///< Server or thread is not running
TAO_NOT_YET_IMPLEMENTED = -54,///< Not yet implemented
TAO_NO_DATA = -55,///< No data available
TAO_NO_FITS_SUPPORT = -56,///< Compiled with no FITS support
TAO_OUT_OF_RANGE = -57,///< Out of range argument
TAO_OVERWRITTEN = -58,///< Contents has been overwritten
TAO_SYSTEM_ERROR = -59,///< Unknown system error
TAO_UNCLOSED_STRING = -60,///< Unclosed string
TAO_UNREADABLE = -61,///< Not readable
TAO_UNRECOVERABLE = -62,///< Unrecoverable error
TAO_UNSUPPORTED = -63,///< Unsupported feature
TAO_UNWRITABLE = -64,///< Not writable
TAO_FORBIDDEN_CHANGE = -47,///< Forbidden change of parameter(s)
TAO_MISSING_SEPARATOR = -48,///< Separator missing
TAO_MUST_RESET = -49,///< Device must be reset
TAO_NOT_ACQUIRING = -50,///< Acquisition not started
TAO_NOT_FOUND = -51,///< Item not found
TAO_NOT_LOCKED = -52,///< Resource not locked by caller
TAO_NOT_READY = -53,///< Device not ready
TAO_NOT_RUNNING = -54,///< Server or thread is not running
TAO_NOT_YET_IMPLEMENTED = -55,///< Not yet implemented
TAO_NO_DATA = -56,///< No data available
TAO_NO_FITS_SUPPORT = -57,///< Compiled with no FITS support
TAO_OUT_OF_RANGE = -58,///< Out of range argument
TAO_OVERWRITTEN = -59,///< Contents has been overwritten
TAO_SYSTEM_ERROR = -60,///< Unknown system error
TAO_UNCLOSED_STRING = -61,///< Unclosed string
TAO_UNREADABLE = -62,///< Not readable
TAO_UNRECOVERABLE = -63,///< Unrecoverable error
TAO_UNSUPPORTED = -64,///< Unsupported feature
TAO_UNWRITABLE = -65,///< Not writable
} tao_error_code;
/**
......
......@@ -66,15 +66,6 @@ typedef struct tao_remote_sensor_dataframe_ {
tao_shackhartmann_data data[1];
} tao_remote_sensor_dataframe;
extern tao_status tao_remote_sensor_copy_config(
tao_remote_sensor_config* dst,
const tao_remote_sensor_config* src);
extern tao_serial tao_remote_sensor_configure(
tao_remote_sensor* wfs,
const tao_remote_sensor_config* cfg,
double secs);
TAO_END_DECLS
#endif // TAO_REMOTE_SENSORS_PRIVATE__H_
......@@ -527,6 +527,38 @@ extern tao_state tao_remote_sensor_get_state(
extern int tao_remote_sensor_is_alive(
const tao_remote_sensor* wfs);
// Getters.
extern long tao_remote_sensor_get_ninds(
const tao_remote_sensor* wfs);
extern long tao_remote_sensor_get_nsubs(
const tao_remote_sensor* wfs);
extern long tao_remote_sensor_get_max_ninds(
const tao_remote_sensor* wfs);
extern long tao_remote_sensor_get_max_nsubs(
const tao_remote_sensor* wfs);
extern const char* tao_remote_sensor_get_camera_owner(
const tao_remote_sensor* wfs);
extern long tao_remote_sensor_get_camera_width(
const tao_remote_sensor* wfs);
extern long tao_remote_sensor_get_camera_height(
const tao_remote_sensor* wfs);
extern tao_shmid tao_remote_sensor_get_camera_shmid(
const tao_remote_sensor* wfs);
extern const long* tao_remote_sensor_get_inds(
const tao_remote_sensor* wfs,