rflex.cc

00001 /*  Player - One Hell of a Robot Server
00002  *  Copyright (C) 2000
00003  *     Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard
00004  *
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 /* notes:
00023  * the Main thread continues running when no-one is connected
00024  * this we retain our odometry data, whether anyone is connected or not
00025  */
00026 
00027 /* Modified by Toby Collett, University of Auckland 2003-02-25
00028  * Added support for bump sensors for RWI b21r robot, uses DIO
00029  */
00030 
00296 #include <fcntl.h>
00297 #include <signal.h>
00298 #include <sys/stat.h>
00299 #include <sys/types.h>
00300 #include <stdio.h>
00301 #include <string.h>
00302 #include <unistd.h>
00303 #include <math.h>
00304 #include <stdlib.h>  /* for abs() */
00305 #include <netinet/in.h>
00306 #include <termios.h>
00307 #include <assert.h>
00308 
00309 #include "rflex.h"
00310 #include "rflex_configs.h"
00311 
00312 //rflex communications stuff
00313 #include "rflex_commands.h"
00314 #include "rflex-io.h"
00315 
00316 #include <libplayercore/playercore.h>
00317 #include <libplayerxdr/playerxdr.h>
00318 extern PlayerTime* GlobalTime;
00319 
00320 extern int               RFLEX::joy_control;
00321 
00322 // help function to rotate sonar positions
00323 void SonarRotate(double heading, double x1, double y1, double t1, double *x2, double *y2, double *t2)
00324 {
00325   *t2 = t1 - heading;
00326   *x2 = x1*cos(heading) + y1*sin(heading);
00327   *y2 = -x1*sin(heading) + y1*cos(heading);
00328 }
00329 
00330 
00331 //NOTE - this is accessed as an extern variable by the other RFLEX objects
00332 rflex_config_t rflex_configs;
00333 
00334 /* initialize the driver.
00335  *
00336  * returns: pointer to new REBIR object
00337  */
00338 Driver*
00339 RFLEX_Init(ConfigFile *cf, int section)
00340 {
00341   return (Driver *) new RFLEX( cf, section);
00342 }
00343 
00344 /* register the rflex driver in the drivertable
00345  *
00346  * returns:
00347  */
00348 void
00349 RFLEX_Register(DriverTable *table)
00350 {
00351   table->AddDriver("rflex", RFLEX_Init);
00352 }
00353 
00355 // Message handler functions
00357 void PrintHeader(player_msghdr_t hdr);
00358 int RFLEX::ProcessMessage(QueuePointer & resp_queue, player_msghdr * hdr,
00359                            void * data)
00360 {
00361   assert(hdr);
00362 
00363   if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_SONAR_REQ_POWER,
00364                         sonar_id))
00365   {
00366     Lock();
00367     if(reinterpret_cast<player_sonar_power_config_t *> (data)->state==0)
00368       rflex_sonars_off(rflex_fd);
00369     else
00370       rflex_sonars_on(rflex_fd);
00371     Unlock();
00372     Publish(sonar_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype);
00373     return 0;
00374   }
00375   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_SONAR_REQ_POWER,
00376                         sonar_id_2))
00377   {
00378     Lock();
00379     if(reinterpret_cast<player_sonar_power_config_t *> (data)->state==0)
00380       rflex_sonars_off(rflex_fd);
00381     else
00382       rflex_sonars_on(rflex_fd);
00383     Unlock();
00384     Publish(sonar_id_2, resp_queue, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype);
00385     return 0;
00386   }
00387   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_SONAR_REQ_GET_GEOM,
00388                         sonar_id))
00389   {
00390     player_sonar_geom_t geom;
00391     Lock();
00392     geom.poses_count = rflex_configs.sonar_1st_bank_end;
00393     geom.poses = new player_pose3d_t[geom.poses_count];
00394     for (int i = 0; i < rflex_configs.sonar_1st_bank_end; i++)
00395     {
00396       geom.poses[i] = rflex_configs.mrad_sonar_poses[i];
00397     }
00398     Unlock();
00399     Publish(sonar_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype, &geom,sizeof(geom));
00400     delete [] geom.poses;
00401     return 0;
00402   }
00403   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_SONAR_REQ_GET_GEOM,
00404                         sonar_id_2))
00405   {
00406     player_sonar_geom_t geom;
00407     Lock();
00408     geom.poses_count = (rflex_configs.num_sonars - rflex_configs.sonar_2nd_bank_start);
00409     geom.poses = new player_pose3d_t[geom.poses_count];
00410     for (int i = 0; i < rflex_configs.num_sonars - rflex_configs.sonar_2nd_bank_start; i++)
00411     {
00412       geom.poses[i] = rflex_configs.mrad_sonar_poses[i+rflex_configs.sonar_2nd_bank_start];
00413     }
00414     Unlock();
00415     Publish(sonar_id_2, resp_queue, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype, &geom,sizeof(geom));
00416     delete [] geom.poses;
00417     return 0;
00418   }
00419   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_BUMPER_REQ_GET_GEOM,
00420                         bumper_id))
00421   {
00422     player_bumper_geom_t geom;
00423     Lock();
00424     geom.bumper_def_count = rflex_configs.bumper_count;
00425     geom.bumper_def = new player_bumper_define_t[geom.bumper_def_count];
00426     for (int i = 0; i < rflex_configs.bumper_count; i++)
00427     {
00428       geom.bumper_def[i] = rflex_configs.bumper_def[i];
00429     }
00430     Unlock();
00431     Publish(bumper_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype, &geom,sizeof(geom));
00432     delete [] geom.bumper_def;
00433     return 0;
00434   }
00435   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_IR_REQ_POSE, ir_id))
00436   {
00437     Lock();
00438     Publish(ir_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype, &rflex_configs.ir_poses,sizeof(rflex_configs.ir_poses));
00439     Unlock();
00440     return 0;
00441   }
00442   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_IR_REQ_POWER, ir_id))
00443   {
00444     player_ir_power_req_t * req = reinterpret_cast<player_ir_power_req_t*> (data);
00445     Lock();
00446     if (req->state == 0)
00447       rflex_ir_off(rflex_fd);
00448     else
00449       rflex_ir_on(rflex_fd);
00450     Unlock();
00451     Publish(ir_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype);
00452     return 0;
00453   }
00454   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_POSITION2D_REQ_SET_ODOM, position_id))
00455   {
00456     player_position2d_set_odom_req * set_odom_req = reinterpret_cast<player_position2d_set_odom_req*> (data);
00457     Lock();
00458     set_odometry(set_odom_req->pose.px,set_odom_req->pose.py,set_odom_req->pose.pa);
00459     Unlock();
00460     Publish(position_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype);
00461     return 0;
00462   }
00463   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_POSITION2D_REQ_MOTOR_POWER, position_id))
00464   {
00465     Lock();
00466     if(((player_position2d_power_config_t*)data)->state==0)
00467       rflex_brake_on(rflex_fd);
00468     else
00469       rflex_brake_off(rflex_fd);
00470     Unlock();
00471     Publish(position_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype);
00472     return 0;
00473   }
00474   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_POSITION2D_REQ_VELOCITY_MODE, position_id))
00475   {
00476     // Does nothing, needs to be implemented
00477     Publish(position_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype);
00478     return 0;
00479   }
00480   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_POSITION2D_REQ_RESET_ODOM, position_id))
00481   {
00482     Lock();
00483     reset_odometry();
00484     Unlock();
00485     Publish(position_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype);
00486     return 0;
00487   }
00488   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_POSITION2D_REQ_GET_GEOM, position_id))
00489   {
00490     player_position2d_geom_t geom={{0}};
00491     Lock();
00492     geom.size.sl = rflex_configs.m_length;
00493     geom.size.sw = rflex_configs.m_width;
00494     Unlock();
00495     Publish(position_id, resp_queue, PLAYER_MSGTYPE_RESP_ACK, hdr->subtype, &geom,sizeof(geom));
00496     return 0;
00497   }
00498   else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, PLAYER_POSITION2D_CMD_VEL, position_id))
00499   {
00500     Lock();
00501     command = *reinterpret_cast<player_position2d_cmd_vel_t *> (data);
00502     Unlock();
00503  
00504     // reset command_type since we have a new 
00505     // velocity command so we can get into the 
00506     // velocity control section in RFLEX::Main()
00507     
00508     command_type = 0;
00509     
00510     return 0;
00511   }
00512 
00513   return -1;
00514 }
00515 
00516 RFLEX::RFLEX(ConfigFile* cf, int section)
00517         : Driver(cf,section)
00518 {
00519   // zero ids, so that we'll know later which interfaces were requested
00520   memset(&this->position_id, 0, sizeof(player_devaddr_t));
00521   memset(&this->sonar_id, 0, sizeof(player_devaddr_t));
00522   memset(&this->sonar_id_2, 0, sizeof(player_devaddr_t));
00523   memset(&this->ir_id, 0, sizeof(player_devaddr_t));
00524   memset(&this->bumper_id, 0, sizeof(player_devaddr_t));
00525   memset(&this->power_id, 0, sizeof(player_devaddr_t));
00526   memset(&this->aio_id, 0, sizeof(player_devaddr_t));
00527   memset(&this->dio_id, 0, sizeof(player_devaddr_t));
00528   
00529   command_type = 0;
00530 
00531   this->position_subscriptions = 0;
00532   this->sonar_subscriptions = 0;
00533   this->ir_subscriptions = 0;
00534   this->bumper_subscriptions = 0;
00535 
00536   // Do we create a robot position interface?
00537   if(cf->ReadDeviceAddr(&(this->position_id), section, "provides",
00538                       PLAYER_POSITION2D_CODE, -1, NULL) == 0)
00539   {
00540     if(this->AddInterface(this->position_id) != 0)
00541     {
00542       this->SetError(-1);
00543       return;
00544     }
00545   }
00546   else
00547   {
00548       PLAYER_WARN("Position2d interface not created for rflex driver");
00549   }
00550 
00551   // Do we create a sonar interface?
00552   if(cf->ReadDeviceAddr(&(this->sonar_id), section, "provides",
00553                       PLAYER_SONAR_CODE, -1, NULL) == 0)
00554   {
00555     if(this->AddInterface(this->sonar_id) != 0)
00556     {
00557       this->SetError(-1);
00558       return;
00559     }
00560   }
00561   else
00562   {
00563       PLAYER_WARN("sonar bank 1 interface not created for rflex driver");
00564   }
00565   // Do we create a second sonar interface?
00566   if(cf->ReadDeviceAddr(&(this->sonar_id_2), section, "provides",
00567                       PLAYER_SONAR_CODE, -1, "bank2") == 0)
00568   {
00569     if(this->AddInterface(this->sonar_id_2) != 0)
00570     {
00571       this->SetError(-1);
00572       return;
00573     }
00574   }
00575   else
00576   {
00577       PLAYER_WARN("sonar bank 2 interface not created for rflex driver");
00578   }
00579 
00580   // Do we create an ir interface?
00581   if(cf->ReadDeviceAddr(&(this->ir_id), section, "provides",
00582                       PLAYER_IR_CODE, -1, NULL) == 0)
00583   {
00584     if(this->AddInterface(this->ir_id) != 0)
00585     {
00586       this->SetError(-1);
00587       return;
00588     }
00589   }
00590   else
00591   {
00592       PLAYER_WARN("ir interface not created for rflex driver");
00593   }
00594 
00595   // Do we create a bumper interface?
00596   if(cf->ReadDeviceAddr(&(this->bumper_id), section, "provides",
00597                       PLAYER_BUMPER_CODE, -1, NULL) == 0)
00598   {
00599     if(this->AddInterface(this->bumper_id) != 0)
00600     {
00601       this->SetError(-1);
00602       return;
00603     }
00604   }
00605   else
00606   {
00607       PLAYER_WARN("bumper interface not created for rflex driver");
00608   }
00609 
00610   // Do we create a power interface?
00611   if(cf->ReadDeviceAddr(&(this->power_id), section, "provides",
00612                       PLAYER_POWER_CODE, -1, NULL) == 0)
00613   {
00614     if(this->AddInterface(this->power_id) != 0)
00615     {
00616       this->SetError(-1);
00617       return;
00618     }
00619   }
00620   else
00621   {
00622       PLAYER_WARN("power interface not created for rflex driver");
00623   }
00624 
00625   // Do we create an aio interface?
00626   if(cf->ReadDeviceAddr(&(this->aio_id), section, "provides",
00627                       PLAYER_AIO_CODE, -1, NULL) == 0)
00628   {
00629     if(this->AddInterface(this->aio_id) != 0)
00630     {
00631       this->SetError(-1);
00632       return;
00633     }
00634   }
00635   else
00636   {
00637       PLAYER_WARN("aio interface not created for rflex driver");
00638   }
00639 
00640   // Do we create a dio interface?
00641   if(cf->ReadDeviceAddr(&(this->dio_id), section, "provides",
00642                       PLAYER_DIO_CODE, -1, NULL) == 0)
00643   {
00644     if(this->AddInterface(this->dio_id) != 0)
00645     {
00646       this->SetError(-1);
00647       return;
00648     }
00649   }
00650   else
00651   {
00652       PLAYER_WARN("dio interface not created for rflex driver");
00653   }
00654 
00655   //just sets stuff to zero
00656   set_config_defaults();
00657 
00658   // joystick override
00659   joy_control = 0;
00660 
00661   //get serial port: everyone needs it (and we dont' want them fighting)
00662   strncpy(rflex_configs.serial_port,
00663           cf->ReadString(section, "rflex_serial_port",
00664                          rflex_configs.serial_port),
00665           sizeof(rflex_configs.serial_port));
00666 
00668   // Position-related options
00669 
00670   //length
00671   rflex_configs.m_length=
00672     cf->ReadFloat(section, "m_length",0.5);
00673   //width
00674   rflex_configs.m_width=
00675     cf->ReadFloat(section, "m_width",0.5);
00676   //distance conversion
00677   rflex_configs.odo_distance_conversion=
00678     cf->ReadFloat(section, "odo_distance_conversion", 0.0);
00679   //angle conversion
00680   rflex_configs.odo_angle_conversion=
00681     cf->ReadFloat(section, "odo_angle_conversion", 0.0);
00682   //default trans accel
00683   rflex_configs.mPsec2_trans_acceleration=
00684     cf->ReadFloat(section, "default_trans_acceleration",0.1);
00685   //default rot accel
00686   rflex_configs.radPsec2_rot_acceleration=
00687     cf->ReadFloat(section, "default_rot_acceleration",0.1);
00688 
00689   // absolute heading options
00690   rflex_configs.heading_home_address =
00691     cf->ReadInt(section, "rflex_heading_home_address",0);
00692   rflex_configs.home_on_start =
00693     cf->ReadInt(section, "rflex_home_on_start",0);
00694 
00695   // use rflex joystick for position
00696   rflex_configs.use_joystick |= cf->ReadInt(section, "rflex_joystick",0);
00697   rflex_configs.joy_pos_ratio = cf->ReadFloat(section, "rflex_joy_pos_ratio",0);
00698   rflex_configs.joy_ang_ratio = cf->ReadFloat(section, "rflex_joy_ang_ratio",0);
00699 
00701   // Sonar-related options
00702   int x;
00703 
00704   rflex_configs.range_distance_conversion=
00705           cf->ReadFloat(section, "range_distance_conversion",1476);
00706   rflex_configs.max_num_sonars=
00707           cf->ReadInt(section, "max_num_sonars",64);
00708   rflex_configs.num_sonars=
00709           cf->ReadInt(section, "num_sonars",24);
00710   rflex_configs.sonar_age=
00711           cf->ReadInt(section, "sonar_age",1);
00712   rflex_configs.sonar_max_range=
00713           cf->ReadInt(section, "sonar_max_range",3000);
00714   rflex_configs.num_sonar_banks=
00715           cf->ReadInt(section, "num_sonar_banks",8);
00716   rflex_configs.num_sonars_possible_per_bank=
00717           cf->ReadInt(section, "num_sonars_possible_per_bank",16);
00718   rflex_configs.num_sonars_in_bank=(int *) malloc(rflex_configs.num_sonar_banks*sizeof(double));
00719   for(x=0;x<rflex_configs.num_sonar_banks;x++)
00720     rflex_configs.num_sonars_in_bank[x]=
00721             (int) cf->ReadTupleFloat(section, "num_sonars_in_bank",x,8);
00722   rflex_configs.sonar_echo_delay=
00723           cf->ReadInt(section, "sonar_echo_delay",3000);
00724   rflex_configs.sonar_ping_delay=
00725           cf->ReadInt(section, "sonar_ping_delay",0);
00726   rflex_configs.sonar_set_delay=
00727           cf->ReadInt(section, "sonar_set_delay", 0);
00728   rflex_configs.mrad_sonar_poses=(player_pose3d_t *) malloc(rflex_configs.num_sonars*sizeof(player_pose3d_t));
00729   for(x=0;x<rflex_configs.num_sonars;x++)
00730   {
00731     rflex_configs.mrad_sonar_poses[x].px=
00732             cf->ReadTupleFloat(section, "mrad_sonar_poses",3*x+1,0.0);
00733     rflex_configs.mrad_sonar_poses[x].py=
00734             cf->ReadTupleFloat(section, "mrad_sonar_poses",3*x+2,0.0);
00735     rflex_configs.mrad_sonar_poses[x].pyaw=
00736             cf->ReadTupleFloat(section, "mrad_sonar_poses",3*x,0.0);
00737   }
00738   rflex_configs.sonar_2nd_bank_start=cf->ReadInt(section, "sonar_2nd_bank_start", 0);
00739   rflex_configs.sonar_1st_bank_end=rflex_configs.sonar_2nd_bank_start>0?rflex_configs.sonar_2nd_bank_start:rflex_configs.num_sonars;
00741   // IR-related options
00742 
00743   int pose_count=cf->ReadInt(section, "pose_count",8);
00744   rflex_configs.ir_base_bank=cf->ReadInt(section, "rflex_base_bank",0);
00745   rflex_configs.ir_bank_count=cf->ReadInt(section, "rflex_bank_count",0);
00746   rflex_configs.ir_min_range=cf->ReadFloat(section,"ir_min_range",0.1);
00747   rflex_configs.ir_max_range=cf->ReadFloat(section,"ir_max_range",0.8);
00748   rflex_configs.ir_count=new int[rflex_configs.ir_bank_count];
00749   rflex_configs.ir_a=new double[pose_count];
00750   rflex_configs.ir_b=new double[pose_count];
00751   rflex_configs.ir_poses.poses_count=pose_count;
00752   rflex_configs.ir_poses.poses=(player_pose3d_t *)
00753   malloc(rflex_configs.ir_poses.poses_count*sizeof(player_pose3d_t));
00754   unsigned int RunningTotal = 0;
00755   for(int i=0; i < rflex_configs.ir_bank_count; ++i)
00756     RunningTotal += (rflex_configs.ir_count[i]=(int) cf->ReadTupleFloat(section, "rflex_banks",i,0));
00757   rflex_configs.ir_total_count = RunningTotal;
00758   // posecount is actually unnecasary, but for consistancy will juse use it for error checking :)
00759   if (RunningTotal != rflex_configs.ir_poses.poses_count)
00760   {
00761     PLAYER_WARN("Error in config file, pose_count not equal to total poses in bank description\n");
00762     rflex_configs.ir_poses.poses_count = RunningTotal;
00763   }
00764 
00765   //  rflex_configs.ir_poses.poses=new int16_t[rflex_configs.ir_poses.pose_count];
00766   for(unsigned int i=0;i<rflex_configs.ir_poses.poses_count;i++)
00767   {
00768     rflex_configs.ir_poses.poses[i].px= cf->ReadTupleFloat(section, "poses",i*3,0);
00769     rflex_configs.ir_poses.poses[i].py= cf->ReadTupleFloat(section, "poses",i*3+1,0);
00770     rflex_configs.ir_poses.poses[i].pyaw= cf->ReadTupleFloat(section, "poses",i*3+2,0);
00771 
00772     // Calibration parameters for ir in form range=(a*voltage)^b
00773     rflex_configs.ir_a[i] = cf->ReadTupleFloat(section, "rflex_ir_calib",i*2,1);
00774     rflex_configs.ir_b[i] = cf->ReadTupleFloat(section, "rflex_ir_calib",i*2+1,1);
00775   }
00776 
00778   // Bumper-related options
00779   rflex_configs.bumper_count = cf->ReadInt(section, "bumper_count",0);
00780   rflex_configs.bumper_def = new player_bumper_define_t[rflex_configs.bumper_count];
00781   for(x=0;x<rflex_configs.bumper_count;++x)
00782   {
00783     rflex_configs.bumper_def[x].pose.px =  (cf->ReadTupleFloat(section, "bumper_def",5*x,0)); //m
00784     rflex_configs.bumper_def[x].pose.py =  (cf->ReadTupleFloat(section, "bumper_def",5*x+1,0)); //m
00785     rflex_configs.bumper_def[x].pose.pyaw =  (cf->ReadTupleFloat(section, "bumper_def",5*x+2,0)); //rad
00786     rflex_configs.bumper_def[x].length =  (cf->ReadTupleFloat(section, "bumper_def",5*x+3,0)); //m
00787     rflex_configs.bumper_def[x].radius =  (cf->ReadTupleFloat(section, "bumper_def",5*x+4,0));  //m
00788   }
00789   rflex_configs.bumper_address = cf->ReadInt(section, "rflex_bumper_address",DEFAULT_RFLEX_BUMPER_ADDRESS);
00790 
00791 
00792   const char *bumperStyleStr = cf->ReadString(section, "rflex_bumper_style",DEFAULT_RFLEX_BUMPER_STYLE);
00793 
00794   if(strcmp(bumperStyleStr,RFLEX_BUMPER_STYLE_BIT) == 0)
00795   {
00796     rflex_configs.bumper_style = BUMPER_BIT;
00797   }
00798   else if(strcmp(bumperStyleStr,RFLEX_BUMPER_STYLE_ADDR) == 0)
00799   {
00800     rflex_configs.bumper_style = BUMPER_ADDR;
00801   }
00802   else
00803   {
00804     //Invalid value
00805     rflex_configs.bumper_style = BUMPER_ADDR;
00806   }
00807 
00809   // Power-related options
00810   rflex_configs.power_offset = cf->ReadFloat(section, "rflex_power_offset",DEFAULT_RFLEX_POWER_OFFSET);
00811 
00812   rflex_fd = -1;
00813 
00814 }
00815 
00816 RFLEX::~RFLEX()
00817 {
00818 }
00819 
00820 int RFLEX::Setup(){
00821   /* now spawn reading thread */
00822   StartThread();
00823   return(0);
00824 }
00825 
00826 int RFLEX::Shutdown()
00827 {
00828   if(rflex_fd == -1)
00829   {
00830     return 0;
00831   }
00832   StopThread();
00833   //make sure it doesn't go anywhere
00834   rflex_stop_robot(rflex_fd,(int) M2ARB_ODO_CONV(rflex_configs.mPsec2_trans_acceleration));
00835   //kill that infernal clicking
00836   rflex_sonars_off(rflex_fd);
00837   // release the port
00838   rflex_close_connection(&rflex_fd);
00839   return 0;
00840 }
00841 
00842 /* start a thread that will invoke Main() */
00843 void
00844 RFLEX::StartThread(void)
00845 {
00846   ThreadAlive = true;
00847   pthread_create(&driverthread, NULL, &DummyMain, this);
00848 }
00849 
00850 /* wait for termination of the thread */
00851 // this is called with the lock held
00852 void
00853 RFLEX::StopThread(void)
00854 {
00855   void* dummy;
00856   ThreadAlive = false;
00857   Unlock();
00858 
00859   //pthread_cancel(driverthread);
00860   if(pthread_join(driverthread,&dummy))
00861     perror("Driver::StopThread:pthread_join()");
00862   Lock();
00863 }
00864 
00865 int
00866 RFLEX::Subscribe(player_devaddr_t id)
00867 {
00868   int setupResult;
00869 
00870   // do the subscription
00871   if((setupResult = Driver::Subscribe(id)) == 0)
00872   {
00873     // also increment the appropriate subscription counter
00874     switch(id.interf)
00875     {
00876       case PLAYER_POSITION2D_CODE:
00877         this->position_subscriptions++;
00878         break;
00879       case PLAYER_SONAR_CODE:
00880         this->sonar_subscriptions++;
00881         break;
00882       case PLAYER_BUMPER_CODE:
00883         this->bumper_subscriptions++;
00884         break;
00885       case PLAYER_IR_CODE:
00886         this->ir_subscriptions++;
00887         break;
00888     }
00889   }
00890 
00891   return(setupResult);
00892 }
00893 
00894 int
00895 RFLEX::Unsubscribe(player_devaddr_t id)
00896 {
00897   int shutdownResult;
00898 
00899   // do the unsubscription
00900   if((shutdownResult = Driver::Unsubscribe(id)) == 0)
00901   {
00902     // also decrement the appropriate subscription counter
00903     switch(id.interf)
00904     {
00905       case PLAYER_POSITION2D_CODE:
00906         --this->position_subscriptions;
00907         assert(this->position_subscriptions >= 0);
00908         break;
00909       case PLAYER_SONAR_CODE:
00910         sonar_subscriptions--;
00911         assert(sonar_subscriptions >= 0);
00912         break;
00913       case PLAYER_BUMPER_CODE:
00914         --this->bumper_subscriptions;
00915         assert(this->bumper_subscriptions >= 0);
00916         break;
00917       case PLAYER_IR_CODE:
00918         --this->ir_subscriptions;
00919         assert(this->ir_subscriptions >= 0);
00920         break;
00921     }
00922   }
00923 
00924   return(shutdownResult);
00925 }
00926 
00927 void
00928 RFLEX::Main()
00929 {
00930   PLAYER_MSG1(1,"%s","Rflex Thread Started");
00931 
00932   //sets up connection, and sets defaults
00933   //configures sonar, motor acceleration, etc.
00934   if(initialize_robot()<0){
00935     PLAYER_ERROR("ERROR, no connection to RFLEX established\n");
00936     return;
00937   }
00938   Lock();
00939   reset_odometry();
00940   Unlock();
00941 
00942 
00943 
00944   static double mPsec_speedDemand=0.0, radPsec_turnRateDemand=0.0;
00945   bool newmotorspeed, newmotorturn;
00946 
00947   int i;
00948   int last_sonar_subscrcount = 0;
00949   int last_position_subscrcount = 0;
00950   int last_ir_subscrcount = 0;
00951 
00952   while(1)
00953   {
00954     int oldstate;
00955     int ret;
00956     ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,&oldstate);
00957 
00958     // we want to turn on the sonars if someone just subscribed, and turn
00959     // them off if the last subscriber just unsubscribed.
00960     if(!last_sonar_subscrcount && this->sonar_subscriptions)
00961     {
00962       Lock();
00963         rflex_sonars_on(rflex_fd);
00964         Unlock();
00965     }
00966     else if(last_sonar_subscrcount && !(this->sonar_subscriptions))
00967     {
00968       Lock();
00969     rflex_sonars_off(rflex_fd);
00970     Unlock();
00971     }
00972     last_sonar_subscrcount = this->sonar_subscriptions;
00973 
00974     // we want to turn on the ir if someone just subscribed, and turn
00975     // it off if the last subscriber just unsubscribed.
00976     if(!last_ir_subscrcount && this->ir_subscriptions)
00977     {
00978       Lock();
00979     rflex_ir_on(rflex_fd);
00980     Unlock();
00981     }
00982     else if(last_ir_subscrcount && !(this->ir_subscriptions))
00983     {
00984       Lock();
00985     rflex_ir_off(rflex_fd);
00986     Unlock();
00987     }
00988     last_ir_subscrcount = this->ir_subscriptions;
00989 
00990     // we want to reset the odometry and enable the motors if the first
00991     // client just subscribed to the position device, and we want to stop
00992     // and disable the motors if the last client unsubscribed.
00993 
00994     //first user logged in
00995     if(!last_position_subscrcount && this->position_subscriptions)
00996     {
00997       Lock();
00998       //set drive defaults
00999       rflex_motion_set_defaults(rflex_fd);
01000 
01001       //make sure robot doesn't go anywhere
01002       rflex_stop_robot(rflex_fd,(int) (M2ARB_ODO_CONV(rflex_configs.mPsec2_trans_acceleration)));
01003 
01004     Unlock();
01005     }
01006     //last user logged out
01007     else if(last_position_subscrcount && !(this->position_subscriptions))
01008     {
01009       Lock();
01010       //make sure robot doesn't go anywhere
01011       rflex_stop_robot(rflex_fd,(int) (M2ARB_ODO_CONV(rflex_configs.mPsec2_trans_acceleration)));
01012       // disable motor power
01013       rflex_brake_on(rflex_fd);
01014       Unlock();
01015     }
01016     last_position_subscrcount = this->position_subscriptions;
01017 
01018   ProcessMessages();
01019 
01020     if(this->position_subscriptions || rflex_configs.use_joystick || rflex_configs.home_on_start)
01021     {
01022     Lock();
01023     newmotorspeed = false;
01024     newmotorturn = false;
01025 
01026     if (rflex_configs.home_on_start)
01027     {
01028       command.vel.pa = M_PI/18;
01029       newmotorturn=true;
01030     }
01031 
01032     if(mPsec_speedDemand != command.vel.px)
01033     {
01034           newmotorspeed = true;
01035           mPsec_speedDemand = command.vel.px;
01036         }
01037         if(radPsec_turnRateDemand != command.vel.pa)
01038         {
01039           newmotorturn = true;
01040           radPsec_turnRateDemand = command.vel.pa;
01041         }
01042         /* NEXT, write commands */
01043         // rflex has a built in failsafe mode where if no move command is recieved in a
01044         // certain interval the robot stops.
01045         // this is a good thing given teh size of the robot...
01046         // if network goes down or some such and the user looses control then the robot stops
01047         // if the robot is running in an autonomous mdoe it is easy enough to simply
01048         // resend the command repeatedly
01049 
01050         // allow rflex joystick to overide the player command
01051         if (joy_control > 0)
01052           --joy_control;
01053         // only set new command if type is valid and their is a new command
01054         else if (command_type == 0)
01055         {
01056           rflex_set_velocity(rflex_fd,(long) M2ARB_ODO_CONV(mPsec_speedDemand),(long) RAD2ARB_ODO_CONV(radPsec_turnRateDemand),(long) M2ARB_ODO_CONV(rflex_configs.mPsec2_trans_acceleration));
01057           command_type = 255;
01058         }
01059         Unlock();
01060     }
01061     else
01062     {
01063       Lock();
01064     rflex_stop_robot(rflex_fd,(long) M2ARB_ODO_CONV(rflex_configs.mPsec2_trans_acceleration));
01065     Unlock();
01066     }
01067 
01068     /* Get data from robot */
01069   static float LastYaw = 0;
01070     player_rflex_data_t rflex_data = {{{0}}};
01071 
01072   Lock();
01073     update_everything(&rflex_data);
01074     Unlock();
01075 
01076   if (position_id.interf != 0)
01077   {
01078     Publish(this->position_id,PLAYER_MSGTYPE_DATA,PLAYER_POSITION2D_DATA_STATE,
01079             (unsigned char*)&rflex_data.position,
01080             sizeof(player_position2d_data_t),
01081             NULL);
01082   }
01083   if (sonar_id.interf != 0)
01084   {
01085       Publish(this->sonar_id,PLAYER_MSGTYPE_DATA,PLAYER_SONAR_DATA_RANGES,
01086             (unsigned char*)&rflex_data.sonar,
01087             sizeof(player_sonar_data_t),
01088             NULL);
01089   }
01090   // Here we check if the robot has changed Yaw...
01091   // If it has we need to update the geometry as well
01092   if (rflex_data.position.pos.pa != LastYaw)
01093   {
01094     // Transmit new sonar geometry
01095     double NewGeom[3];
01096 
01097         player_sonar_geom_t geom;
01098 
01099     Lock();
01100         geom.poses_count = rflex_configs.num_sonars - rflex_configs.sonar_2nd_bank_start;
01101         geom.poses = new player_pose3d_t[geom.poses_count];
01102         for (i = 0; i < rflex_configs.num_sonars - rflex_configs.sonar_2nd_bank_start; i++)
01103         {
01104       SonarRotate(rad_odo_theta, rflex_configs.mrad_sonar_poses[i+rflex_configs.sonar_2nd_bank_start].px,rflex_configs.mrad_sonar_poses[i+rflex_configs.sonar_2nd_bank_start].py,rflex_configs.mrad_sonar_poses[i+rflex_configs.sonar_2nd_bank_start].pyaw,NewGeom,&NewGeom[1],&NewGeom[2]);
01105           geom.poses[i].px = NewGeom[0];
01106           geom.poses[i].py = NewGeom[1];
01107           geom.poses[i].pyaw = NewGeom[2];
01108         }
01109         Unlock();
01110         if (sonar_id_2.interf)
01111         Publish(this->sonar_id_2,  PLAYER_MSGTYPE_DATA, PLAYER_SONAR_DATA_GEOM,
01112         (unsigned char*)&geom, sizeof(player_sonar_geom_t), NULL);
01113         delete [] geom.poses;
01114   }
01115   LastYaw = rflex_data.position.pos.pa;
01116 
01117   if (sonar_id_2.interf)
01118       Publish(this->sonar_id_2,PLAYER_MSGTYPE_DATA,PLAYER_SONAR_DATA_RANGES,
01119             (unsigned char*)&rflex_data.sonar2,
01120             sizeof(player_sonar_data_t),
01121             NULL);
01122   if (ir_id.interf)
01123       Publish(this->ir_id,PLAYER_MSGTYPE_DATA,PLAYER_IR_DATA_RANGES,
01124             (unsigned char*)&rflex_data.ir,
01125             sizeof(player_ir_data_t),
01126             NULL);
01127   if (bumper_id.interf)
01128       Publish(this->bumper_id,PLAYER_MSGTYPE_DATA,PLAYER_BUMPER_DATA_STATE,
01129             (unsigned char*)&rflex_data.bumper,
01130             sizeof(player_bumper_data_t),
01131             NULL);
01132   if (power_id.interf)
01133     Publish(this->power_id,PLAYER_MSGTYPE_DATA,PLAYER_POWER_DATA_STATE,
01134             (unsigned char*)&rflex_data.power,
01135             sizeof(player_power_data_t),
01136             NULL);
01137   if (aio_id.interf != 0)
01138   {
01139       Publish(this->aio_id,PLAYER_MSGTYPE_DATA,PLAYER_AIO_DATA_STATE,
01140             (unsigned char*)&rflex_data.aio,
01141             sizeof(player_aio_data_t),
01142             NULL);
01143   }
01144   if (dio_id.interf != 0)
01145   {
01146       Publish(this->dio_id,PLAYER_MSGTYPE_DATA,PLAYER_DIO_DATA_VALUES,
01147             (unsigned char*)&rflex_data.dio,
01148             sizeof(player_dio_data_t),
01149             NULL);
01150   }
01151 
01152   ret=pthread_setcancelstate(oldstate,NULL);
01153   player_position2d_data_t_cleanup(&rflex_data.position);
01154   player_sonar_data_t_cleanup(&rflex_data.sonar);
01155   player_sonar_data_t_cleanup(&rflex_data.sonar2);
01156   player_gripper_data_t_cleanup(&rflex_data.gripper);
01157   player_power_data_t_cleanup(&rflex_data.power);
01158   player_bumper_data_t_cleanup(&rflex_data.bumper);
01159   player_dio_data_t_cleanup(&rflex_data.dio);
01160   player_aio_data_t_cleanup(&rflex_data.aio);
01161   player_ir_data_t_cleanup(&rflex_data.ir);
01162   Lock();
01163   if (!ThreadAlive)
01164   {
01165     Unlock();
01166     break;
01167   }
01168   Unlock();
01169 
01170   // release cpu somewhat so other threads can run.
01171   usleep(1000);
01172   
01173   }
01174   pthread_exit(NULL);
01175 }
01176 
01177 int RFLEX::initialize_robot(){
01178   // Neither g++ nor I can find a definition for thread_is_running - BPG
01179 #if 0
01180 #ifdef _REENTRANT
01181   if (thread_is_running)
01182     {
01183       fprintf(stderr,"Tried to connect to the robot while the command loop "
01184                   "thread is running.\n");
01185       fprintf(stderr,"This is a bug in the code, and must be fixed.\n");
01186       return -1;
01187     }
01188 #endif
01189 #endif
01190 
01191   if (rflex_open_connection(rflex_configs.serial_port, &rflex_fd) < 0)
01192     return -1;
01193 
01194   printf("Rflex initialisation called\n");
01195   rflex_initialize(rflex_fd, (int) M2ARB_ODO_CONV(rflex_configs.mPsec2_trans_acceleration),(int) RAD2ARB_ODO_CONV(rflex_configs.radPsec2_rot_acceleration), 0, 0);
01196   printf("RFlex init done\n");
01197 
01198   return 0;
01199 }
01200 
01201 void RFLEX::reset_odometry() {
01202   m_odo_x=0;
01203   m_odo_y=0;
01204   rad_odo_theta= 0.0;
01205 }
01206 
01207 void RFLEX::set_odometry(float m_x, float m_y, float rad_theta) {
01208   m_odo_x=m_x;
01209   m_odo_y=m_y;
01210   rad_odo_theta=rad_theta;
01211 }
01212 
01213 void RFLEX::update_everything(player_rflex_data_t* d)
01214 {
01215 
01216   int *arb_ranges = new int[rflex_configs.num_sonars];
01217   char *abumper_ranges = new char[rflex_configs.bumper_count];
01218   uint8_t *air_ranges = new uint8_t[rflex_configs.ir_total_count];
01219 
01220   static int initialized = 0;
01221 
01222   double m_new_range_position; double rad_new_bearing_position;
01223   double mPsec_t_vel;
01224   double radPsec_r_vel;
01225 
01226   int arb_t_vel, arb_r_vel;
01227   static int arb_last_range_position;
01228   static int arb_last_bearing_position;
01229   int arb_new_range_position;
01230   int arb_new_bearing_position;
01231   double m_displacement;
01232   short a_num_sonars, a_num_bumpers, a_num_ir;
01233 
01234   int batt,brake;
01235 
01236   int i;
01237 
01238   //update status
01239   rflex_update_status(rflex_fd, &arb_new_range_position,
01240                       &arb_new_bearing_position, &arb_t_vel,
01241                       &arb_r_vel);
01242   mPsec_t_vel=ARB2M_ODO_CONV(arb_t_vel);
01243   radPsec_r_vel=ARB2RAD_ODO_CONV(arb_r_vel);
01244   m_new_range_position=ARB2M_ODO_CONV(arb_new_range_position);
01245   rad_new_bearing_position=ARB2RAD_ODO_CONV(arb_new_bearing_position);
01246 
01247   if (!initialized) {
01248     initialized = 1;
01249   } else {
01250     rad_odo_theta += ARB2RAD_ODO_CONV(arb_new_bearing_position - arb_last_bearing_position);
01251     rad_odo_theta = normalize_theta(rad_odo_theta);
01252     m_displacement = ARB2M_ODO_CONV(arb_new_range_position - arb_last_range_position);
01253 
01254     //integrate latest motion into odometry
01255     m_odo_x += m_displacement * cos(rad_odo_theta);
01256     m_odo_y += m_displacement * sin(rad_odo_theta);
01257     d->position.pos.px = m_odo_x;
01258     d->position.pos.py = m_odo_y;
01259     while(rad_odo_theta<0)
01260       rad_odo_theta+=2*M_PI;
01261     while(rad_odo_theta>2*M_PI)
01262       rad_odo_theta-=2*M_PI;
01263     d->position.pos.pa = rad_odo_theta;
01264 
01265     d->position.vel.px = mPsec_t_vel;
01266     d->position.vel.pa = radPsec_r_vel;
01267     //TODO - get better stall information (battery draw?)
01268   }
01269   d->position.stall = false;
01270 
01271   arb_last_range_position = arb_new_range_position;
01272   arb_last_bearing_position = arb_new_bearing_position;
01273 
01274    //note - sonar mappings are strange - look in rflex_commands.c
01275   if(this->sonar_subscriptions)
01276   {
01277     // TODO - currently bad sonar data is sent back to clients
01278     // (not enough data buffered, so sonar sent in wrong order - missing intermittent sonar values - fix this
01279     a_num_sonars=rflex_configs.num_sonars;
01280 
01281 //    pthread_testcancel();
01282     rflex_update_sonar(rflex_fd, a_num_sonars,
01283            arb_ranges);
01284 //    pthread_testcancel();
01285     if (d->sonar.ranges_count!=rflex_configs.sonar_1st_bank_end)
01286     {
01287       d->sonar.ranges_count=rflex_configs.sonar_1st_bank_end;
01288       delete [] d->sonar.ranges;
01289       d->sonar.ranges = new float[d->sonar.ranges_count];
01290     }
01291     for (i = 0; i < rflex_configs.sonar_1st_bank_end; i++){
01292       d->sonar.ranges[i] = ARB2M_RANGE_CONV(arb_ranges[i]);
01293     }
01294     if (d->sonar2.ranges_count!=(rflex_configs.num_sonars - rflex_configs.sonar_2nd_bank_start))
01295     {
01296       d->sonar2.ranges_count=(rflex_configs.num_sonars - rflex_configs.sonar_2nd_bank_start);
01297       delete [] d->sonar2.ranges;
01298       d->sonar2.ranges = new float[d->sonar2.ranges_count];
01299     }
01300     for (i = 0; i < rflex_configs.num_sonars - rflex_configs.sonar_2nd_bank_start; i++){
01301       d->sonar2.ranges[i] = ARB2M_RANGE_CONV(arb_ranges[rflex_configs.sonar_2nd_bank_start+i]);
01302     }
01303   }
01304 
01305   // if someone is subscribed to bumpers copy internal data to device
01306   if(this->bumper_subscriptions)
01307   {
01308     a_num_bumpers=rflex_configs.bumper_count;
01309 
01310 //    pthread_testcancel();
01311     // first make sure our internal state is up to date
01312     rflex_update_bumpers(rflex_fd, a_num_bumpers, abumper_ranges);
01313  //   pthread_testcancel();
01314 
01315     d->bumper.bumpers_count=(a_num_bumpers);
01316     d->bumper.bumpers = (uint8_t*)abumper_ranges;
01317   }
01318 
01319   // if someone is subscribed to irs copy internal data to device
01320   if(this->ir_subscriptions)
01321   {
01322     a_num_ir=rflex_configs.ir_poses.poses_count;
01323 
01324 //    pthread_testcancel();
01325     // first make sure our internal state is up to date
01326     rflex_update_ir(rflex_fd, a_num_ir, air_ranges);
01327 //    pthread_testcancel();
01328 
01329     if (d->ir.ranges_count != (unsigned int) a_num_ir)
01330     {
01331       d->ir.ranges_count = a_num_ir;
01332       d->ir.voltages_count = a_num_ir;
01333       delete [] d->ir.ranges;
01334       delete [] d->ir.voltages;
01335       d->ir.ranges = new float [a_num_ir];
01336       d->ir.voltages = new float [a_num_ir];
01337     }
01338     for (int i = 0; i < a_num_ir; ++i)
01339     {
01340       d->ir.voltages[i] = air_ranges[i];
01341       // using power law mapping of form range = a*voltage^b
01342       float range = pow(air_ranges[i],rflex_configs.ir_b[i]) * rflex_configs.ir_a[i];
01343       // check for min and max ranges, < min = 0 > max = max
01344       range = range < rflex_configs.ir_min_range ? 0 : range;
01345       range = range > rflex_configs.ir_max_range ? rflex_configs.ir_max_range : range;
01346       d->ir.ranges[i] = (range);
01347 
01348     }
01349   }
01350 
01351   //this would get the battery,time, and brake state (if we cared)
01352   //update system (battery,time, and brake also request joystick data)
01353   rflex_update_system(rflex_fd,&batt,&brake);
01354   
01355   // set the bits for the fields we're using
01356   d->power.valid = PLAYER_POWER_MASK_VOLTS | PLAYER_POWER_MASK_PERCENT;
01357   
01358   d->power.volts = static_cast<float>(batt)/100.0 + rflex_configs.power_offset;
01359   if (d->power.volts > 24)
01360     d->power.percent = 100;
01361   else if (d->power.volts < 20)
01362     d->power.percent = 0;
01363   else
01364     d->power.percent = 100.0*(d->power.volts-20.0)/4.0;
01365 }
01366 
01367 //this is so things don't crash if we don't load a device
01368 //(and thus it's settings)
01369 void RFLEX::set_config_defaults(){
01370   memset(&rflex_configs, 0, sizeof(rflex_configs));
01371   strcpy(rflex_configs.serial_port,"/dev/ttyR0");
01372   rflex_configs.mPsec2_trans_acceleration=0.500;
01373   rflex_configs.radPsec2_rot_acceleration=0.500;
01374 }

Last updated 12 September 2005 21:38:45