Commit 6389de51 authored by Brett Selby's avatar Brett Selby Committed by Jeff Niu

Remove actuators (#72)

* Squash 10 commits
Delete actuator.cpp

Delete actuator.h

Delete actuatorsetup.cpp

Delete actuatorsetup.h

Delete actuatorsetup.ui

Remove reference to actuatorsetup.h

Remove actuator variables from mainwindow.h

Removed actuator sections from mainwindow.cpp

Removed actuator sections from mainwindow.h

Remove actuator options from interface, replace actuator with solenoid in switchControllerTo()

* Added object tracker

* Added cmake NO_DEBUG flag
parent 5509985f
#include <thread>
#include <future>
#include "actuator.h"
Actuator::Actuator(const QString &serial_port,
const PortSettings &settings, QextSerialPort::QueryMode mode) :
Controller(1, 1), m_serial_port(new QextSerialPort(serial_port, settings, mode)) {
//on successful connection
if (m_serial_port->lastError() == 0) {
Logger::log(serial_port.toStdString() + " successfully opened!", Logger::INFO);
m_serial_port->flush();
// Send a renumbering request for the devices
resetDeviceNumber();
} else {
Logger::log("ERROR: " + serial_port.toStdString() + " could not be opened! "
+ m_serial_port->errorString().toStdString(), Logger::FATAL);
}
}
// Copy constructor
Actuator::Actuator(const Actuator &other) :
Controller(other.m_invert_x, other.m_invert_y),
m_x_device(other.m_x_device), m_y_device(other.m_y_device),
m_serial_port(other.m_serial_port) {}
char *const Actuator::convertDataToBytes(long int data) {
if (data < 0) {
data = intPow(BYTE_RANGE, 4) + data;
}
char *result = new char[DATA_SIZE];
for (int i = DATA_SIZE - 1; i >= 0; --i) {
int temp = intPow(BYTE_RANGE, i);
result[i] = (char) (data / temp);
data = data - temp * result[i];
}
return result;
}
void Actuator::resetDeviceNumber() {
char instr[] = {0, ZaberCmd::RENUMBER, 0, 0, 0, 0};
m_serial_port->write(instr);
m_x_device = 0;
m_y_device = 1;
}
int const Actuator::intPow(int x, int p) {
if (p == 0) return 1;
if (p == 1) return x;
int tmp = intPow(x, p / 2);
if (p % 2 == 0) return tmp * tmp;
else return x * tmp * tmp;
}
int Actuator::setSerPort(const QString &serial_port) {
if (m_serial_port->portName() == serial_port) {
return 0;
}
//close the current port
if (m_serial_port->isOpen()) {
m_serial_port->flush();
m_serial_port->close();
}
m_serial_port->setPortName(serial_port);
if (m_serial_port->lastError() != 0) {
Logger::log(m_serial_port->errorString().toStdString(), Logger::FATAL);
return -1;
}
return 0;
}
int Actuator::changeSettings(const PortSettings &settings) {
m_serial_port->setBaudRate(settings.BaudRate);
m_serial_port->setDataBits(settings.DataBits);
m_serial_port->setParity(settings.Parity);
m_serial_port->setStopBits(settings.StopBits);
m_serial_port->setFlowControl(settings.FlowControl);
m_serial_port->setTimeout(settings.Timeout_Millisec);
if (m_serial_port->lastError() != 0) {
Logger::log(m_serial_port->errorString().toStdString(), Logger::FATAL);
return -1;
}
return 0;
}
void Actuator::switchDevices() {
unsigned char temp = m_x_device;
m_x_device = m_y_device;
m_y_device = temp;
}
Actuator::~Actuator() {
delete m_serial_port;
}
void Actuator::move(Vector2i dir, int timer) {
bool success = true;
#ifndef NDEBUG
Logger::log("Attempting move (" + std::to_string(dir.x_comp) + ", " + std::to_string(dir.y_comp) + ")",
Logger::DEBUG);
#endif
try {
std::future<void> x_thread(std::async(&Actuator::moveActuator, this, m_x_device, dir.x_comp, timer));
std::future<void> y_thread(std::async(&Actuator::moveActuator, this, m_y_device, dir.y_comp, timer));
x_thread.get();
y_thread.get();
}
catch (std::exception &e) {
Logger::log(e.what(), Logger::FATAL);
success = false;
}
catch (std::string e) {
Logger::log(e, Logger::FATAL);
success = false;
}
catch (...) {
success = false;
#ifndef NDEBUG
Logger::log("Unexpected exception", Logger::DEBUG);
#endif
}
if (success) {
Logger::log("Moved " + dir.toString() + " in " + std::to_string(timer) + " milliseconds.", Logger::INFO);
} else {
Logger::log("The movement " + dir.toString() + " could not be completed.", Logger::FATAL);
}
}
void Actuator::moveActuator(const unsigned char device, const int value, const int t) {
try {
std::chrono::milliseconds sleep_step = std::chrono::milliseconds(0);
if (value != 0) {
sleep_step = std::chrono::milliseconds(t / value); // still need to test negative steps
}
char *instr = new char(CMD_SIZE + DATA_SIZE);
// Setup device and command numbers
instr[0] = device;
instr[1] = ZaberCmd::REL_MOVE;
char *data = convertDataToBytes(STEP_FACTOR);
for (int i = 0; i < DATA_SIZE; i++) {
instr[i + 2] = data[i];
}
delete[] data;
// TODO: This is yet to be tested, sorry I don't have Zaber actuators at home :(
for (int i = abs(value); i > 0; i--) {
if (m_serial_port->isOpen()) {
m_serial_port->write(instr, CMD_SIZE + DATA_SIZE);
} else {
delete instr;
std::string error_msg = "ERROR: Failed to write to serial port "
+ (m_serial_port->portName()).toStdString() +
" because it's not open.";
throw error_msg;
}
std::this_thread::sleep_for(sleep_step);
}
delete instr;
}
catch (std::string e) {
throw e;
}
catch (...) {
throw std::current_exception();
}
}
//TODO: Add static method for getting current configuration of a given port
#ifndef ACTUATOR_H
#define ACTUATOR_H
#include "controller.h"
#include "qextserialport.h"
#define BYTE_RANGE 256
#define DATA_SIZE 4
#define CMD_SIZE 2
#define STEP_FACTOR 5
// For Zaber, settings must be: 9600 baud, no hand shaking, 8 data bits, no parity, one stop bit.
const PortSettings DEFAULT_SETTINGS = { BAUD9600, DATA_8, PAR_NONE, STOP_1, FLOW_XONXOFF, 10 };
class QextSerialPort;
// Command mapping for Zaber T-LSR actuators http://www.zaber.com/wiki/Manuals/T-LSR
enum ZaberCmd {
HOME = 1,
RENUMBER = 2,
ABS_MOVE = 20,
REL_MOVE = 21,
CONST_SPEED_MOVE = 22,
STOP_MOVE = 23,
SET_CURRENT_POS = 45,
FIRM_VER = 51
};
class Actuator : public Controller
{
public:
Actuator(const QString& serial_port = "",
const PortSettings& settings = DEFAULT_SETTINGS,
QextSerialPort::QueryMode mode = QextSerialPort::EventDriven);
Actuator(const Actuator&);
int setSerPort(const QString& serial_port);
int changeSettings(const PortSettings& settings);
void switchDevices();
void move(Vector2i dir, int timer);
~Actuator();
private:
QextSerialPort* m_serial_port;
unsigned char m_x_device, m_y_device;
//helper functions
static char* const convertDataToBytes(long int data);
void resetDeviceNumber();
static int const intPow(int x, int p);
void moveActuator(unsigned char device, const int value, const int time);
};
#endif // ACTUATOR_H
#include "actuatorsetup.h"
#include "ui_actuatorsetup.h"
#include "../controller/actuator.h"
#include <QtCore>
ActuatorSetup::ActuatorSetup(std::shared_ptr<Actuator>& controller, QWidget *parent) :
QDialog(parent),
ui(new Ui::ActuatorSetup),
m_emma(controller)
{
ui->setupUi(this);
//! [0]
foreach(QextPortInfo info, QextSerialEnumerator::getPorts())
ui->portBox->addItem(info.portName);
//make sure user can input their own port name!
ui->portBox->setEditable(true);
ui->baudRateBox->addItem("1200", BAUD1200);
ui->baudRateBox->addItem("2400", BAUD2400);
ui->baudRateBox->addItem("4800", BAUD4800);
ui->baudRateBox->addItem("9600", BAUD9600);
ui->baudRateBox->addItem("19200", BAUD19200);
ui->baudRateBox->setCurrentIndex(3);
ui->parityBox->addItem("NONE", PAR_NONE);
ui->parityBox->addItem("ODD", PAR_ODD);
ui->parityBox->addItem("EVEN", PAR_EVEN);
ui->dataBitsBox->addItem("5", DATA_5);
ui->dataBitsBox->addItem("6", DATA_6);
ui->dataBitsBox->addItem("7", DATA_7);
ui->dataBitsBox->addItem("8", DATA_8);
ui->dataBitsBox->setCurrentIndex(3);
ui->stopBitsBox->addItem("1", STOP_1);
ui->stopBitsBox->addItem("2", STOP_2);
ui->queryModeBox->addItem("Polling", QextSerialPort::Polling);
ui->queryModeBox->addItem("EventDriven", QextSerialPort::EventDriven);
m_current_settings = { BAUD9600, DATA_8, PAR_NONE, STOP_1, FLOW_XONXOFF, 10 };
controller->setSerPort(ui->portBox->currentText());
controller->changeSettings(m_current_settings);;
m_enumerator = new QextSerialEnumerator(this);
m_enumerator->setUpNotifications();
connect(ui->buttonBox, SIGNAL(accepted()), SLOT(onSettingsApplied()));
//TODO: Refresh to the current settings if button box is rejected
connect(ui->portBox, SIGNAL(editTextChanged(QString)), SLOT(onPortNameChanged(QString)));
connect(m_enumerator, SIGNAL(deviceDiscovered(QextPortInfo)), SLOT(onPortAddedOrRemoved()));
connect(m_enumerator, SIGNAL(deviceRemoved(QextPortInfo)), SLOT(onPortAddedOrRemoved()));
Logger::log("Actuator initialized", Logger::INFO);
setWindowTitle(tr("Actuator Setup"));
}
ActuatorSetup::~ActuatorSetup()
{
m_emma.reset();
delete m_enumerator;
delete ui;
}
void ActuatorSetup::onSettingsApplied(){
PortSettings settings = {
(BaudRateType)ui->baudRateBox->itemData(ui->baudRateBox->currentIndex()).toInt(),
(DataBitsType)ui->dataBitsBox->itemData(ui->baudRateBox->currentIndex()).toInt(),
(ParityType)ui->parityBox->itemData(ui->parityBox->currentIndex()).toInt(),
(StopBitsType)ui->stopBitsBox->itemData(ui->stopBitsBox->currentIndex()).toInt(),
FLOW_XONXOFF,
ui->timeoutBox->value()
};
if (m_emma->changeSettings(settings) == 0) {
m_current_settings = settings;
}
else {
//TODO: Spawn an error dialog
}
}
void ActuatorSetup::onPortNameChanged(const QString & name)
{
m_emma->setSerPort(name);
}
void ActuatorSetup::onPortAddedOrRemoved()
{
QString current = ui->portBox->currentText();
ui->portBox->blockSignals(true);
ui->portBox->clear();
foreach(QextPortInfo info, QextSerialEnumerator::getPorts())
ui->portBox->addItem(info.portName);
ui->portBox->setCurrentIndex(ui->portBox->findText(current));
ui->portBox->blockSignals(false);
}
#ifndef ACTUATORSETUP_H
#define ACTUATORSETUP_H
#include "qextserialport.h"
#include "qextserialenumerator.h"
#include "../controller/actuator.h"
#include <QDialog>
#include <memory>
class QextSerialEnumerator;
class Actuator;
namespace Ui {
class ActuatorSetup;
}
class ActuatorSetup : public QDialog
{
Q_OBJECT
public:
ActuatorSetup(std::shared_ptr<Actuator>& controller, QWidget *parent = 0);
~ActuatorSetup();
private Q_SLOTS:
void onPortNameChanged(const QString &name);
void onSettingsApplied();
void onPortAddedOrRemoved();
private:
Ui::ActuatorSetup *ui;
QTimer *timer;
std::shared_ptr<Actuator> m_emma;
QextSerialEnumerator *m_enumerator;
PortSettings m_current_settings;
};
#endif // ACTUATORSETUP_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ActuatorSetup</class>
<widget class="QDialog" name="ActuatorSetup">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>202</width>
<height>252</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>202</width>
<height>252</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>202</width>
<height>252</height>
</size>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>161</width>
<height>191</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="portBox"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>BaudRate:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="baudRateBox"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>DataBits:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="dataBitsBox"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Parity:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="parityBox"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>StopBits:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="stopBitsBox"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>QueryMode:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="queryModeBox"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Timeout:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSpinBox" name="timeoutBox">
<property name="suffix">
<string> ms</string>
</property>
<property name="minimum">
<number>-1</number>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>10</x>
<y>210</y>
<width>181</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
......@@ -11,7 +11,6 @@ MainWindow::MainWindow(QWidget *parent, const char *) :
//Set up logger
Logger::setStream(getLogView());
m_actuator = std::make_shared<Actuator>();
m_solenoid = std::make_shared<Solenoid>();
m_simulator = std::make_shared<Simulator>(1, -1);
m_controller = m_solenoid;
......@@ -22,15 +21,12 @@ MainWindow::MainWindow(QWidget *parent, const char *) :
PythonEngine::getInstance().append_module("emb", &Embedded::PyInit_emb);
// Setup subwindows
m_actuator_setup_window = new ActuatorSetup(m_actuator, this);
m_simulator_window = new SimulatorWindow(m_simulator, this);
m_script_window = new ScriptWindow(this);
m_about_window = new ActionAbout(this);
m_camera_display = new CameraDisplay(this);
// Setup slot connections
connect(ui->setup_actuator, SIGNAL(triggered()), this, SLOT(openActuatorSetup()));
connect(ui->switch_to_actuator_mode, SIGNAL(triggered()), this, SLOT(switchToActuator()));
connect(ui->switch_to_simulator_mode, SIGNAL(triggered()), this, SLOT(switchToSimulator()));
connect(ui->start_python_interpreter, SIGNAL(triggered()), this, SLOT(openPythonInterpreter()));
connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(openActionAbout()));
......@@ -97,7 +93,6 @@ void MainWindow::mousePressEvent(QMouseEvent *) {
MainWindow::~MainWindow() {
// Destroy all subwindows
delete m_actuator_setup_window;
delete m_about_window;
delete m_simulator_window;
delete m_script_window;
......@@ -123,10 +118,10 @@ void MainWindow::switchControllerTo(Controller::Type const type) {
}
m_controller_type = type;
switch (type) {
case Controller::Type::ACTUATOR:
// Switch to the actuator controller and hide the simulation window
Logger::log("Switching to ACTUATOR", Logger::INFO);
m_controller = m_actuator;
case Controller::Type::SOLENOID:
// Switch to the solenoid controller and hide the simulation window
Logger::log("Switching to SOLENOID", Logger::INFO);
m_controller = m_solenoid;
if (m_simulator_window->isVisible()) { m_simulator_window->hide(); }
break;
case Controller::Type::SIMULATOR:
......@@ -140,10 +135,6 @@ void MainWindow::switchControllerTo(Controller::Type const type) {
}
}
void MainWindow::openActuatorSetup() {
m_actuator_setup_window->show();
}
void MainWindow::openPythonInterpreter() {
m_script_window->show();
}
......
......@@ -12,7 +12,6 @@
#include "../controller/solenoid.h"
#include "../controller/simulator.h"
#include "actuatorsetup.h"
#include "simulatorwindow.h"
#include "actionabout.h"
#include "scriptwindow.h"
......@@ -40,15 +39,13 @@ public:
public Q_SLOTS:
void openActuatorSetup();
void openPythonInterpreter();
void openActionAbout();
void openCameraDisplay();
inline void switchToActuator() { switchControllerTo(Controller::Type::ACTUATOR); }
inline void switchToSolenoid() { switchControllerTo(Controller::Type::SOLENOID); }
inline void switchToSimulator() { switchControllerTo(Controller::Type::SIMULATOR); }
......@@ -64,7 +61,6 @@ private Q_SLOTS:
private:
Ui::MainWindow *ui;
ActuatorSetup *m_actuator_setup_window;
ScriptWindow *m_script_window;
SimulatorWindow *m_simulator_window;
ActionAbout *m_about_window;
......@@ -73,7 +69,6 @@ private:
Controller::Type m_controller_type;
std::shared_ptr<Controller> m_controller;
std::shared_ptr<Actuator> m_actuator;
std::shared_ptr<Solenoid> m_solenoid;
std::shared_ptr<Simulator> m_simulator;
......
......@@ -173,10 +173,8 @@ p, li { white-space: pre-wrap; }
<property name="title">
<string>Setup</string>
</property>
<addaction name="switch_to_actuator_mode"/>
<addaction name="switch_to_simulator_mode"/>
<addaction name="separator"/>
<addaction name="setup_actuator"/>
<addaction name="start_python_interpreter"/>
<addaction name="separator"/>
<addaction name="exit"/>
......@@ -235,20 +233,6 @@ p, li { white-space: pre-wrap; }
<addaction name="tools_menu"/>
<addaction name="menuHelp"/>
</widget>
<action name="switch_to_actuator_mode">
<property name="checkable">
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>SAM Actuator mode</string>
</property>
</action>
<action name="switch_to_simulator_mode">
<property name="checkable">
<bool>false</bool>
......@@ -260,14 +244,6 @@ p, li { white-space: pre-wrap; }
<string>Simulator mode</string>
</property>
</action>
<action name="setup_actuator">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Actuators</string>
</property>
</action>
<action name="exit">
<property name="text">
<string>Exit</string>
......
......@@ -47,7 +47,7 @@ void SimulatorWindow::reject() {
QWidget *parent = parentWidget();
if (!parent) return;
MainWindow *main_window = (MainWindow*) parent;
main_window->switchToActuator();
main_window->switchToSolenoid();
QDialog::reject();
}
......
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