complies with cpplint
This commit is contained in:
parent
f94492264d
commit
15b11c3bb5
6 changed files with 635 additions and 648 deletions
|
@ -9,164 +9,150 @@
|
||||||
*
|
*
|
||||||
* Hand Control is distributed in the hope that it will be useful,
|
* Hand Control is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with Hand Control. If not, see <http://www.gnu.org/licenses/>.
|
* along with Hand Control. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
#include <ros/ros.h>
|
#include <ros/ros.h>
|
||||||
#include <ros/time.h>
|
#include <ros/time.h>
|
||||||
#include <locale.h>
|
|
||||||
#include <limits>
|
|
||||||
#include <math.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#include <pcl_ros/point_cloud.h>
|
#include <pcl_ros/point_cloud.h>
|
||||||
#include <pcl/point_types.h>
|
#include <pcl/point_types.h>
|
||||||
|
|
||||||
#include <hand_control/Plan.h>
|
#include <hand_control/Plan.h>
|
||||||
#include <geometry_msgs/Twist.h>
|
#include <geometry_msgs/Twist.h>
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <dynamic_reconfigure/server.h>
|
#include <dynamic_reconfigure/server.h>
|
||||||
#include <hand_control/CommanderConfig.h>
|
#include <hand_control/CommanderConfig.h>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
class Run
|
|
||||||
{
|
class Run {
|
||||||
private:
|
private:
|
||||||
float xx, yy, zz, theta; // read coords
|
float xx, yy, zz, theta; // read coords
|
||||||
|
|
||||||
// see README.md to know what are the parameters
|
// see README.md to know what are the parameters
|
||||||
float x_vel, y_vel, z_vel, angle_vel, up_factor, neutral_z; // parameters
|
float x_vel, y_vel, z_vel, angle_vel,
|
||||||
float max_curv; // not used yet
|
up_factor, neutral_z; // parameters
|
||||||
float z_dev_min, x_dev_min, y_dev_min, th_dev_min; // parameters : thresholds
|
float max_curv; // not used yet
|
||||||
uint64_t min_number; // parameter
|
float z_dev_min, x_dev_min, y_dev_min,
|
||||||
bool no_diag; // parameter
|
th_dev_min; // parameters : thresholds
|
||||||
|
uint64_t min_number; // parameter
|
||||||
|
bool no_diag; // parameter
|
||||||
|
|
||||||
ros::Publisher pub;
|
ros::Publisher pub;
|
||||||
|
|
||||||
void publish()
|
void publish() {
|
||||||
// build and publish a message from the "xx", "yy", "zz" and "theta" informations
|
// build and publish a message from the "xx",
|
||||||
{
|
// "yy", "zz" and "theta" informations
|
||||||
geometry_msgs::Twist::Ptr mvt(new geometry_msgs::Twist());
|
geometry_msgs::Twist::Ptr mvt(new geometry_msgs::Twist());
|
||||||
|
|
||||||
if (fabs(zz) > z_dev_min)
|
if (fabs(zz) > z_dev_min) {
|
||||||
{
|
// up_factor to balance out the gravity effect
|
||||||
// up_factor to balance out the gravity effect
|
if (zz > 0)
|
||||||
if (zz > 0)
|
mvt->linear.z = zz * z_vel * up_factor;
|
||||||
mvt->linear.z = zz * z_vel * up_factor ;
|
else
|
||||||
else
|
mvt->linear.z = zz * z_vel;
|
||||||
mvt->linear.z = zz * z_vel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// no_diag true : the drone can only translate on the "x" axis
|
|
||||||
// or the "y" axis but not on a linear combination of these axes.
|
|
||||||
if (no_diag)
|
|
||||||
{
|
|
||||||
if (fabs(yy) > fabs(xx) && fabs(yy) > y_dev_min)
|
|
||||||
{
|
|
||||||
mvt->linear.y = yy * y_vel;
|
|
||||||
}
|
}
|
||||||
else if (fabs(xx) > x_dev_min)
|
|
||||||
{
|
// no_diag true : the drone can only translate on the "x" axis
|
||||||
mvt->linear.x = - xx * x_vel;
|
// or the "y" axis but not on a linear combination of these axes.
|
||||||
|
if (no_diag) {
|
||||||
|
if (fabs(yy) > fabs(xx) && fabs(yy) > y_dev_min)
|
||||||
|
mvt->linear.y = yy * y_vel;
|
||||||
|
else if (fabs(xx) > x_dev_min)
|
||||||
|
mvt->linear.x = - xx * x_vel;
|
||||||
|
} else {
|
||||||
|
// no_diag false : the drone can translate on any possible direction
|
||||||
|
if (fabs(yy) > y_dev_min)
|
||||||
|
mvt->linear.y = yy * y_vel;
|
||||||
|
if (fabs(xx) > x_dev_min)
|
||||||
|
mvt->linear.x = - xx * x_vel;
|
||||||
}
|
}
|
||||||
} else // no_diag false : the drone can translate on any possible direction
|
|
||||||
{
|
|
||||||
if (fabs(yy) > y_dev_min)
|
|
||||||
mvt->linear.y = yy * y_vel;
|
|
||||||
if (fabs(xx) > x_dev_min)
|
|
||||||
mvt->linear.x = - xx * x_vel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fabs(theta) > th_dev_min) {
|
if (fabs(theta) > th_dev_min) {
|
||||||
mvt->angular.z = theta * angle_vel;
|
mvt->angular.z = theta * angle_vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub.publish(mvt);
|
pub.publish(mvt);
|
||||||
ROS_INFO("cmd published");
|
ROS_INFO("cmd published");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Run(const ros::Publisher& cmd_publisher) :
|
explicit Run(const ros::Publisher& cmd_publisher) :
|
||||||
pub(cmd_publisher) {}
|
pub(cmd_publisher) {}
|
||||||
|
|
||||||
void callback(const hand_control::Plan::ConstPtr& msg)
|
|
||||||
// handle received messages
|
// handle received messages
|
||||||
{
|
void callback(const hand_control::Plan::ConstPtr& msg) {
|
||||||
ROS_INFO("plan received");
|
ROS_INFO("plan received");
|
||||||
if (msg->curvature < max_curv && msg->number > min_number)
|
|
||||||
// we ever have msg->curvature == 0 in fact (not implemented yet)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(msg->normal.z > 0)
|
// we ever have msg->curvature == 0 in fact (not implemented yet)
|
||||||
{
|
if (msg->curvature < max_curv && msg->number > min_number) {
|
||||||
yy = msg->normal.x;
|
if (msg->normal.z > 0) {
|
||||||
xx = msg->normal.y;
|
yy = msg->normal.x;
|
||||||
}
|
xx = msg->normal.y;
|
||||||
else
|
} else {
|
||||||
{
|
yy = - msg->normal.x;
|
||||||
yy = - msg->normal.x;
|
xx = - msg->normal.y;
|
||||||
xx = - msg->normal.y;
|
}
|
||||||
|
zz = msg->altitude - neutral_z;
|
||||||
|
theta = msg->angle;
|
||||||
|
// theta between -90 and 90
|
||||||
|
ROS_INFO("coords updated");
|
||||||
|
} else {
|
||||||
|
xx = yy = zz = 0.;
|
||||||
}
|
}
|
||||||
|
publish();
|
||||||
|
}
|
||||||
|
|
||||||
zz = msg->altitude - neutral_z;
|
|
||||||
|
|
||||||
theta = msg->angle;
|
|
||||||
// theta between -90 and 90
|
|
||||||
|
|
||||||
ROS_INFO("coords updated");
|
|
||||||
} else {
|
|
||||||
xx = yy = zz = 0.;
|
|
||||||
}
|
|
||||||
publish();
|
|
||||||
};
|
|
||||||
|
|
||||||
void reconfigure(const hand_control::CommanderConfig& c, const uint32_t& level)
|
|
||||||
// updates the parameters (received with dynamic_reconfigure)
|
// updates the parameters (received with dynamic_reconfigure)
|
||||||
{
|
void reconfigure(const hand_control::CommanderConfig& c,
|
||||||
max_curv = c.max_curvature;
|
const uint32_t& level) {
|
||||||
x_dev_min = c.x_minimal_deviation;
|
max_curv = c.max_curvature;
|
||||||
y_dev_min = c.y_minimal_deviation;
|
x_dev_min = c.x_minimal_deviation;
|
||||||
z_dev_min = c.z_minimal_deviation;
|
y_dev_min = c.y_minimal_deviation;
|
||||||
th_dev_min = c.theta_minimal_deviation;
|
z_dev_min = c.z_minimal_deviation;
|
||||||
neutral_z = c.neutral_alt;
|
th_dev_min = c.theta_minimal_deviation;
|
||||||
min_number = c.min_points_number;
|
neutral_z = c.neutral_alt;
|
||||||
up_factor = c.up_fact;
|
min_number = c.min_points_number;
|
||||||
x_vel = c.x_vel;
|
up_factor = c.up_fact;
|
||||||
y_vel = c.y_vel;
|
x_vel = c.x_vel;
|
||||||
z_vel = c.z_vel;
|
y_vel = c.y_vel;
|
||||||
angle_vel = c.angle_vel;
|
z_vel = c.z_vel;
|
||||||
no_diag = c.no_diag;
|
angle_vel = c.angle_vel;
|
||||||
|
no_diag = c.no_diag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void run()
|
|
||||||
// runs the callbacks and publications process
|
// runs the callbacks and publications process
|
||||||
{
|
void run() {
|
||||||
ros::spin();
|
ros::spin();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv) {
|
||||||
{
|
ros::init(argc, argv, "commander");
|
||||||
ros::init(argc, argv, "commander");
|
ros::NodeHandle node("commander");
|
||||||
ros::NodeHandle node("commander");
|
ros::Publisher cmd_pub =\
|
||||||
ros::Publisher cmd_pub = node.advertise<geometry_msgs::Twist>("/cmd_vel", 1);
|
node.advertise<geometry_msgs::Twist>("/cmd_vel", 1);
|
||||||
Run run(cmd_pub);
|
Run run(cmd_pub);
|
||||||
ros::Subscriber plan_sub = node.subscribe<hand_control::Plan>("input", 1, &Run::callback, &run);
|
ros::Subscriber plan_sub =\
|
||||||
|
node.subscribe<hand_control::Plan>("input", 1, &Run::callback, &run);
|
||||||
|
|
||||||
// setting up dynamic_reconfigure (for rqt_reconfigure)
|
// setting up dynamic_reconfigure (for rqt_reconfigure)
|
||||||
dynamic_reconfigure::Server<hand_control::CommanderConfig> server;
|
dynamic_reconfigure::Server<hand_control::CommanderConfig> server;
|
||||||
dynamic_reconfigure::Server<hand_control::CommanderConfig>::CallbackType f;
|
dynamic_reconfigure::Server<hand_control::CommanderConfig>::CallbackType f;
|
||||||
f = boost::bind(&Run::reconfigure, &run, _1, _2);
|
f = boost::bind(&Run::reconfigure, &run, _1, _2);
|
||||||
server.setCallback(f);
|
server.setCallback(f);
|
||||||
|
|
||||||
// starts working
|
// starts working
|
||||||
run.run();
|
run.run();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
198
src/display.cpp
198
src/display.cpp
|
@ -17,10 +17,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// library used by "keyboard_cmd.cpp"
|
// library used by "keyboard_cmd.cpp"
|
||||||
|
|
||||||
|
#include "./display.h"
|
||||||
|
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#include <string>
|
|
||||||
#include <geometry_msgs/Twist.h>
|
#include <geometry_msgs/Twist.h>
|
||||||
#include "display.h"
|
#include <string>
|
||||||
|
|
||||||
const int Curses::cmd_kbd_lines = 8;
|
const int Curses::cmd_kbd_lines = 8;
|
||||||
const int Curses::cmd_kbd_columns = 55;
|
const int Curses::cmd_kbd_columns = 55;
|
||||||
|
@ -41,110 +43,110 @@ const int Curses::topic_lines = 8;
|
||||||
const int Curses::topic_columns = 22;
|
const int Curses::topic_columns = 22;
|
||||||
|
|
||||||
Curses::Curses() {
|
Curses::Curses() {
|
||||||
initscr();
|
initscr();
|
||||||
cbreak();
|
cbreak();
|
||||||
start_color();
|
start_color();
|
||||||
//noecho();
|
// noecho();
|
||||||
|
|
||||||
cmd_kbd = newwin(cmd_kbd_lines, cmd_kbd_columns, 0, 0);
|
cmd_kbd = newwin(cmd_kbd_lines, cmd_kbd_columns, 0, 0);
|
||||||
|
|
||||||
get = newwin(get_lines, get_columns,
|
get = newwin(get_lines, get_columns,
|
||||||
cmd_kbd_lines, cmd_kbd_columns/2);
|
cmd_kbd_lines, cmd_kbd_columns/2);
|
||||||
|
|
||||||
cmd_speed = newwin(cmd_speed_lines, cmd_speed_columns,
|
cmd_speed = newwin(cmd_speed_lines, cmd_speed_columns,
|
||||||
cmd_kbd_lines + get_lines, 0);
|
cmd_kbd_lines + get_lines, 0);
|
||||||
|
|
||||||
log_sent_title = newwin(1, log_sent_w_columns,
|
log_sent_title = newwin(1, log_sent_w_columns,
|
||||||
0, cmd_kbd_columns + 1);
|
0, cmd_kbd_columns + 1);
|
||||||
waddstr(log_sent_title, "SENT COMMANDS");
|
waddstr(log_sent_title, "SENT COMMANDS");
|
||||||
wrefresh(log_sent_title);
|
wrefresh(log_sent_title);
|
||||||
log_sent_w = newwin(log_sent_w_lines - 1, log_sent_w_columns,
|
log_sent_w = newwin(log_sent_w_lines - 1, log_sent_w_columns,
|
||||||
1, cmd_kbd_columns + 1);
|
1, cmd_kbd_columns + 1);
|
||||||
log_line_number = log_sent_w_lines - 2;
|
log_line_number = log_sent_w_lines - 2;
|
||||||
wattron(log_sent_w, A_BOLD);
|
wattron(log_sent_w, A_BOLD);
|
||||||
init_pair(1, COLOR_GREEN, COLOR_BLACK);
|
init_pair(1, COLOR_GREEN, COLOR_BLACK);
|
||||||
wattron(log_sent_w, COLOR_PAIR(1));
|
wattron(log_sent_w, COLOR_PAIR(1));
|
||||||
scrollok(log_sent_w, TRUE);
|
scrollok(log_sent_w, TRUE);
|
||||||
|
|
||||||
nav_data = newwin(nav_data_lines, nav_data_columns,
|
nav_data = newwin(nav_data_lines, nav_data_columns,
|
||||||
cmd_kbd_lines + get_lines + cmd_speed_lines + 1, 0);
|
cmd_kbd_lines + get_lines + cmd_speed_lines + 1, 0);
|
||||||
init_pair(2, COLOR_RED, COLOR_BLACK);
|
init_pair(2, COLOR_RED, COLOR_BLACK);
|
||||||
wattron(nav_data, COLOR_PAIR(2));
|
wattron(nav_data, COLOR_PAIR(2));
|
||||||
wattron(nav_data, A_BOLD);
|
wattron(nav_data, A_BOLD);
|
||||||
|
|
||||||
topic = newwin(topic_lines, topic_columns,
|
topic = newwin(topic_lines, topic_columns,
|
||||||
cmd_kbd_lines + get_lines + cmd_speed_lines + 1,
|
cmd_kbd_lines + get_lines + cmd_speed_lines + 1,
|
||||||
nav_data_columns + 1);
|
nav_data_columns + 1);
|
||||||
init_pair(3, COLOR_BLUE, COLOR_BLACK);
|
init_pair(3, COLOR_BLUE, COLOR_BLACK);
|
||||||
wattron(topic, COLOR_PAIR(3));
|
wattron(topic, COLOR_PAIR(3));
|
||||||
wattron(topic, A_BOLD);
|
wattron(topic, A_BOLD);
|
||||||
|
|
||||||
print_nav_data();
|
print_nav_data();
|
||||||
print_cmd_kbd();
|
print_cmd_kbd();
|
||||||
print_cmd_speed();
|
print_cmd_speed();
|
||||||
print_topic();
|
print_topic();
|
||||||
|
|
||||||
wmove(get, 0, 0);
|
wmove(get, 0, 0);
|
||||||
wrefresh(get);
|
wrefresh(get);
|
||||||
}
|
}
|
||||||
|
|
||||||
Curses::~Curses() {
|
Curses::~Curses() {
|
||||||
delwin(cmd_kbd);
|
delwin(cmd_kbd);
|
||||||
delwin(cmd_speed);
|
delwin(cmd_speed);
|
||||||
delwin(log_sent_w);
|
delwin(log_sent_w);
|
||||||
delwin(log_sent_title);
|
delwin(log_sent_title);
|
||||||
delwin(nav_data);
|
delwin(nav_data);
|
||||||
delwin(get);
|
delwin(get);
|
||||||
delwin(topic);
|
delwin(topic);
|
||||||
endwin();
|
endwin();
|
||||||
}
|
}
|
||||||
|
|
||||||
char Curses::getchar() {
|
char Curses::getchar() {
|
||||||
return wgetch(get);
|
return wgetch(get);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curses::print_cmd_kbd() {
|
void Curses::print_cmd_kbd() {
|
||||||
wmove(cmd_kbd, 0, 0);
|
wmove(cmd_kbd, 0, 0);
|
||||||
waddstr(cmd_kbd, " ---------------------\n");
|
waddstr(cmd_kbd, " ---------------------\n");
|
||||||
waddstr(cmd_kbd, " takeoff>| t|⇑ y|↖ u|↑ i|↗ o|\n");
|
waddstr(cmd_kbd, " takeoff>| t|⇑ y|↖ u|↑ i|↗ o|\n");
|
||||||
waddstr(cmd_kbd, " |---|---|---|---|---|----\n");
|
waddstr(cmd_kbd, " |---|---|---|---|---|----\n");
|
||||||
waddstr(cmd_kbd, " reset>| g|⇐ h|← j| k|→ l|⇒ m|\n");
|
waddstr(cmd_kbd, " reset>| g|⇐ h|← j| k|→ l|⇒ m|\n");
|
||||||
waddstr(cmd_kbd, " |---|---|---|---|---|----\n");
|
waddstr(cmd_kbd, " |---|---|---|---|---|----\n");
|
||||||
waddstr(cmd_kbd, " land>| b|⇓ n|↙ ,|↓ ;|↘ :|\n");
|
waddstr(cmd_kbd, " land>| b|⇓ n|↙ ,|↓ ;|↘ :|\n");
|
||||||
waddstr(cmd_kbd, " ---------------------\n");
|
waddstr(cmd_kbd, " ---------------------\n");
|
||||||
waddstr(cmd_kbd, " Press ctrl + C to quit");
|
waddstr(cmd_kbd, " Press ctrl + C to quit");
|
||||||
wrefresh(cmd_kbd);
|
wrefresh(cmd_kbd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curses::print_cmd_speed() {
|
void Curses::print_cmd_speed() {
|
||||||
wmove(cmd_speed, 0, 0);
|
wmove(cmd_speed, 0, 0);
|
||||||
waddstr(cmd_speed, " `x` cmd speed : (a/w : increase/decrease)\n");
|
waddstr(cmd_speed, " `x` cmd speed : (a/w : increase/decrease)\n");
|
||||||
waddstr(cmd_speed, " `y` cmd speed : (z/x : increase/decrease)\n");
|
waddstr(cmd_speed, " `y` cmd speed : (z/x : increase/decrease)\n");
|
||||||
waddstr(cmd_speed, " `z` cmd speed : (e/c : increase/decrease)\n");
|
waddstr(cmd_speed, " `z` cmd speed : (e/c : increase/decrease)\n");
|
||||||
waddstr(cmd_speed, "rotation speed : (r/v : increase/decrease)\n");
|
waddstr(cmd_speed, "rotation speed : (r/v : increase/decrease)\n");
|
||||||
wrefresh(cmd_speed);
|
wrefresh(cmd_speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Curses::update_cmd_speed(const char& coord, const float& v) {
|
void Curses::update_cmd_speed(const char& coord, const float& v) {
|
||||||
switch(coord) {
|
switch (coord) {
|
||||||
case 'x':
|
case 'x':
|
||||||
wmove(cmd_speed, 0, 16);
|
wmove(cmd_speed, 0, 16);
|
||||||
wprintw(cmd_speed, "%f", v);
|
wprintw(cmd_speed, "%f", v);
|
||||||
break;
|
break;
|
||||||
case 'y':
|
case 'y':
|
||||||
wmove(cmd_speed, 1, 16);
|
wmove(cmd_speed, 1, 16);
|
||||||
wprintw(cmd_speed, "%f", v);
|
wprintw(cmd_speed, "%f", v);
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
wmove(cmd_speed, 2, 16);
|
wmove(cmd_speed, 2, 16);
|
||||||
wprintw(cmd_speed, "%f", v);
|
wprintw(cmd_speed, "%f", v);
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
wmove(cmd_speed, 3, 16);
|
wmove(cmd_speed, 3, 16);
|
||||||
wprintw(cmd_speed, "%f", v);
|
wprintw(cmd_speed, "%f", v);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
;
|
{}
|
||||||
}
|
}
|
||||||
wrefresh(cmd_speed);
|
wrefresh(cmd_speed);
|
||||||
}
|
}
|
||||||
|
@ -170,39 +172,39 @@ void Curses::update_nav_data(const float& batteryPercent,
|
||||||
wmove(nav_data, 2, 10);
|
wmove(nav_data, 2, 10);
|
||||||
wprintw(nav_data, "%f %", time);
|
wprintw(nav_data, "%f %", time);
|
||||||
wmove(nav_data, 1, 10);
|
wmove(nav_data, 1, 10);
|
||||||
switch(state) {
|
switch (state) {
|
||||||
case 0:
|
case 0:
|
||||||
waddstr(nav_data, "unknown ");
|
waddstr(nav_data, "unknown ");
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
waddstr(nav_data, "inited ");
|
waddstr(nav_data, "inited ");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
waddstr(nav_data, "landed ");
|
waddstr(nav_data, "landed ");
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
waddstr(nav_data, "flying ");
|
waddstr(nav_data, "flying ");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
waddstr(nav_data, "hovering ");
|
waddstr(nav_data, "hovering ");
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
waddstr(nav_data, "test ");
|
waddstr(nav_data, "test ");
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
waddstr(nav_data, "taking off ");
|
waddstr(nav_data, "taking off ");
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
waddstr(nav_data, "flying ");
|
waddstr(nav_data, "flying ");
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
waddstr(nav_data, "landing ");
|
waddstr(nav_data, "landing ");
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
waddstr(nav_data, "looping ");
|
waddstr(nav_data, "looping ");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
;
|
{}
|
||||||
}
|
}
|
||||||
wrefresh(nav_data);
|
wrefresh(nav_data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,16 +16,15 @@
|
||||||
* along with Hand Control. If not, see <http://www.gnu.org/licenses/>.
|
* along with Hand Control. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CURSES_DISPLAY
|
#ifndef SRC_DISPLAY_H_
|
||||||
#define CURSES_DISPLAY
|
#define SRC_DISPLAY_H_
|
||||||
|
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
#include <string>
|
|
||||||
#include <geometry_msgs/Twist.h>
|
#include <geometry_msgs/Twist.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class Curses
|
class Curses {
|
||||||
{
|
private:
|
||||||
private:
|
|
||||||
static const int cmd_kbd_lines;
|
static const int cmd_kbd_lines;
|
||||||
static const int cmd_kbd_columns;
|
static const int cmd_kbd_columns;
|
||||||
WINDOW* cmd_kbd;
|
WINDOW* cmd_kbd;
|
||||||
|
@ -56,12 +55,11 @@ class Curses
|
||||||
WINDOW* topic;
|
WINDOW* topic;
|
||||||
void print_topic();
|
void print_topic();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Curses();
|
Curses();
|
||||||
~Curses();
|
~Curses();
|
||||||
char getchar();
|
char getchar();
|
||||||
|
|
||||||
// TODO
|
|
||||||
void update_cmd_speed(const char& coord, const float& v);
|
void update_cmd_speed(const char& coord, const float& v);
|
||||||
void update_nav_data(const float& batteryPercent,
|
void update_nav_data(const float& batteryPercent,
|
||||||
const int& state,
|
const int& state,
|
||||||
|
@ -70,4 +68,4 @@ class Curses
|
||||||
void update_topic(const geometry_msgs::Twist::ConstPtr& twist);
|
void update_topic(const geometry_msgs::Twist::ConstPtr& twist);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // SRC_DISPLAY_H_
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
/* Copyright © 2015 CentraleSupélec
|
/* Copyright © 2015 CentraleSupélec
|
||||||
*
|
*
|
||||||
|
|
||||||
* This file is part of Hand Control.
|
* This file is part of Hand Control.
|
||||||
*
|
*
|
||||||
|
|
||||||
* Hand Control is free software: you can redistribute it and/or modify
|
* Hand Control is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
|
|
||||||
* Hand Control is distributed in the hope that it will be useful,
|
* Hand Control is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
|
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with Hand Control. If not, see <http://www.gnu.org/licenses/>.
|
* along with Hand Control. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
@ -33,84 +37,93 @@ typedef pcl::PointCloud<Point> PointCloud;
|
||||||
typedef Eigen::Matrix3f& Matrix;
|
typedef Eigen::Matrix3f& Matrix;
|
||||||
|
|
||||||
class Callback {
|
class Callback {
|
||||||
public:
|
public:
|
||||||
void callback(const PointCloud::ConstPtr& msg)
|
|
||||||
// handles received messages and publish the plan estimation
|
// handles received messages and publish the plan estimation
|
||||||
{
|
void callback(const PointCloud::ConstPtr& msg) {
|
||||||
ROS_INFO("PointCloud received");
|
ROS_INFO("PointCloud received");
|
||||||
|
|
||||||
if (msg->width > 3){
|
if (msg->width > 3) {
|
||||||
// else, no plan can be estimated…
|
// else, no plan can be estimated…
|
||||||
|
analyser.setInputCloud(msg);
|
||||||
|
Matrix eg = analyser.getEigenVectors();
|
||||||
|
|
||||||
analyser.setInputCloud(msg);
|
// to build the "Plan" message to be published
|
||||||
Matrix eg = analyser.getEigenVectors();
|
float x, y, z, th, h, c;
|
||||||
|
x = y = z = th = h = c = 0.;
|
||||||
|
|
||||||
// to build the "Plan" message to be published
|
// v = eg_1 ^ eg_2 is the plan normal
|
||||||
float x, y, z, th, h, c;
|
Eigen::Vector3f v = eg.col(0).cross(eg.col(1));
|
||||||
x = y = z = th = h = c = 0.;
|
v.normalize(); // to have norm(v) == 1
|
||||||
|
|
||||||
// v = eg_1 ^ eg_2 is the plan normal
|
// x, y and z are the coords of the plan normal
|
||||||
Eigen::Vector3f v = eg.col(0).cross(eg.col(1));
|
if (!reverse) {
|
||||||
v.normalize(); // to have norm(v) == 1
|
x = v(0); y = v(1);
|
||||||
|
} else {
|
||||||
|
// if "x" and "y" axes are inverted
|
||||||
|
// (reverse is a parameter to set with dynamic_reconfigure)
|
||||||
|
x = v(1); y = v(0);
|
||||||
|
}
|
||||||
|
z = v(2);
|
||||||
|
|
||||||
// x, y and z are the coords of the plan normal
|
// h is the altitude
|
||||||
if (!reverse)
|
h = (analyser.getMean())(2);
|
||||||
{
|
|
||||||
x = v(0); y = v(1);
|
|
||||||
} else {
|
// angle calculation
|
||||||
// if "x" and "y" axes are inverted
|
|
||||||
// (reverse is a parameter to set with dynamic_reconfigure)
|
|
||||||
x = v(1); y = v(0);
|
// m_x and m_y are the "x" and "y" coords
|
||||||
|
// of the first principal component
|
||||||
|
float m_x, m_y;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// parameter to set
|
||||||
|
// with dynamic_reconfigure
|
||||||
|
if (reverse_angle) {
|
||||||
|
m_x = eg(0, 0);
|
||||||
|
m_y = eg(1, 0);
|
||||||
|
} else {
|
||||||
|
m_x = eg(1, 0);
|
||||||
|
m_y = eg(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// because we want "th" only between -90° and 90°
|
||||||
|
if (m_x < 0.)
|
||||||
|
m_y *= -1;
|
||||||
|
|
||||||
|
th = - asin(m_y / sqrt(pow(m_y, 2)+ pow(m_x, 2))); // 0 <= th <= pi
|
||||||
|
th *= _RAD2DEG; // -90 <= th <= 90
|
||||||
|
|
||||||
|
// TODO(someone)
|
||||||
|
// -> calculate "c" (the curvature)
|
||||||
|
// ( c == 0 for the moment)
|
||||||
|
|
||||||
|
// publication
|
||||||
|
ROS_INFO("Plan published");
|
||||||
|
publisher.publish(
|
||||||
|
to_Plan(
|
||||||
|
x, y, z, h, th, c,
|
||||||
|
msg->header.seq,
|
||||||
|
msg->header.stamp,
|
||||||
|
msg->width));
|
||||||
}
|
}
|
||||||
z = v(2);
|
|
||||||
|
|
||||||
// h is the altitude
|
|
||||||
h = (analyser.getMean())(2);
|
|
||||||
|
|
||||||
// angle calculation
|
|
||||||
|
|
||||||
// m_x and m_y are the "x" and "y" coords
|
|
||||||
// of the first principal component
|
|
||||||
float m_x, m_y;
|
|
||||||
|
|
||||||
if (reverse_angle)
|
|
||||||
// parameter to set
|
|
||||||
// with dynamic_reconfigure
|
|
||||||
{
|
|
||||||
m_x = eg(0,0);
|
|
||||||
m_y = eg(1,0);
|
|
||||||
} else {
|
|
||||||
m_x = eg(1,0);
|
|
||||||
m_y = eg(0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// because we want "th" only between -90° and 90°
|
|
||||||
if (m_x < 0.)
|
|
||||||
m_y *= -1;
|
|
||||||
|
|
||||||
th = - asin(m_y / sqrt(pow(m_y,2)+ pow(m_x,2))); // 0 <= th <= pi
|
|
||||||
th *= _RAD2DEG; // -90 <= th <= 90
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
// -> calculate "c" (the curvature)
|
|
||||||
// ( c == 0 for the moment)
|
|
||||||
|
|
||||||
// publication
|
|
||||||
ROS_INFO("Plan published");
|
|
||||||
publisher.publish(to_Plan(x, y, z, h, th, c, msg->header.seq, msg->header.stamp, msg->width));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Callback(ros::Publisher& pub):publisher(pub), _RAD2DEG(45.f/atan(1.)), reverse(false), reverse_angle(false) {};
|
explicit Callback(const ros::Publisher& pub) :
|
||||||
|
publisher(pub),
|
||||||
|
_RAD2DEG(45.f/atan(1.)),
|
||||||
|
reverse(false),
|
||||||
|
reverse_angle(false) {}
|
||||||
|
|
||||||
void reconfigure(const hand_control::EstimatorConfig& c, const uint32_t& level)
|
|
||||||
// updates the parameters received from dynamic_reconfigure
|
// updates the parameters received from dynamic_reconfigure
|
||||||
{
|
void reconfigure(const hand_control::EstimatorConfig& c,
|
||||||
reverse = c.reverse ;
|
const uint32_t& level) {
|
||||||
reverse_angle = c.reverse_angle;
|
reverse = c.reverse;
|
||||||
|
reverse_angle = c.reverse_angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ros::Publisher publisher;
|
ros::Publisher publisher;
|
||||||
pcl::PCA<Point> analyser;
|
pcl::PCA<Point> analyser;
|
||||||
const float _RAD2DEG;
|
const float _RAD2DEG;
|
||||||
|
@ -119,47 +132,48 @@ class Callback {
|
||||||
// return a "Plan" message build with
|
// return a "Plan" message build with
|
||||||
// the informations provided
|
// the informations provided
|
||||||
inline const hand_control::Plan::ConstPtr
|
inline const hand_control::Plan::ConstPtr
|
||||||
to_Plan(const float& x, const float& y,
|
to_Plan(const float& x, const float& y,
|
||||||
const float& z, const float& h,
|
const float& z, const float& h,
|
||||||
const float& th,
|
const float& th,
|
||||||
const float& c, const uint32_t& seq,
|
const float& c, const uint32_t& seq,
|
||||||
const uint64_t& msec64, const uint64_t& number)
|
const uint64_t& msec64, const uint64_t& number) {
|
||||||
{
|
hand_control::Plan::Ptr ros_msg(new hand_control::Plan());
|
||||||
hand_control::Plan::Ptr ros_msg(new hand_control::Plan());
|
ros_msg->normal.x = x;
|
||||||
ros_msg->normal.x = x;
|
ros_msg->normal.y = y;
|
||||||
ros_msg->normal.y = y;
|
ros_msg->normal.z = z;
|
||||||
ros_msg->normal.z = z;
|
|
||||||
ros_msg->altitude = h;
|
ros_msg->altitude = h;
|
||||||
ros_msg->angle = th;
|
ros_msg->angle = th;
|
||||||
ros_msg->curvature = c;
|
ros_msg->curvature = c;
|
||||||
ros_msg->number = number;
|
|
||||||
uint64_t sec64 = msec64 / 1000000;
|
ros_msg->number = number;
|
||||||
uint64_t nsec64 = (msec64 % 1000000) * 1000;
|
uint64_t sec64 = msec64 / 1000000;
|
||||||
ros_msg->header.stamp.sec = (uint32_t) sec64;
|
uint64_t nsec64 = (msec64 % 1000000) * 1000;
|
||||||
ros_msg->header.stamp.nsec = (uint32_t) nsec64;
|
ros_msg->header.stamp.sec = (uint32_t) sec64;
|
||||||
ros_msg->header.seq = seq;
|
ros_msg->header.stamp.nsec = (uint32_t) nsec64;
|
||||||
ros_msg->header.frame_id = "0";
|
ros_msg->header.seq = seq;
|
||||||
return ros_msg;
|
ros_msg->header.frame_id = "0";
|
||||||
}
|
return ros_msg;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv) {
|
||||||
{
|
ros::init(argc, argv, "estimator");
|
||||||
ros::init(argc, argv, "estimator");
|
ros::NodeHandle node("estimator");
|
||||||
ros::NodeHandle node("estimator");
|
ros::Publisher publisher = node.advertise<hand_control::Plan>("output", 1);
|
||||||
ros::Publisher publisher = node.advertise<hand_control::Plan>("output", 1);
|
Callback callback(publisher);
|
||||||
Callback callback(publisher);
|
ros::Subscriber subscriber =
|
||||||
ros::Subscriber subscriber = node.subscribe<PointCloud>("input", 1, &Callback::callback, &callback);
|
node.subscribe<PointCloud>("input", 1, &Callback::callback, &callback);
|
||||||
|
|
||||||
// sets up dynamic_reconfigure
|
// sets up dynamic_reconfigure
|
||||||
dynamic_reconfigure::Server<hand_control::EstimatorConfig> server;
|
dynamic_reconfigure::Server<hand_control::EstimatorConfig> server;
|
||||||
dynamic_reconfigure::Server<hand_control::EstimatorConfig>::CallbackType f;
|
dynamic_reconfigure::Server<hand_control::EstimatorConfig>::CallbackType f;
|
||||||
f = boost::bind(&Callback::reconfigure, &callback, _1, _2);
|
f = boost::bind(&Callback::reconfigure, &callback, _1, _2);
|
||||||
server.setCallback(f);
|
server.setCallback(f);
|
||||||
|
|
||||||
// begins working
|
// begins working
|
||||||
ROS_INFO("node started");
|
ROS_INFO("node started");
|
||||||
ros::spin();
|
ros::spin();
|
||||||
ROS_INFO("exit");
|
ROS_INFO("exit");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
165
src/filter.cpp
165
src/filter.cpp
|
@ -16,109 +16,122 @@
|
||||||
* along with Hand Control. If not, see <http://www.gnu.org/licenses/>.
|
* along with Hand Control. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <hand_control/FilterConfig.h>
|
||||||
#include <ros/ros.h>
|
#include <ros/ros.h>
|
||||||
#include <pcl_ros/point_cloud.h>
|
#include <pcl_ros/point_cloud.h>
|
||||||
#include <pcl/point_types.h>
|
#include <pcl/point_types.h>
|
||||||
#include <pcl/tracking/impl/hsv_color_coherence.hpp>
|
#include <pcl/tracking/impl/hsv_color_coherence.hpp>
|
||||||
#include <assert.h>
|
|
||||||
#include <dynamic_reconfigure/server.h>
|
#include <dynamic_reconfigure/server.h>
|
||||||
#include <hand_control/FilterConfig.h>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
typedef pcl::PointXYZRGB Point;
|
typedef pcl::PointXYZRGB Point;
|
||||||
typedef pcl::PointCloud<Point> PointCloud;
|
typedef pcl::PointCloud<Point> PointCloud;
|
||||||
|
|
||||||
class Callback {
|
class Callback {
|
||||||
public:
|
public:
|
||||||
void
|
|
||||||
callback(const PointCloud::ConstPtr& msg)
|
|
||||||
// handles and filters the received PointCloud and
|
// handles and filters the received PointCloud and
|
||||||
// publishes the filtered PointCloud
|
// publishes the filtered PointCloud
|
||||||
{
|
void callback(const PointCloud::ConstPtr& msg) {
|
||||||
PointCloud::Ptr pcl(new PointCloud());
|
PointCloud::Ptr pcl(new PointCloud());
|
||||||
copy_info(msg, pcl); // copy the header
|
copy_info(msg, pcl); // copy the header
|
||||||
BOOST_FOREACH (const Point& pt, msg->points)
|
BOOST_FOREACH(const Point& pt, msg->points) {
|
||||||
{
|
float hue_dist, sat, val;
|
||||||
float hue_dist, sat, val;
|
hdist_s_v(pt, hue_dist, sat, val);
|
||||||
hdist_s_v(pt, hue_dist, sat, val);
|
if (pt.z < z_max &&
|
||||||
if (pt.z < z_max and hue_dist < delta_hue and sat < sat_max and sat > sat_min and val < val_max and val > val_min)
|
hue_dist < delta_hue &&
|
||||||
pcl->push_back(pt);
|
sat < sat_max &&
|
||||||
}
|
sat > sat_min &&
|
||||||
pcl->height = 1;
|
val < val_max &&
|
||||||
pcl->width = pcl->points.size();
|
val > val_min) {
|
||||||
publisher.publish(pcl);
|
pcl->push_back(pt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pcl->height = 1;
|
||||||
|
pcl->width = pcl->points.size();
|
||||||
|
publisher.publish(pcl);
|
||||||
}
|
}
|
||||||
|
|
||||||
Callback(const ros::Publisher& pub)
|
explicit Callback(const ros::Publisher& pub) :
|
||||||
: publisher(pub), z_max(90.), hue(0.), delta_hue(20.), sat_min(0.3), sat_max(1.), val_min(0.3), val_max(1.)
|
publisher(pub),
|
||||||
{}
|
z_max(90.),
|
||||||
|
hue(0.),
|
||||||
|
delta_hue(20.),
|
||||||
|
sat_min(0.3),
|
||||||
|
sat_max(1.),
|
||||||
|
val_min(0.3),
|
||||||
|
val_max(1.) {}
|
||||||
|
|
||||||
void
|
|
||||||
reconfigure(const hand_control::FilterConfig& c, const uint32_t& level)
|
|
||||||
// updates the parameters
|
// updates the parameters
|
||||||
{
|
void reconfigure(const hand_control::FilterConfig& c,
|
||||||
z_max = c.z_max;
|
const uint32_t& level) {
|
||||||
hue = c.hue;
|
z_max = c.z_max;
|
||||||
delta_hue = c.delta_hue;
|
hue = c.hue;
|
||||||
val_min = c.val_min;
|
delta_hue = c.delta_hue;
|
||||||
val_max = c.val_max;
|
val_min = c.val_min;
|
||||||
sat_min = c.sat_min;
|
val_max = c.val_max;
|
||||||
sat_max = c.sat_max;
|
sat_min = c.sat_min;
|
||||||
|
sat_max = c.sat_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ros::Publisher publisher;
|
ros::Publisher publisher;
|
||||||
float z_max, hue, delta_hue, val_min, val_max, sat_min, sat_max;
|
float z_max, hue, delta_hue, val_min,
|
||||||
|
val_max, sat_min, sat_max;
|
||||||
|
|
||||||
inline
|
|
||||||
void
|
|
||||||
copy_info(const PointCloud::ConstPtr& a,
|
|
||||||
PointCloud::Ptr& b)
|
|
||||||
// copy the header info (useful in order to use rviz)
|
// copy the header info (useful in order to use rviz)
|
||||||
{
|
inline void copy_info(const PointCloud::ConstPtr& a,
|
||||||
b->header = a->header;
|
PointCloud::Ptr& b) {
|
||||||
b->sensor_origin_ = a->sensor_origin_;
|
b->header = a->header;
|
||||||
b->sensor_orientation_ = a->sensor_orientation_;
|
b->sensor_origin_ = a->sensor_origin_;
|
||||||
b->is_dense = a->is_dense;
|
b->sensor_orientation_ = a->sensor_orientation_;
|
||||||
|
b->is_dense = a->is_dense;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
// calculate the distance from the wished hue,
|
||||||
void
|
// the saturation and the value of the point
|
||||||
hdist_s_v(const Point& pt, float& h_dist, float& s, float& v)
|
inline void hdist_s_v(const Point& pt,
|
||||||
// calculate the distance from the wished hue, the saturation and the value
|
float& h_dist,
|
||||||
// of the point
|
float& s,
|
||||||
{
|
float& v) {
|
||||||
float h, diff1, diff2;
|
float h, diff1, diff2;
|
||||||
pcl::tracking::RGB2HSV(pt.r, pt.g, pt.b, h, s, v);
|
pcl::tracking::RGB2HSV(pt.r, pt.g, pt.b, h, s, v);
|
||||||
h *= 360.0f ;
|
h *= 360.0f;
|
||||||
diff1 = std::fabs(h - hue);
|
diff1 = std::fabs(h - hue);
|
||||||
// hue is periodic
|
// hue is periodic
|
||||||
if (h < hue)
|
if (h < hue)
|
||||||
diff2 = std::fabs(360.0f + h - hue);
|
diff2 = std::fabs(360.0f + h - hue);
|
||||||
else
|
else
|
||||||
diff2 = std::fabs(360.0f + hue - h);
|
diff2 = std::fabs(360.0f + hue - h);
|
||||||
h_dist = std::min(diff1, diff2);
|
h_dist = std::min(diff1, diff2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int main(int argc, char** argv) {
|
||||||
main(int argc, char** argv)
|
ros::init(argc, argv, "filter");
|
||||||
{
|
ros::NodeHandle node("filter");
|
||||||
ros::init(argc, argv, "filter");
|
|
||||||
ros::NodeHandle node("filter");
|
|
||||||
ros::Publisher publisher = node.advertise<PointCloud>("output", 1);
|
|
||||||
Callback my_callback(publisher);
|
|
||||||
ros::Subscriber subscriber = node.subscribe<PointCloud>("input", 1, &Callback::callback, &my_callback);
|
|
||||||
|
|
||||||
// sets up dynamic_reconfigure
|
ros::Publisher publisher =
|
||||||
dynamic_reconfigure::Server<hand_control::FilterConfig> server;
|
node.advertise<PointCloud>("output", 1);
|
||||||
dynamic_reconfigure::Server<hand_control::FilterConfig>::CallbackType f;
|
|
||||||
f = boost::bind(&Callback::reconfigure, &my_callback, _1, _2);
|
|
||||||
server.setCallback(f);
|
|
||||||
|
|
||||||
// begins working
|
Callback my_callback(publisher);
|
||||||
ROS_INFO("node started");
|
|
||||||
ros::spin();
|
ros::Subscriber subscriber =
|
||||||
ROS_INFO("exit");
|
node.subscribe<PointCloud>("input", 1,
|
||||||
return 0;
|
&Callback::callback,
|
||||||
|
&my_callback);
|
||||||
|
|
||||||
|
// sets up dynamic_reconfigure
|
||||||
|
dynamic_reconfigure::Server<hand_control::FilterConfig> server;
|
||||||
|
dynamic_reconfigure::Server<hand_control::FilterConfig>::CallbackType f;
|
||||||
|
f = boost::bind(&Callback::reconfigure, &my_callback, _1, _2);
|
||||||
|
server.setCallback(f);
|
||||||
|
|
||||||
|
// begins working
|
||||||
|
ROS_INFO("node started");
|
||||||
|
ros::spin();
|
||||||
|
ROS_INFO("exit");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,280 +16,254 @@
|
||||||
* along with Hand Control. If not, see <http://www.gnu.org/licenses/>.
|
* along with Hand Control. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <ros/ros.h>
|
#include <ros/ros.h>
|
||||||
#include <ros/time.h>
|
#include <ros/time.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include "display.h"
|
|
||||||
|
|
||||||
#include <std_msgs/Empty.h>
|
#include <std_msgs/Empty.h>
|
||||||
#include <geometry_msgs/Twist.h>
|
#include <geometry_msgs/Twist.h>
|
||||||
#include <ardrone_autonomy/Navdata.h>
|
#include <ardrone_autonomy/Navdata.h>
|
||||||
|
|
||||||
class NavdataCallback
|
#include "./display.h"
|
||||||
{
|
|
||||||
private:
|
class NavdataCallback {
|
||||||
|
private:
|
||||||
boost::shared_ptr<Curses> term;
|
boost::shared_ptr<Curses> term;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NavdataCallback(const boost::shared_ptr<Curses>& terminal) :
|
explicit NavdataCallback(const boost::shared_ptr<Curses>& terminal) :
|
||||||
term(terminal) {}
|
term(terminal) {}
|
||||||
|
|
||||||
void operator()(const ardrone_autonomy::Navdata::ConstPtr& msg) {
|
void operator()(const ardrone_autonomy::Navdata::ConstPtr& msg) {
|
||||||
term->update_nav_data(msg->batteryPercent, msg->state, msg->tm);
|
term->update_nav_data(msg->batteryPercent, msg->state, msg->tm);
|
||||||
}
|
}
|
||||||
}; // class NavdataCallback
|
};
|
||||||
|
|
||||||
class CmdVelCallback
|
class CmdVelCallback {
|
||||||
{
|
private:
|
||||||
private:
|
|
||||||
boost::shared_ptr<Curses> term;
|
boost::shared_ptr<Curses> term;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CmdVelCallback(const boost::shared_ptr<Curses>& terminal) :
|
explicit CmdVelCallback(const boost::shared_ptr<Curses>& terminal) :
|
||||||
term(terminal) {}
|
term(terminal) {}
|
||||||
|
|
||||||
void operator()(const geometry_msgs::Twist::ConstPtr& msg) {
|
void operator()(const geometry_msgs::Twist::ConstPtr& msg) {
|
||||||
term->update_topic(msg);
|
term->update_topic(msg);
|
||||||
}
|
}
|
||||||
}; // class CmdVelCallback
|
};
|
||||||
|
|
||||||
class Run
|
class Run {
|
||||||
{
|
private:
|
||||||
private:
|
|
||||||
std_msgs::Empty empty;
|
std_msgs::Empty empty;
|
||||||
ros::NodeHandle n;
|
ros::NodeHandle n;
|
||||||
ros::Rate loop_rate;
|
ros::Rate loop_rate;
|
||||||
ros::Publisher cmd, pub_takeoff, pub_land, pub_reset;
|
ros::Publisher cmd, pub_takeoff, pub_land, pub_reset;
|
||||||
ros::Subscriber data_subscriber, cmdvel_subscriber;
|
ros::Subscriber data_subscriber, cmdvel_subscriber;
|
||||||
void land() { pub_land.publish(empty); };
|
void land() { pub_land.publish(empty); }
|
||||||
void takeoff() { pub_takeoff.publish(empty); };
|
void takeoff() { pub_takeoff.publish(empty); }
|
||||||
void reset() { pub_reset.publish(empty); };
|
void reset() { pub_reset.publish(empty); }
|
||||||
float x_speed, y_speed, z_speed, turn;
|
float x_speed, y_speed, z_speed, turn;
|
||||||
boost::shared_ptr<Curses> term;
|
boost::shared_ptr<Curses> term;
|
||||||
NavdataCallback data_callback;
|
NavdataCallback data_callback;
|
||||||
CmdVelCallback cmdvel_callback;
|
CmdVelCallback cmdvel_callback;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Run(const boost::shared_ptr<Curses>& terminal) :
|
explicit Run(const boost::shared_ptr<Curses>& terminal) :
|
||||||
data_callback(terminal),
|
data_callback(terminal),
|
||||||
cmdvel_callback(terminal),
|
cmdvel_callback(terminal),
|
||||||
term(terminal),
|
term(terminal),
|
||||||
loop_rate(30),
|
loop_rate(30),
|
||||||
x_speed(0.1),
|
x_speed(0.1),
|
||||||
y_speed(0.1),
|
y_speed(0.1),
|
||||||
z_speed(0.1),
|
z_speed(0.1),
|
||||||
turn(0.1) {
|
turn(0.1) {
|
||||||
cmd = n.advertise<geometry_msgs::Twist>("/cmd_vel",1);
|
cmd = n.advertise<geometry_msgs::Twist>("/cmd_vel", 1);
|
||||||
pub_takeoff = n.advertise<std_msgs::Empty>("/ardrone/takeoff", 1);
|
pub_takeoff = n.advertise<std_msgs::Empty>("/ardrone/takeoff", 1);
|
||||||
pub_land = n.advertise<std_msgs::Empty>("/ardrone/land", 1);
|
pub_land = n.advertise<std_msgs::Empty>("/ardrone/land", 1);
|
||||||
pub_reset = n.advertise<std_msgs::Empty>("/ardrone/reset", 1);
|
pub_reset = n.advertise<std_msgs::Empty>("/ardrone/reset", 1);
|
||||||
data_subscriber = n.subscribe<ardrone_autonomy::Navdata>("/ardrone/navdata", 1, data_callback);
|
|
||||||
cmdvel_subscriber = n.subscribe<geometry_msgs::Twist>("/cmd_vel", 1, cmdvel_callback);
|
|
||||||
|
|
||||||
term->update_cmd_speed('x', x_speed);
|
data_subscriber =
|
||||||
term->update_cmd_speed('y', y_speed);
|
n.subscribe<ardrone_autonomy::Navdata>(
|
||||||
term->update_cmd_speed('z', z_speed);
|
"/ardrone/navdata", 1, data_callback);
|
||||||
term->update_cmd_speed('t', turn);
|
|
||||||
|
|
||||||
float a(0);
|
cmdvel_subscriber =
|
||||||
int s(0);
|
n.subscribe<geometry_msgs::Twist>(
|
||||||
float time(0);
|
"/cmd_vel", 1, cmdvel_callback);
|
||||||
term->update_nav_data(a, s, time);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()()
|
term->update_cmd_speed('x', x_speed);
|
||||||
{
|
term->update_cmd_speed('y', y_speed);
|
||||||
while (ros::ok())
|
term->update_cmd_speed('z', z_speed);
|
||||||
{
|
term->update_cmd_speed('t', turn);
|
||||||
ros::spinOnce();
|
|
||||||
|
|
||||||
geometry_msgs::Twist::Ptr msg(new geometry_msgs::Twist());
|
float a(0);
|
||||||
msg->linear.x = msg->linear.y = msg->linear.z =
|
int s(0);
|
||||||
msg->angular.x = msg->angular.y = msg->angular.z = 0.;
|
float time(0);
|
||||||
|
term->update_nav_data(a, s, time);
|
||||||
|
}
|
||||||
|
|
||||||
char c = term->getchar();
|
void operator()() {
|
||||||
|
while (ros::ok()) {
|
||||||
|
ros::spinOnce();
|
||||||
|
|
||||||
switch(c)
|
geometry_msgs::Twist::Ptr msg(new geometry_msgs::Twist());
|
||||||
{
|
msg->linear.x = msg->linear.y = msg->linear.z =
|
||||||
case 'k' :
|
msg->angular.x = msg->angular.y = msg->angular.z = 0.;
|
||||||
{// hover
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("hover !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'i' :
|
|
||||||
{// forward
|
|
||||||
msg->linear.x = x_speed;
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("forward !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ';' :
|
|
||||||
{// backward
|
|
||||||
msg->linear.x = -x_speed;
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("backward !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'h' :
|
|
||||||
{//translate left
|
|
||||||
msg->linear.y = -y_speed;
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("translate left !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'm' :
|
|
||||||
{//translate right
|
|
||||||
msg->linear.y = y_speed;
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("translate right !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'j' :
|
|
||||||
{//rotate left
|
|
||||||
msg->angular.z = turn;
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("rotate left !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'l' :
|
|
||||||
{//rotate right
|
|
||||||
msg->angular.z = -turn;
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("rotate right !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'u' :
|
|
||||||
{//turn left
|
|
||||||
msg->angular.z = turn;
|
|
||||||
msg->linear.x = x_speed;
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("forward left !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'o' :
|
|
||||||
{//turn right
|
|
||||||
msg->angular.z = -turn;
|
|
||||||
msg->linear.x = x_speed;
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("forward right !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ',' :
|
|
||||||
{//turn left backward
|
|
||||||
msg->angular.z = turn;
|
|
||||||
msg->linear.x = -x_speed;
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("backward left !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ':' :
|
|
||||||
{//turn right backward
|
|
||||||
msg->angular.z = -turn;
|
|
||||||
msg->linear.x = -x_speed;
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("backward right !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'y' :
|
|
||||||
{//up
|
|
||||||
msg->linear.z = z_speed;
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("up !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'n' :
|
|
||||||
{//down
|
|
||||||
msg->linear.z = -z_speed;
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("down !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 't' :
|
|
||||||
{//takeoff
|
|
||||||
takeoff();
|
|
||||||
term->log_sent("takeoff !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'b' :
|
|
||||||
{//land
|
|
||||||
land();
|
|
||||||
term->log_sent("land !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'g' :
|
|
||||||
{//reset
|
|
||||||
reset();
|
|
||||||
term->log_sent("reset !");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'a' :
|
|
||||||
{// + x_speed
|
|
||||||
x_speed *= 1.1;
|
|
||||||
term->update_cmd_speed('x', x_speed);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'w' :
|
|
||||||
{// - x_speed
|
|
||||||
x_speed *= 0.9;
|
|
||||||
term->update_cmd_speed('x', x_speed);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'z' :
|
|
||||||
{// + y_speed
|
|
||||||
y_speed *= 1.1;
|
|
||||||
term->update_cmd_speed('y', y_speed);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'x' :
|
|
||||||
{// - y_speed
|
|
||||||
y_speed *= 0.9;
|
|
||||||
term->update_cmd_speed('y', y_speed);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'e' :
|
|
||||||
{// + z_speed
|
|
||||||
z_speed *= 1.1;
|
|
||||||
term->update_cmd_speed('z', z_speed);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'c' :
|
|
||||||
{// - z_speed
|
|
||||||
z_speed *= 0.9;
|
|
||||||
term->update_cmd_speed('z', z_speed);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'r' :
|
|
||||||
{// + turn speed
|
|
||||||
turn *= 1.1;
|
|
||||||
term->update_cmd_speed('t', turn);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'v' :
|
|
||||||
{// - turn speed
|
|
||||||
turn *= 0.9;
|
|
||||||
term->update_cmd_speed('t', turn);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default :
|
|
||||||
{
|
|
||||||
cmd.publish(msg);
|
|
||||||
term->log_sent("hover !");
|
|
||||||
}
|
|
||||||
} // switch(c)
|
|
||||||
loop_rate.sleep();
|
|
||||||
} // while
|
|
||||||
} //void run()
|
|
||||||
|
|
||||||
}; // class Run
|
char c = term->getchar();
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
switch (c) {
|
||||||
{
|
case 'k' : { // hover
|
||||||
setlocale(LC_ALL, "");
|
cmd.publish(msg);
|
||||||
ros::init(argc, argv, "keyboard_cmd");
|
term->log_sent("hover !");
|
||||||
boost::shared_ptr<Curses> term(new Curses());
|
break;
|
||||||
Run fun(term);
|
}
|
||||||
fun();
|
case 'i' : { // forward
|
||||||
return 0;
|
msg->linear.x = x_speed;
|
||||||
} // main
|
cmd.publish(msg);
|
||||||
|
term->log_sent("forward !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ';' : { // backward
|
||||||
|
msg->linear.x = -x_speed;
|
||||||
|
cmd.publish(msg);
|
||||||
|
term->log_sent("backward !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'h' : { // translate left
|
||||||
|
msg->linear.y = -y_speed;
|
||||||
|
cmd.publish(msg);
|
||||||
|
term->log_sent("translate left !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'm' : { // translate right
|
||||||
|
msg->linear.y = y_speed;
|
||||||
|
cmd.publish(msg);
|
||||||
|
term->log_sent("translate right !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'j' : { // rotate left
|
||||||
|
msg->angular.z = turn;
|
||||||
|
cmd.publish(msg);
|
||||||
|
term->log_sent("rotate left !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'l' : { // rotate right
|
||||||
|
msg->angular.z = -turn;
|
||||||
|
cmd.publish(msg);
|
||||||
|
term->log_sent("rotate right !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'u' : { // turn left
|
||||||
|
msg->angular.z = turn;
|
||||||
|
msg->linear.x = x_speed;
|
||||||
|
cmd.publish(msg);
|
||||||
|
term->log_sent("forward left !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'o' : { // turn right
|
||||||
|
msg->angular.z = -turn;
|
||||||
|
msg->linear.x = x_speed;
|
||||||
|
cmd.publish(msg);
|
||||||
|
term->log_sent("forward right !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ',' : { // turn left backward
|
||||||
|
msg->angular.z = turn;
|
||||||
|
msg->linear.x = -x_speed;
|
||||||
|
cmd.publish(msg);
|
||||||
|
term->log_sent("backward left !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ':' : { // turn right backward
|
||||||
|
msg->angular.z = -turn;
|
||||||
|
msg->linear.x = -x_speed;
|
||||||
|
cmd.publish(msg);
|
||||||
|
term->log_sent("backward right !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'y' : { // up
|
||||||
|
msg->linear.z = z_speed;
|
||||||
|
cmd.publish(msg);
|
||||||
|
term->log_sent("up !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'n' : { // down
|
||||||
|
msg->linear.z = -z_speed;
|
||||||
|
cmd.publish(msg);
|
||||||
|
term->log_sent("down !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 't' : { // takeoff
|
||||||
|
takeoff();
|
||||||
|
term->log_sent("takeoff !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'b' : { // land
|
||||||
|
land();
|
||||||
|
term->log_sent("land !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'g' : { // reset
|
||||||
|
reset();
|
||||||
|
term->log_sent("reset !");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'a' : { // + x_speed
|
||||||
|
x_speed *= 1.1;
|
||||||
|
term->update_cmd_speed('x', x_speed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'w' : { // - x_speed
|
||||||
|
x_speed *= 0.9;
|
||||||
|
term->update_cmd_speed('x', x_speed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'z' : { // + y_speed
|
||||||
|
y_speed *= 1.1;
|
||||||
|
term->update_cmd_speed('y', y_speed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'x' : { // - y_speed
|
||||||
|
y_speed *= 0.9;
|
||||||
|
term->update_cmd_speed('y', y_speed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'e' : { // + z_speed
|
||||||
|
z_speed *= 1.1;
|
||||||
|
term->update_cmd_speed('z', z_speed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'c' : { // - z_speed
|
||||||
|
z_speed *= 0.9;
|
||||||
|
term->update_cmd_speed('z', z_speed);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'r' : { // + turn speed
|
||||||
|
turn *= 1.1;
|
||||||
|
term->update_cmd_speed('t', turn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'v' : { // - turn speed
|
||||||
|
turn *= 0.9;
|
||||||
|
term->update_cmd_speed('t', turn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : {
|
||||||
|
cmd.publish(msg);
|
||||||
|
term->log_sent("hover !");
|
||||||
|
}
|
||||||
|
} // switch(c)
|
||||||
|
loop_rate.sleep();
|
||||||
|
} // while
|
||||||
|
} // void run()
|
||||||
|
}; // class Run
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
ros::init(argc, argv, "keyboard_cmd");
|
||||||
|
boost::shared_ptr<Curses> term(new Curses());
|
||||||
|
Run fun(term);
|
||||||
|
fun();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue