Commit a46d84a6 authored by Pavel Vainerman's avatar Pavel Vainerman

Исправлены ошибки в классе Calibration, связанные с неправильной обработкой…

Исправлены ошибки в классе Calibration, связанные с неправильной обработкой отрицательных диапазонов.
parent 5e03f449
......@@ -3,7 +3,7 @@
Name: libuniset
Version: 1.0
Release: alt38
Release: alt39
Summary: UniSet - library for building distributed industrial control systems
License: GPL
Group: Development/C++
......
......@@ -175,4 +175,14 @@
</messages>
<!-- <xi:include href="testID.xml"/> -->
<!-- <xi:include href="testIDnon-exist.xml"/> -->
<Calibrations name="Calibrations">
<diagram name="testcal">
<point x="-100" y="-60"/>
<point x="-50" y="-20"/>
<point x="0" y="0"/>
<point x="50" y="20"/>
<point x="100" y="60"/>
</diagram>
</Calibrations>
</UNISETPLC>
......@@ -194,7 +194,8 @@ AC_CONFIG_FILES([Makefile
extensions/UNet2/libUniSetUNet2.pc
extensions/SharedMemory/Makefile
extensions/SharedMemory/libUniSetSharedMemory.pc
extensions/SharedMemoryPlus/Makefile])
extensions/SharedMemoryPlus/Makefile
extensions/tests/Makefile])
AC_OUTPUT
......
......@@ -4,7 +4,7 @@
if HAVE_EXTENTIONS
SUBDIRS = lib include SharedMemory IOControl RTUExchange LogicProcessor \
ModbusSlave MBTCPMaster SMViewer UniNetwork UNet2 DBServer-MySQL
ModbusSlave MBTCPMaster SMViewer UniNetwork UNet2 DBServer-MySQL tests
#SMDBServer
#SharedMemoryPlus
#UDPExchange
......
#ifndef Calibration_H_
#define Calibration_H_
// -----------------------------------------------------------------------------
#include <cmath>
#include <string>
#include <list>
#include <ostream>
// -----------------------------------------------------------------------------
/*!
Класс позволяющий загружать калибровочные
характеристики из конфигурационного файла
и получать по ней точки.
\code
C, калиброванное значение
^
|
|
|
|
-------->
R(raw value), сырое значение
\endcode
*/
class Calibration
{
public:
Calibration();
Calibration( const std::string name, const std::string confile="calibration.xml" );
Calibration( xmlNode* node );
~Calibration();
/*! выход за границы диапазона */
static const int outOfRange=-1;
/*!
Получение калиброванного значения
\param raw - сырое значение
\return Возвращает калиброванное
*/
long getValue( long raw );
/*!
Получение сырого значения по калиброванному
*/
long getRawValue( long cal );
/*! построение характеристрики из конф. файла
\param name - название характеристики в файле
\param confile - файл содержащий данные
\param node - если node!=0, то используется этот узел...
*/
void build( const std::string name, const std::string confile, xmlNode* node=0 );
/*! Тип для хранения текущего значения */
typedef float TypeOfValue;
/*! преобразование типа для хранения
в тип для аналоговых датчиков
*/
inline long tRound( const TypeOfValue& val )
{
return lround(val);
}
friend std::ostream& operator<<(std::ostream& os, Calibration& c );
friend std::ostream& operator<<(std::ostream& os, Calibration* c );
protected:
/*! точка характеристики */
struct Point
{
Point( TypeOfValue _x, TypeOfValue _y ):
x(_x),y(_y){}
TypeOfValue x;
TypeOfValue y;
inline bool operator < ( const Point& p ) const
{
return ( x < p.x );
}
};
/*! участок характеристики */
class Part
{
public:
Part( Point& pleft, Point& pright );
~Part(){};
/*! находится ли точка на данном участке */
bool check( Point& p );
/*! находится ли точка на данном участке по X */
bool checkX( TypeOfValue x );
/*! находится ли точка на данном участке по Y */
bool checkY( TypeOfValue y );
// функции могут вернуть OutOfRange
TypeOfValue getY( TypeOfValue x ); /*!< получить значение Y */
TypeOfValue getX( TypeOfValue y ); /*!< получить значение X */
TypeOfValue calcY( TypeOfValue x ); /*!< расчитать значение для x */
TypeOfValue calcX( TypeOfValue y ); /*!< расчитать значение для y */
inline bool operator < ( const Part& p ) const
{
return (p_right < p.p_right);
}
inline Point leftPoint(){ return p_left; }
inline Point rightPoint(){ return p_right; }
inline TypeOfValue getK(){ return k; } /*!< получить коэффициент наклона */
inline TypeOfValue left_x(){ return p_left.x; }
inline TypeOfValue left_y(){ return p_left.y; }
inline TypeOfValue right_x(){ return p_right.x; }
inline TypeOfValue right_y(){ return p_right.y; }
protected:
Point p_left; /*!< левый предел участка */
Point p_right; /*!< правый предел участка */
TypeOfValue k; /*!< коэффициент наклона */
};
// список надо отсортировать по x!
typedef std::list<Part> PartsList;
private:
PartsList plist;
std::string myname;
};
// -----------------------------------------------------------------------------
#endif // Calibration_H_
// -----------------------------------------------------------------------------
......@@ -23,15 +23,11 @@ Calibration::Part::Part( Point& pleft, Point& pright ):
// вычисление коэффициента наклона (один раз в конструкторе)
// k = (y2-y1)/(x2-x1)
if( (p_right.y==0 && p_left.y==0) || (p_right.x==0 && p_left.x==0) )
k=0;
k = 0;
else
k = ( p_right.y - p_left.y ) / ( p_right.x - p_left.x );
}
// ----------------------------------------------------------------------------
// чтобы участки между собой не пересекались
// нижняя граница (по x и y)
// не входит в диапазон
// (т.е. как бы относится к предыдущему участку)
bool Calibration::Part::check( Point& p )
{
return ( checkX(p.x) && checkY(p.y) );
......@@ -39,14 +35,14 @@ bool Calibration::Part::check( Point& p )
bool Calibration::Part::checkX( TypeOfValue x )
{
if( x <= p_left.x || x > p_right.x )
if( x < p_left.x || x > p_right.x )
return false;
return true;
}
bool Calibration::Part::checkY( TypeOfValue y )
{
if( y <= p_left.y || y > p_right.y )
if( y < p_left.y || y > p_right.y )
return false;
return true;
......@@ -58,6 +54,12 @@ Calibration::TypeOfValue Calibration::Part::getY( TypeOfValue x )
if( !checkX(x) )
return Calibration::outOfRange;
if( x == left_x() )
return left_y();
if( x == right_x() )
return right_y();
return calcY(x);
}
// ----------------------------------------------------------------------------
......@@ -66,6 +68,12 @@ Calibration::TypeOfValue Calibration::Part::getX( TypeOfValue y )
if( !checkY(y) )
return Calibration::outOfRange;
if( y == left_y() )
return left_x();
if( y == right_y() )
return right_x();
return calcX(y);
}
// ----------------------------------------------------------------------------
......@@ -143,7 +151,7 @@ void Calibration::build( const string name, const string confile, xmlNode* root
throw Exception(err.str());
}
bool prev = true;
bool prev = false;
Point prev_point(0,0);
for(;it;it.goNext())
{
......@@ -160,11 +168,20 @@ void Calibration::build( const string name, const string confile, xmlNode* root
// cout << myname << "(Calibration::build):"
// << "\tadd x=" << p.x << " y=" << p.y << endl;
Part pt(prev_point,p);
plist.push_back(pt);
if( prev )
{
// cout << myname << "(Calibration::build):"
// << "\tadd x=" << p.x << " y=" << p.y
// << " prev.x=" << prev_point.x
// << " prev.y=" << prev_point.y
// << endl;
Part pt(prev_point,p);
plist.push_back(pt);
}
else
prev = true;
prev_point = p;
prev = false;
}
plist.sort();
......@@ -176,13 +193,18 @@ void Calibration::build( const string name, const string confile, xmlNode* root
}
}
// ----------------------------------------------------------------------------
long Calibration::getValue( long raw )
long Calibration::getValue( long raw, bool crop_raw )
{
PartsList::iterator it=plist.begin();
// если l левее первого отрезка то берём первую точку...
if( raw < it->left_x() )
return it->left_x();
// если x левее первого отрезка то берём первую точку...
if( raw <= it->left_x() )
{
if( crop_raw )
return it->left_y();
return it->calcY(raw);
}
for( ; it!=plist.end(); ++it )
{
......@@ -195,9 +217,10 @@ long Calibration::getValue( long raw )
it = plist.end();
it--;
TypeOfValue q = it->calcY(raw);
if( crop_raw && raw >= it->right_x() )
return it->right_y();
return ( q<0 ) ? 0 : q;
return it->calcY(raw);
}
// ----------------------------------------------------------------------------
long Calibration::getRawValue( long cal )
......@@ -208,6 +231,7 @@ long Calibration::getRawValue( long cal )
if( q != outOfRange )
return tRound(q);
}
return outOfRange;
}
// ----------------------------------------------------------------------------
......@@ -216,7 +240,9 @@ std::ostream& operator<<( std::ostream& os, Calibration& c )
os << "*******************" << endl;
for( Calibration::PartsList::iterator it=c.plist.begin(); it!=c.plist.end(); ++it )
{
os << "[" << it->leftPoint().x << ": " << it->rightPoint().x << " ] --> " << it->leftPoint().y << endl;
os << "[" << it->leftPoint().x << " : " << it->rightPoint().x << " ] --> ["
<< it->leftPoint().y << " : " << it->rightPoint().y << " ]"
<< endl;
}
os << "*******************" << endl;
return os;
......@@ -227,7 +253,9 @@ std::ostream& operator<<( std::ostream& os, Calibration* c )
os << "*******************" << endl;
for( Calibration::PartsList::iterator it=c->plist.begin(); it!=c->plist.end(); ++it )
{
os << "[" << it->leftPoint().x << ": " << it->rightPoint().x << " ] --> " << it->leftPoint().y << endl;
os << "[" << it->leftPoint().x << " : " << it->rightPoint().x << " ] --> ["
<< it->leftPoint().y << " : " << it->rightPoint().y << " ]"
<< endl;
}
os << "*******************" << endl;
......
noinst_PROGRAMS = calibration
calibration_SOURCES = calibration.cc
calibration_LDADD = $(top_builddir)/lib/libUniSet.la $(top_builddir)/extensions/lib/libUniSetExtensions.la
calibration_CPPFLAGS = -I$(top_builddir)/include -I$(top_builddir)/extensions/include
#! /bin/sh
# calibration - temporary wrapper script for .libs/calibration
# Generated by ltmain.sh - GNU libtool 1.5.26 (1.1220.2.493 2008/02/01 16:58:18)
#
# The calibration program cannot be directly executed until all the libtool
# libraries that it depends on are installed.
#
# This wrapper script should never be moved out of the build directory.
# If it is, it will not operate correctly.
# Sed substitution that helps us do robust quoting. It backslashifies
# metacharacters that are still active within double-quoted strings.
Xsed='/bin/sed -e 1s/^X//'
sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
# Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
else
case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
fi
BIN_SH=xpg4; export BIN_SH # for Tru64
DUALCASE=1; export DUALCASE # for MKS sh
# The HP-UX ksh and POSIX shell print the target directory to stdout
# if CDPATH is set.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
relink_command="(cd /home/pv/Projects/uniset/extensions/tests; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=\"/usr/share/eterbuild/functions/commands:/usr/lib/kde4/bin:/home/pv/bin:/usr/local/bin:/usr/bin:/bin:/usr/games:/usr/X11R6/bin:/usr/lib/kde3/bin:/usr/lib/kde3/bin:/usr/lib/kde3/bin:/usr/lib/kde3/bin:/usr/lib/kde3/bin:/usr/lib/kde3/bin\"; export PATH; g++ -pedantic -Wall -funsigned-char -g -D_GNU_SOURCE -D__x86__ -D__linux__ -D__OSVERSION__=2 -I/usr/include/libxml2 -I../../include -o \$progdir/\$file calibration-calibration.o -lomniORB4 -lomnithread -lxml2 ../../lib/.libs/libUniSet.so ../../extensions/lib/.libs/libUniSetExtensions.so -Wl,--rpath -Wl,/home/pv/Projects/uniset/lib/.libs -Wl,--rpath -Wl,/home/pv/Projects/uniset/extensions/lib/.libs ) "
# This environment variable determines our operation mode.
if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
# install mode needs the following variable:
notinst_deplibs=' ../../lib/libUniSet.la ../../extensions/lib/libUniSetExtensions.la'
else
# When we are sourced in execute mode, $file and $echo are already set.
if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
echo="echo"
file="$0"
# Make sure echo works.
if test "X$1" = X--no-reexec; then
# Discard the --no-reexec flag, and continue.
shift
elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
# Yippee, $echo works!
:
else
# Restart under the correct shell, and then maybe $echo will work.
exec /bin/sh "$0" --no-reexec ${1+"$@"}
fi
fi
# Find the directory that this script lives in.
thisdir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
test "x$thisdir" = "x$file" && thisdir=.
# Follow symbolic links until we get to the real thisdir.
file=`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
while test -n "$file"; do
destdir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`
# If there was a directory component, then change thisdir.
if test "x$destdir" != "x$file"; then
case "$destdir" in
[\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;;
*) thisdir="$thisdir/$destdir" ;;
esac
fi
file=`$echo "X$file" | $Xsed -e 's%^.*/%%'`
file=`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
done
# Try to get the absolute directory name.
absdir=`cd "$thisdir" && pwd`
test -n "$absdir" && thisdir="$absdir"
program=lt-'calibration'
progdir="$thisdir/.libs"
if test ! -f "$progdir/$program" || \
{ file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /bin/sed 1q`; \
test "X$file" != "X$progdir/$program"; }; then
file="$$-$program"
if test ! -d "$progdir"; then
mkdir "$progdir"
else
rm -f "$progdir/$file"
fi
# relink executable if necessary
if test -n "$relink_command"; then
if relink_command_output=`eval $relink_command 2>&1`; then :
else
echo "$relink_command_output" >&2
rm -f "$progdir/$file"
exit 1
fi
fi
mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
{ rm -f "$progdir/$program";
mv -f "$progdir/$file" "$progdir/$program"; }
rm -f "$progdir/$file"
fi
if test -f "$progdir/$program"; then
if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then
# Run the actual program with our arguments.
exec "$progdir/$program" ${1+"$@"}
$echo "$0: cannot exec $program $*"
exit 1
fi
else
# The program doesn't exist.
$echo "$0: error: \`$progdir/$program' does not exist" 1>&2
$echo "This script is just a wrapper for $program." 1>&2
echo "See the libtool documentation for more information." 1>&2
exit 1
fi
fi
#include <iostream>
#include "Exceptions.h"
#include "UniXML.h"
#include "UniSetTypes.h"
#include "Configuration.h"
#include "Extensions.h"
#include "Calibration.h"
using namespace std;
using namespace UniSetTypes;
using namespace UniSetExtensions;
int main( int argc, const char** argv )
{
try
{
uniset_init(argc,argv,"test.xml");
Calibration* cal = buildCalibrationDiagram("testcal");
cout << "diagram: " << cal << endl;
cout << "-1500 --> " << cal->getValue(-1500) << endl;
cout << "-100 --> " << cal->getValue(-100) << endl;
cout << " -75 --> " << cal->getValue(-75) << endl;
cout << " -50 --> " << cal->getValue(-50) << endl;
cout << " -25 --> " << cal->getValue(-25) << endl;
cout << " -0 --> " << cal->getValue(0) << endl;
cout << " 25 --> " << cal->getValue(25) << endl;
cout << " 50 --> " << cal->getValue(50) << endl;
cout << " 75 --> " << cal->getValue(75) << endl;
cout << " 100 --> " << cal->getValue(100) << endl;
cout << " 1500 --> " << cal->getValue(1500) << endl;
cout << endl << " RAW VALUE.." << endl;
cout << "-1220 --> " << cal->getRawValue(-1220) << endl;
cout << " -60 --> " << cal->getRawValue(-60) << endl;
cout << " -40 --> " << cal->getRawValue(-40) << endl;
cout << " -20 --> " << cal->getRawValue(-20) << endl;
cout << " 0 --> " << cal->getRawValue(0) << endl;
cout << " 20 --> " << cal->getRawValue(20) << endl;
cout << " 40 --> " << cal->getRawValue(40) << endl;
cout << " 60 --> " << cal->getRawValue(60) << endl;
cout << " 1500 --> " << cal->getRawValue(1500) << endl;
return 0;
}
catch( Exception& ex )
{
cerr << "(unetexchange): " << ex << std::endl;
}
catch(...)
{
cerr << "(unetexchange): catch ..." << std::endl;
}
return 1;
}
../../conf/test.xml
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment