rosaria/Legacy/Aria/src/ArForbiddenRangeDevice.cpp
2021-12-16 14:07:59 +00:00

220 lines
6.8 KiB
C++

/*
Adept MobileRobots Robotics Interface for Applications (ARIA)
Copyright (C) 2004, 2005 ActivMedia Robotics LLC
Copyright (C) 2006, 2007, 2008, 2009, 2010 MobileRobots Inc.
Copyright (C) 2011, 2012, 2013 Adept Technology
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
If you wish to redistribute ARIA under different terms, contact
Adept MobileRobots for information about a commercial version of ARIA at
robots@mobilerobots.com or
Adept MobileRobots, 10 Columbia Drive, Amherst, NH 03031; +1-603-881-7960
*/
#include "ArExport.h"
#include "ariaOSDef.h"
#include "ArRobot.h"
#include "ariaUtil.h"
#include "ArForbiddenRangeDevice.h"
/**
This will take a map and then convert the forbidden lines into
range device readings every cycle.
It doesn't add any data for drawing the current range device
readings since the lines themselves show up in the map.
@param armap the map to use forbidden lines from
@param distanceIncrement how many mm to increment search in sensor readings for forbidden lines
@param maxRange how far out to look total
@param name the name of the device
**/
AREXPORT ArForbiddenRangeDevice::ArForbiddenRangeDevice(
ArMapInterface *armap, double distanceIncrement, unsigned int maxRange,
const char *name) :
ArRangeDevice(INT_MAX, 0, name, maxRange, 0, 0, 0, true),
myDataMutex(),
myMap(armap),
myDistanceIncrement(distanceIncrement),
mySegments(),
myProcessCB(this, &ArForbiddenRangeDevice::processReadings),
myMapChangedCB(this, &ArForbiddenRangeDevice::processMap) ,
myIsEnabled(true),
myEnableCB(this, &ArForbiddenRangeDevice::enable),
myDisableCB(this, &ArForbiddenRangeDevice::disable)
{
myDataMutex.setLogName("ArForbiddenRangeDevice::myDataMutex");
myMapChangedCB.setName("ArForbiddenRangeDevice");
}
AREXPORT ArForbiddenRangeDevice::~ArForbiddenRangeDevice()
{
}
AREXPORT void ArForbiddenRangeDevice::processMap(void)
{
std::list<ArMapObject *>::const_iterator it;
ArMapObject *obj;
myDataMutex.lock();
ArUtil::deleteSet(mySegments.begin(), mySegments.end());
mySegments.clear();
for (it = myMap->getMapObjects()->begin();
it != myMap->getMapObjects()->end();
it++)
{
obj = (*it);
if (strcmp(obj->getType(), "ForbiddenLine") == 0 &&
obj->hasFromTo())
{
mySegments.push_back(new ArLineSegment(obj->getFromPose(),
obj->getToPose()));
}
if (strcmp(obj->getType(), "ForbiddenArea") == 0 &&
obj->hasFromTo())
{
double angle = obj->getPose().getTh();
double sa = ArMath::sin(angle);
double ca = ArMath::cos(angle);
double fx = obj->getFromPose().getX();
double fy = obj->getFromPose().getY();
double tx = obj->getToPose().getX();
double ty = obj->getToPose().getY();
ArPose P0((fx*ca - fy*sa), (fx*sa + fy*ca));
ArPose P1((tx*ca - fy*sa), (tx*sa + fy*ca));
ArPose P2((tx*ca - ty*sa), (tx*sa + ty*ca));
ArPose P3((fx*ca - ty*sa), (fx*sa + ty*ca));
mySegments.push_back(new ArLineSegment(P0, P1));
mySegments.push_back(new ArLineSegment(P1, P2));
mySegments.push_back(new ArLineSegment(P2, P3));
mySegments.push_back(new ArLineSegment(P3, P0));
}
}
myDataMutex.unlock();
}
AREXPORT void ArForbiddenRangeDevice::processReadings(void)
{
ArPose intersection;
std::list<ArLineSegment *>::iterator it;
lockDevice();
myDataMutex.lock();
myCurrentBuffer.beginRedoBuffer();
if (!myIsEnabled)
{
myCurrentBuffer.endRedoBuffer();
myDataMutex.unlock();
unlockDevice();
return;
}
ArLineSegment *segment;
ArPose start;
double startX;
double startY;
ArPose end;
double angle;
double length;
double gone;
double sin;
double cos;
double atX;
double atY;
double robotX = myRobot->getX();
double robotY = myRobot->getY();
double max = (double) myMaxRange;
double maxSquared = (double) myMaxRange * (double) myMaxRange;
ArTime startingTime;
//startingTime.setToNow();
// now see if the end points of the segments are too close to us
for (it = mySegments.begin(); it != mySegments.end(); it++)
{
segment = (*it);
// if either end point or some perpindicular point is close to us
// add the line's data
if (ArMath::squaredDistanceBetween(
segment->getX1(), segment->getY1(),
myRobot->getX(), myRobot->getY()) < maxSquared ||
ArMath::squaredDistanceBetween(
segment->getX2(), segment->getY2(),
myRobot->getX(), myRobot->getY()) < maxSquared ||
segment->getPerpDist(myRobot->getPose()) < max)
{
start.setPose(segment->getX1(), segment->getY1());
end.setPose(segment->getX2(), segment->getY2());
angle = start.findAngleTo(end);
cos = ArMath::cos(angle);
sin = ArMath::sin(angle);
startX = start.getX();
startY = start.getY();
length = start.findDistanceTo(end);
// first put in the start point if we should
if (ArMath::squaredDistanceBetween(
startX, startY, robotX, robotY) < maxSquared)
myCurrentBuffer.redoReading(start.getX(), start.getY());
// now walk the length of the line and see if we should put the points in
for (gone = 0; gone < length; gone += myDistanceIncrement)
{
atX = startX + gone * cos;
atY = startY + gone * sin;
if (ArMath::squaredDistanceBetween(
atX, atY, robotX, robotY) < maxSquared)
myCurrentBuffer.redoReading(atX, atY);
}
// now check the end point
if (end.squaredFindDistanceTo(myRobot->getPose()) < maxSquared)
myCurrentBuffer.redoReading(end.getX(), end.getY());
}
}
myDataMutex.unlock();
// and we're done
myCurrentBuffer.endRedoBuffer();
unlockDevice();
//printf("%d\n", startingTime.mSecSince());
}
AREXPORT void ArForbiddenRangeDevice::setRobot(ArRobot *robot)
{
myRobot = robot;
if (myRobot != NULL)
myRobot->addSensorInterpTask(myName.c_str(), 20, &myProcessCB);
ArRangeDevice::setRobot(robot);
myMap->lock();
myMap->addMapChangedCB(&myMapChangedCB);
processMap();
myMap->unlock();
}
AREXPORT void ArForbiddenRangeDevice::enable(void)
{
myDataMutex.lock();
myIsEnabled = true;
myDataMutex.unlock();
}
AREXPORT void ArForbiddenRangeDevice::disable(void)
{
myDataMutex.lock();
myIsEnabled = false;
myDataMutex.unlock();
}