pastie/robot.cpp

262 lines
4.1 KiB
C++

#include <vector>
#include "robot.h"
#include "mainwindow.h"
extern MainWindow *mwindow;
GCode::GCode(QByteArray c) :
cmd(c)
{ }
GCode & GCode::arg(char param, int v)
{
QByteArray arg;
arg.push_back(param);
arg.push_back(QByteArray::number(v));
args.push_back(arg);
}
GCode & GCode::arg(char param, double v)
{
QByteArray arg;
arg += param;
arg += QByteArray::number(v);
args += arg;
}
GCode::operator QByteArray()
{
QByteArray ret;
ret += cmd;
if (args.size()) {
ret += " ";
for (QByteArray arg : args) {
ret += arg;
if (arg != args.last())
ret += " ";
}
}
return ret;
}
/************ GCode Factories ***************/
GCode GCode::moveZ(double z)
{
return GCode("G0")
.arg('Z', z);
}
GCode GCode::moveXY(Point2f pos)
{
return GCode("G0")
.arg('X', pos.x)
.arg('Y', pos.y);
}
GCode GCode::move(Point3f pos)
{
return GCode("G0")
.arg('X', pos.x)
.arg('Y', pos.y)
.arg('Z', pos.z);
}
GCode GCode::home()
{
return GCode("G28");
}
GCode GCode::calibrate()
{
return GCode("G29");
}
GCode GCode::stop()
{
return GCode("M124");
}
GCode GCode::comment(QString c)
{
// return GCode(";" + c);
}
/****************** Robot *******************/
Robot::Robot(Pattern *pa, PathPlanner *pp) :
pattern(pa),
planner(pp)
{ }
void Robot::connect(QHostAddress addr, int port, QString key)
{
Q_UNUSED(addr)
Q_UNUSED(port)
Q_UNUSED(key)
}
void Robot::save(QString fileName)
{
QFile file(fileName);
file.open(QFile::WriteOnly);
if (!file.isWritable()) {
qCritical() << "Failed to open file: " << fileName;
return;
}
processPath();
while (!queue.isEmpty()) {
QByteArray gco = queue.dequeue();
file.write(gco);
qDebug() << "GCode: " << gco;
}
file.close();
}
void Robot::home()
{
// FIXME: send GCode to OctoPrint
}
void Robot::calibrate()
{
// FIXME: send GCode to OctoPrint
}
void Robot::start()
{
// FIXME: send GCode to OctoPrint
}
void Robot::stop()
{
// FIXME: send GCode to OctoPrint
}
void Robot::moveDelta(Point3f delta)
{
queue << GCode("G91");
queue << GCode::move(delta);
queue << GCode("G90");
}
void Robot::prolog()
{
queue << GCode::home();
queue << GCode::calibrate();
}
void Robot::epilog()
{
queue << GCode::home();
}
void Robot::processPath()
{
Image *img = mwindow->getCurrentImage();
if (!img)
return;
PathResult *path = dynamic_cast<PathResult*>(img->getResult(planner));
if (!path)
return;
queue.clear();
prolog();
int i = 0;
double distance = 0;
double time = 0;
for (Pad pad : *path) {
Point2f p = map(pad.center);
/* Check Bed Bounds */
if (bedShape == BED_RECTANGULAR) {
if (p.x > bedSize.width ||
p.y > bedSize.height ||
p.x < 0 ||
p.y < 0
) {
qCritical() << "Pad outside of bed: " << toQt(p);
return;
}
}
else if (bedShape == BED_CIRCULAR) {
if (pow(p.x / bedSize.width, 2) + pow(p.y / bedSize.height, 2) > 1) {
qCritical() << "Pad outside of bed: " << toQt(p);
return;
}
}
queue << GCode::comment(QString("Pad %1: x=%2, y=%3").arg(i).arg(pad.center.x).arg(pad.center.y));
queue << GCode::moveZ(zOffset + zSwing);
queue << GCode::moveXY(p);
queue << GCode::moveZ(zOffset);
i++;
}
epilog();
qDebug() << "Finished G-Code processing: distance = " << distance << "time = " << time;
}
Point2f Robot::map(Point2f p)
{
//Point2f a = affine * Point3f(p.x, p.y, 1);
//return Point3f(a.x, a.y, zOffset);
}
Point2f Robot::unmap(Point2f p)
{
//return affine.inv() * Point2f(p.x, p.y);
}
void Robot::updateTransformation()
{
std::vector<Point2f> src(calibPoints, calibPoints+3);
std::vector<Point2f> dst;
Image *img = mwindow->getCurrentImage();
if (!img)
return;
PatternResult *pat = dynamic_cast<PatternResult*>(img->getResult(pattern));
if (!pat)
return;
dst = pat->getPoints();
qDebug() << "Mapping: " << toQt(src[0]) << "=>" << toQt(dst[0]) << ", "
<< toQt(src[1]) << "=>" << toQt(dst[1]) << ", "
<< toQt(src[2]) << "=>" << toQt(dst[2]);
affine = getAffineTransform(src, dst);
qDebug() << "Affine: " << toQTransform(affine);
}
void Robot::setCalibPoints(Point2f p[3])
{
for (int i = 0; i < 3; i++)
calibPoints[i] = p[i];
updateTransformation();
}