rovio_move.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  * Software License Agreement (BSD License)
00004  *
00005  *  Copyright (c) 2012, Worcester Polytechnic Institute
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions
00010  *  are met:
00011  *
00012  *   * Redistributions of source code must retain the above copyright
00013  *     notice, this list of conditions and the following disclaimer.
00014  *   * Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions and the following
00016  *     disclaimer in the documentation and/or other materials provided
00017  *     with the distribution.
00018  *   * Neither the name of the Worcester Polytechnic Institute nor the
00019  *     names of its contributors may be used to endorse or promote
00020  *     products derived from this software without specific prior
00021  *     written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  *********************************************************************/
00037 
00049 #include <algorithm>
00050 #include <geometry_msgs/Twist.h>
00051 #include <math.h>
00052 #include <ros/ros.h>
00053 #include <rovio_shared/man_drv.h>
00054 #include <rovio_shared/rovio_http.h>
00055 #include <rovio_ctrl/rovio_move.h>
00056 #include <sstream>
00057 #include <string>
00058 
00059 using namespace std;
00060 
00061 move_controller::move_controller()
00062 {
00063   string user;
00064   string pass;
00065 
00066   // check for all the correct parameters
00067   if (!node.getParam(USER, user))
00068   {
00069     ROS_ERROR("Parameter %s not found.", USER);
00070     exit(-1);
00071   }
00072   if (!node.getParam(PASS, pass))
00073   {
00074     ROS_ERROR("Parameter %s not found.", PASS);
00075     exit(-1);
00076   }
00077   if (!node.getParam(HOST, host))
00078   {
00079     ROS_ERROR("Parameter %s not found.", HOST);
00080     exit(-1);
00081   }
00082 
00083   // create the communication object to talk to Rovio
00084   rovio = new rovio_http(user, pass);
00085 
00086   // add subscriptions that will control the Rovio
00087   man_drv = node.subscribe<rovio_shared::man_drv>("man_drv", 10, &move_controller::man_drv_callback, this);
00088   cmd_vel = node.subscribe<geometry_msgs::Twist>("cmd_vel", 10, &move_controller::cmd_vel_callback, this);
00089 
00090   drive = 0;
00091   speed = 0;
00092   rotate = 0;
00093 
00094   ROS_INFO("Rovio Move Controller Initialized");
00095 }
00096 
00097 move_controller::~move_controller()
00098 {
00099   // free up the rovio_http object
00100   delete rovio;
00101 }
00102 
00103 void move_controller::update()
00104 {
00105   // check for a drive command
00106   if (drive > 0)
00107   {
00108     // build the URL command and send it
00109     stringstream ss;
00110     ss << "http://" << host.c_str() << "/rev.cgi?Cmd=nav&action=18&drive=" << drive << "&speed=" << speed;
00111     rovio_response *buf = rovio->send(ss.str().c_str());
00112     rovio_response_clean(buf);
00113   }
00114   // check for a rotation command
00115   if (rotate > 0)
00116   {
00117     // build the URL command and send it
00118     stringstream ss;
00119     ss << "http://" << host.c_str() << "/rev.cgi?Cmd=nav&action=18&drive=6&speed=" << rotate;
00120     rovio_response *buf = rovio->send(ss.str().c_str());
00121     rovio_response_clean(buf);
00122   }
00123   else if (rotate < 0)
00124   {
00125     // build the URL command and send it
00126     stringstream ss;
00127     ss << "http://" << host.c_str() << "/rev.cgi?Cmd=nav&action=18&drive=5&speed=" << -rotate;
00128     rovio_response *buf = rovio->send(ss.str().c_str());
00129     rovio_response_clean(buf);
00130   }
00131 }
00132 
00133 void move_controller::man_drv_callback(const rovio_shared::man_drv::ConstPtr &msg)
00134 {
00135   // check to see if all the requests are valid
00136   if (msg->drive < rovio_shared::man_drv::MIN_DRIVE_VAL || msg->drive > rovio_shared::man_drv::MAX_DRIVE_VAL)
00137   {
00138     ROS_ERROR(
00139         "Manual Drive 'drive' value of %i out of range [%i,%i].", msg->drive, rovio_shared::man_drv::MIN_DRIVE_VAL, rovio_shared::man_drv::MAX_DRIVE_VAL);
00140     return;
00141   }
00142   if (msg->speed < rovio_shared::man_drv::MIN_SPEED_VAL || msg->speed > rovio_shared::man_drv::MAX_SPEED_VAL)
00143   {
00144     ROS_ERROR(
00145         "Manual Drive 'speed' value of %i out of range [%i,%i].", msg->speed, rovio_shared::man_drv::MIN_SPEED_VAL, rovio_shared::man_drv::MAX_SPEED_VAL);
00146     return;
00147   }
00148 
00149   // set the values
00150   drive = msg->drive;
00151   speed = msg->speed;
00152 }
00153 
00154 void move_controller::cmd_vel_callback(const geometry_msgs::Twist::ConstPtr &msg)
00155 {
00156   // check if we are moving left or right
00157   if (msg->linear.x == 0 && msg->linear.y > 0)
00158   {
00159     // drive left
00160     drive = 3;
00161   }
00162   else if (msg->linear.x == 0 && msg->linear.y < 0)
00163   {
00164     // drive right
00165     drive = 4;
00166   }
00167   else
00168   {
00169     // calculate the angle
00170     double angle = atan2(msg->linear.x, msg->linear.y);
00171     // bound the movements to one of the discrete Rovio drive commands
00172     if (msg->linear.x > 0 && angle <= 5 * M_PI / 8 && angle >= 3 * M_PI / 8)
00173     {
00174       // drive forwards
00175       drive = 1;
00176     }
00177     else if (msg->linear.x > 0 && msg->linear.y > 0 && angle < 3 * M_PI / 8 && angle >= M_PI / 8)
00178     {
00179       // drive forwards and right
00180       drive = 8;
00181     }
00182     else if (msg->linear.y > 0 && (angle >= -1 * M_PI / 8 || angle >= 3 * M_PI / 8))
00183     {
00184       // drive right
00185       drive = 4;
00186     }
00187     else if (msg->linear.x < 0 && msg->linear.y > 0 && angle < -1 * M_PI / 8 && angle >= -3 * M_PI / 8)
00188     {
00189       // drive backwards and right
00190       drive = 10;
00191     }
00192     else if (msg->linear.x < 0 && angle <= -3 * M_PI / 8 && angle >= -5 * M_PI / 8)
00193     {
00194       // drive backwards
00195       drive = 2;
00196     }
00197     else if (msg->linear.x < 0 && msg->linear.y < 0 && angle <= -5 * M_PI / 8 && angle >= -7 * M_PI / 8)
00198     {
00199       // drive backwards and left
00200       drive = 9;
00201     }
00202     else if (msg->linear.y < 0 && (angle < -7 * M_PI / 8 || angle >= 7 * M_PI / 8))
00203     {
00204       // drive left
00205       drive = 3;
00206     }
00207     else if (msg->linear.x > 0 && msg->linear.y < 0 && angle < 7 * M_PI / 8 && angle >= 5 * M_PI / 8)
00208     {
00209       // drive forwards and left
00210       drive = 7;
00211     }
00212     else
00213     {
00214       // no movement
00215       drive = 0;
00216     }
00217   }
00218 
00219   // get the rotational speed
00220   rotate = -msg->angular.z * 10.0;
00221 
00222   // get the linear speed (10 being the fastest)
00223   speed = min(10, (int)(sqrt(pow(msg->linear.x, 2.0) + pow(msg->linear.y, 2.0)) * 10));
00224 }
00225 
00226 int main(int argc, char **argv)
00227 {
00228   // initialize ROS and the node
00229   ros::init(argc, argv, "rovio_move");
00230 
00231   // initialize the Rovio controller
00232   move_controller controller;
00233 
00234   // update at 5 Hz
00235   ros::Rate loop_rate(5);
00236   // continue until a ctrl-c has occurred
00237   while (ros::ok())
00238   {
00239     ros::spinOnce();
00240     // update the motors
00241     controller.update();
00242     loop_rate.sleep();
00243   }
00244 }


rovio_ctrl
Author(s): Russell Toris
autogenerated on Sat Dec 28 2013 17:38:53