WaypointList.cc 9.95 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/*=====================================================================

PIXHAWK Micro Air Vehicle Flying Robotics Toolkit

(c) 2009, 2010 PIXHAWK PROJECT  <http://pixhawk.ethz.ch>

This file is part of the PIXHAWK project

    PIXHAWK 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 3 of the License, or
    (at your option) any later version.

    PIXHAWK 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 PIXHAWK. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/

/**
 * @file
 *   @brief Waypoint list widget
 *
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *   @author Benjamin Knecht <mavteam@student.ethz.ch>
30
 *   @author Petri Tanskanen <mavteam@student.ethz.ch>
pixhawk's avatar
pixhawk committed
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
 *
 */

#include "WaypointList.h"
#include "ui_WaypointList.h"
#include <UASInterface.h>
#include <UASManager.h>
#include <QDebug>
#include <QFileDialog>

WaypointList::WaypointList(QWidget *parent, UASInterface* uas) :
        QWidget(parent),
        uas(NULL),
        m_ui(new Ui::WaypointList)
{
    m_ui->setupUi(this);

    listLayout = new QVBoxLayout(m_ui->listWidget);
    listLayout->setSpacing(6);
    listLayout->setMargin(0);
    listLayout->setAlignment(Qt::AlignTop);
    m_ui->listWidget->setLayout(listLayout);

    wpViews = QMap<Waypoint*, WaypointView*>();

    this->uas = NULL;

    // ADD WAYPOINT
    // Connect add action, set right button icon and connect action to this class
    connect(m_ui->addButton, SIGNAL(clicked()), m_ui->actionAddWaypoint, SIGNAL(triggered()));
    connect(m_ui->actionAddWaypoint, SIGNAL(triggered()), this, SLOT(add()));

    // SEND WAYPOINTS
    connect(m_ui->transmitButton, SIGNAL(clicked()), this, SLOT(transmit()));

66
    // REQUEST WAYPOINTS
67
    connect(m_ui->readButton, SIGNAL(clicked()), this, SLOT(read()));
68

pixhawk's avatar
pixhawk committed
69 70 71 72 73 74
    // SAVE/LOAD WAYPOINTS
    connect(m_ui->saveButton, SIGNAL(clicked()), this, SLOT(saveWaypoints()));
    connect(m_ui->loadButton, SIGNAL(clicked()), this, SLOT(loadWaypoints()));

    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setUAS(UASInterface*)));

75 76 77
    // STATUS LABEL
    updateStatusLabel("");

pixhawk's avatar
pixhawk committed
78 79 80 81 82 83 84 85 86
    // SET UAS AFTER ALL SIGNALS/SLOTS ARE CONNECTED
    setUAS(uas);
}

WaypointList::~WaypointList()
{
    delete m_ui;
}

87 88 89 90 91
void WaypointList::updateStatusLabel(const QString &string)
{
    m_ui->statusLabel->setText(string);
}

pixhawk's avatar
pixhawk committed
92 93 94 95 96
void WaypointList::setUAS(UASInterface* uas)
{
    if (this->uas == NULL && uas != NULL)
    {
        this->uas = uas;
pixhawk's avatar
pixhawk committed
97 98

        connect(&uas->getWaypointManager(), SIGNAL(updateStatusString(const QString &)),                                this, SLOT(updateStatusLabel(const QString &)));
pixhawk's avatar
pixhawk committed
99
        connect(&uas->getWaypointManager(), SIGNAL(waypointUpdated(int,quint16,double,double,double,double,bool,bool,double,int)), this, SLOT(setWaypoint(int,quint16,double,double,double,double,bool,bool,double,int)));
pixhawk's avatar
pixhawk committed
100 101
        connect(&uas->getWaypointManager(), SIGNAL(currentWaypointChanged(quint16)),                                    this, SLOT(currentWaypointChanged(quint16)));

102 103 104
        connect(this, SIGNAL(sendWaypoints(const QVector<Waypoint*> &)),    &uas->getWaypointManager(), SLOT(sendWaypoints(const QVector<Waypoint*> &)));
        connect(this, SIGNAL(requestWaypoints()),                           &uas->getWaypointManager(), SLOT(requestWaypoints()));
        connect(this, SIGNAL(clearWaypointList()),                          &uas->getWaypointManager(), SLOT(clearWaypointList()));
pixhawk's avatar
pixhawk committed
105 106 107
    }
}

pixhawk's avatar
pixhawk committed
108
void WaypointList::setWaypoint(int uasId, quint16 id, double x, double y, double z, double yaw, bool autocontinue, bool current, double orbit, int holdTime)
pixhawk's avatar
pixhawk committed
109 110 111
{
    if (uasId == this->uas->getUASID())
    {
pixhawk's avatar
pixhawk committed
112
        Waypoint* wp = new Waypoint(id, x, y, z, yaw, autocontinue, current, orbit, holdTime);
pixhawk's avatar
pixhawk committed
113 114 115 116
        addWaypoint(wp);
    }
}

117
void WaypointList::waypointReached(UASInterface* uas, quint16 waypointId)
pixhawk's avatar
pixhawk committed
118
{
119
    Q_UNUSED(uas);
120 121
    qDebug() << "Waypoint reached: " << waypointId;

pixhawk's avatar
pixhawk committed
122 123 124 125 126 127
    updateStatusLabel(QString("Waypoint %1 reached.").arg(waypointId));
}

void WaypointList::currentWaypointChanged(quint16 seq)
{
    if (seq < waypoints.size())
pixhawk's avatar
pixhawk committed
128
    {
pixhawk's avatar
pixhawk committed
129
        for(int i = 0; i < waypoints.size(); i++)
pixhawk's avatar
pixhawk committed
130
        {
pixhawk's avatar
pixhawk committed
131
            WaypointView* widget = wpViews.find(waypoints[i]).value();
pixhawk's avatar
pixhawk committed
132

pixhawk's avatar
pixhawk committed
133
            if (waypoints[i]->getId() == seq)
pixhawk's avatar
pixhawk committed
134
            {
pixhawk's avatar
pixhawk committed
135 136 137 138 139 140 141
                waypoints[i]->setCurrent(true);
                widget->setCurrent(true);
            }
            else
            {
                waypoints[i]->setCurrent(false);
                widget->setCurrent(false);
pixhawk's avatar
pixhawk committed
142 143
            }
        }
pixhawk's avatar
pixhawk committed
144 145
        redrawList();
    }
pixhawk's avatar
pixhawk committed
146 147
}

148
void WaypointList::read()
pixhawk's avatar
pixhawk committed
149 150 151 152 153
{
    while(waypoints.size()>0)
    {
        removeWaypoint(waypoints[0]);
    }
pixhawk's avatar
pixhawk committed
154

pixhawk's avatar
pixhawk committed
155 156 157
    emit requestWaypoints();
}

158 159 160
void WaypointList::transmit()
{
    emit sendWaypoints(waypoints);
pixhawk's avatar
pixhawk committed
161
    //emit requestWaypoints(); FIXME
162 163
}

pixhawk's avatar
pixhawk committed
164 165 166 167 168 169 170
void WaypointList::add()
{
    // Only add waypoints if UAS is present
    if (uas)
    {
        if (waypoints.size() > 0)
        {
pixhawk's avatar
pixhawk committed
171
            addWaypoint(new Waypoint(waypoints.size(), 1.1, 1.1, -0.6, 0.0, true, false, 0.1, 2000));
pixhawk's avatar
pixhawk committed
172 173 174
        }
        else
        {
pixhawk's avatar
pixhawk committed
175
            addWaypoint(new Waypoint(waypoints.size(), 1.1, 1.1, -0.6, 0.0, true, true, 0.1, 2000));
pixhawk's avatar
pixhawk committed
176 177 178 179 180 181
        }
    }
}

void WaypointList::addWaypoint(Waypoint* wp)
{
pixhawk's avatar
pixhawk committed
182
    waypoints.push_back(wp);
pixhawk's avatar
pixhawk committed
183 184 185 186 187 188 189
    if (!wpViews.contains(wp))
    {
        WaypointView* wpview = new WaypointView(wp, this);
        wpViews.insert(wp, wpview);
        listLayout->addWidget(wpViews.value(wp));
        connect(wpview, SIGNAL(moveDownWaypoint(Waypoint*)), this, SLOT(moveDown(Waypoint*)));
        connect(wpview, SIGNAL(moveUpWaypoint(Waypoint*)), this, SLOT(moveUp(Waypoint*)));
190
        connect(wpview, SIGNAL(removeWaypoint(Waypoint*)), this, SLOT(removeWaypoint(Waypoint*)));
pixhawk's avatar
pixhawk committed
191
        connect(wpview, SIGNAL(currentWaypointChanged(quint16)), this, SLOT(currentWaypointChanged(quint16)));
pixhawk's avatar
pixhawk committed
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
    }
}

void WaypointList::redrawList()
{
    // Clear list layout
    if (!wpViews.empty())
    {
        QMapIterator<Waypoint*,WaypointView*> viewIt(wpViews);
        viewIt.toFront();
        while(viewIt.hasNext())
        {
            viewIt.next();
            listLayout->removeWidget(viewIt.value());
        }
        // Re-add waypoints
        for(int i = 0; i < waypoints.size(); i++)
        {
            listLayout->addWidget(wpViews.value(waypoints[i]));
        }
    }
}

void WaypointList::moveUp(Waypoint* wp)
{
217
    int id = wp->getId();
pixhawk's avatar
pixhawk committed
218 219 220 221 222 223 224
    if (waypoints.size() > 1 && waypoints.size() > id)
    {
        Waypoint* temp = waypoints[id];
        if (id > 0)
        {
            waypoints[id] = waypoints[id-1];
            waypoints[id-1] = temp;
225 226
            waypoints[id-1]->setId(id-1);
            waypoints[id]->setId(id);
pixhawk's avatar
pixhawk committed
227 228 229 230 231
        }
        else
        {
            waypoints[id] = waypoints[waypoints.size()-1];
            waypoints[waypoints.size()-1] = temp;
232 233
            waypoints[waypoints.size()-1]->setId(waypoints.size()-1);
            waypoints[id]->setId(id);
pixhawk's avatar
pixhawk committed
234 235 236 237 238 239 240
        }
        redrawList();
    }
}

void WaypointList::moveDown(Waypoint* wp)
{
241
    int id = wp->getId();
pixhawk's avatar
pixhawk committed
242 243 244 245 246 247 248
    if (waypoints.size() > 1 && waypoints.size() > id)
    {
        Waypoint* temp = waypoints[id];
        if (id != waypoints.size()-1)
        {
            waypoints[id] = waypoints[id+1];
            waypoints[id+1] = temp;
249 250
            waypoints[id+1]->setId(id+1);
            waypoints[id]->setId(id);
pixhawk's avatar
pixhawk committed
251 252 253 254 255
        }
        else
        {
            waypoints[id] = waypoints[0];
            waypoints[0] = temp;
256 257
            waypoints[0]->setId(0);
            waypoints[id]->setId(id);
pixhawk's avatar
pixhawk committed
258 259 260 261 262 263 264 265
        }
        redrawList();
    }
}

void WaypointList::removeWaypoint(Waypoint* wp)
{
    // Delete from list
pixhawk's avatar
pixhawk committed
266 267
    if (wp != NULL)
    {
268 269
        waypoints.remove(wp->getId());
        for(int i = wp->getId(); i < waypoints.size(); i++)
pixhawk's avatar
pixhawk committed
270
        {
271
            waypoints[i]->setId(i);
pixhawk's avatar
pixhawk committed
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
        }

        // Remove from view
        WaypointView* widget = wpViews.find(wp).value();
        wpViews.remove(wp);
        widget->hide();
        listLayout->removeWidget(widget);
        delete wp;
    }
}

void WaypointList::changeEvent(QEvent *e)
{
    switch (e->type()) {
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

void WaypointList::saveWaypoints()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"), "./waypoints.txt", tr("Waypoint File (*.txt)"));
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        return;

    QTextStream in(&file);
    for (int i = 0; i < waypoints.size(); i++)
    {
        Waypoint* wp = waypoints[i];
305
        in << "\t" << wp->getId() << "\t" << wp->getX() << "\t" << wp->getY()  << "\t" << wp->getZ()  << "\t" << wp->getYaw()  << "\t" << wp->getAutoContinue() << "\t" << wp->getCurrent() << "\t" << wp->getOrbit() << "\t" << wp->getHoldTime() << "\n";
pixhawk's avatar
pixhawk committed
306 307 308 309 310 311 312 313 314 315 316 317 318 319
        in.flush();
    }
    file.close();
}

void WaypointList::loadWaypoints()
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Load File"), ".", tr("Waypoint File (*.txt)"));
    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    while(waypoints.size()>0)
    {
320
        removeWaypoint(waypoints[0]);
pixhawk's avatar
pixhawk committed
321 322 323 324 325
    }

    QTextStream in(&file);
    while (!in.atEnd())
    {
pixhawk's avatar
pixhawk committed
326
        QStringList wpParams = in.readLine().split("\t");
pixhawk's avatar
pixhawk committed
327
        if (wpParams.size() == 10)
pixhawk's avatar
pixhawk committed
328
            addWaypoint(new Waypoint(wpParams[1].toInt(), wpParams[2].toDouble(), wpParams[3].toDouble(), wpParams[4].toDouble(), wpParams[5].toDouble(), (wpParams[6].toInt() == 1 ? true : false), (wpParams[7].toInt() == 1 ? true : false), wpParams[8].toDouble(), wpParams[9].toInt()));
pixhawk's avatar
pixhawk committed
329 330 331 332
    }
    file.close();
}