Revision: 9139 http://sourceforge.net/p/playerstage/svn/9139 Author: jpgr87 Date: 2014-02-18 02:50:05 +0000 (Tue, 18 Feb 2014) Log Message: ----------- Applied patch #625: Offline path computations with wavefront
Modified Paths: -------------- code/player/trunk/server/drivers/planner/wavefront/plan.c code/player/trunk/server/drivers/planner/wavefront/plan.h code/player/trunk/server/drivers/planner/wavefront/wavefront.cc Modified: code/player/trunk/server/drivers/planner/wavefront/plan.c =================================================================== --- code/player/trunk/server/drivers/planner/wavefront/plan.c 2014-02-18 00:28:27 UTC (rev 9138) +++ code/player/trunk/server/drivers/planner/wavefront/plan.c 2014-02-18 02:50:05 UTC (rev 9139) @@ -212,6 +212,51 @@ return; } +// Copy the planner +plan_t *plan_copy(plan_t *plan) +{ + int i; + plan_t* ret_plan; + + ret_plan = plan_alloc(plan->abs_min_radius, + plan->des_min_radius, + plan->max_radius, + plan->dist_penalty, + plan->hysteresis_factor); + + assert(ret_plan); + + // Fill in the map structure + // First, get the map info + ret_plan->scale = plan->scale; + ret_plan->size_x = plan->size_x; + ret_plan->size_y = plan->size_y; + ret_plan->origin_x = plan->origin_x; + ret_plan->origin_y = plan->origin_y; + + // Now get the map data + // Allocate space for map cells + ret_plan->cells = (plan_cell_t*)realloc(ret_plan->cells, + (ret_plan->size_x * + ret_plan->size_y * + sizeof(plan_cell_t))); + assert(ret_plan->cells); + + // Do initialization + plan_init(ret_plan); + + // Copy the map data + for (i = 0; i < ret_plan->size_x * ret_plan->size_y; i++) + { + ret_plan->cells[i].occ_dist = plan->cells[i].occ_dist; + ret_plan->cells[i].occ_state = plan->cells[i].occ_state; + ret_plan->cells[i].occ_state_dyn = plan->cells[i].occ_state_dyn; + ret_plan->cells[i].occ_dist_dyn = plan->cells[i].occ_dist_dyn; + } + + return ret_plan; +} + // Initialize the plan void plan_init(plan_t *plan) { Modified: code/player/trunk/server/drivers/planner/wavefront/plan.h =================================================================== --- code/player/trunk/server/drivers/planner/wavefront/plan.h 2014-02-18 00:28:27 UTC (rev 9138) +++ code/player/trunk/server/drivers/planner/wavefront/plan.h 2014-02-18 02:50:05 UTC (rev 9139) @@ -133,6 +133,9 @@ // Destroy a planner void plan_free(plan_t *plan); +// Copy a planner +plan_t *plan_copy(plan_t *plan); + // Initialize the plan void plan_init(plan_t *plan); Modified: code/player/trunk/server/drivers/planner/wavefront/wavefront.cc =================================================================== --- code/player/trunk/server/drivers/planner/wavefront/wavefront.cc 2014-02-18 00:28:27 UTC (rev 9138) +++ code/player/trunk/server/drivers/planner/wavefront/wavefront.cc 2014-02-18 02:50:05 UTC (rev 9139) @@ -197,7 +197,7 @@ driver ( name "wavefront" - provides ["planner:0"] + provides ["planner:0" "offline:::planner:1"] requires ["output:::position2d:1" "input:::position2d:2" "map:0"] safety_dist 0.15 distance_epsilon 0.5 @@ -209,12 +209,6 @@ */ /** @} */ -// TODO: -// -// - allow for computing a path, without actually executing it. -// -// - compute and return path length - #include <string.h> #include <stddef.h> #include <stdlib.h> @@ -249,6 +243,8 @@ player_devaddr_t map_id; player_devaddr_t laser_id; player_devaddr_t graphics2d_id; + player_devaddr_t offline_planner_id; + double map_res; double robot_radius; double safety_dist; @@ -261,6 +257,8 @@ // the plan object plan_t* plan; + // another plan object for offline path computation + plan_t* offline_plan; // pointers to the underlying devices Device* position; @@ -325,7 +323,15 @@ double* scan_points; int scan_points_size; int scan_points_count; + + // Do we have an offline planner + bool have_offline_planner; + // offline planner goal postion + player_pose2d_t offline_goal; + // offline planner start position + player_pose2d_t offline_start; + // methods for internal use int SetupLocalize(); int SetupLaser(); @@ -352,6 +358,7 @@ void LocalizeToPosition(double* px, double* py, double* pa, double lx, double ly, double la); void SetWaypoint(double wx, double wy, double wa); + void ComputeOfflineWaypoints(player_planner_waypoints_req_t* req, player_planner_waypoints_req_t* reply); public: // Constructor @@ -385,9 +392,9 @@ //////////////////////////////////////////////////////////////////////////////// // Constructor Wavefront::Wavefront( ConfigFile* cf, int section) - : ThreadedDriver(cf, section, true, - PLAYER_MSGQUEUE_DEFAULT_MAXLEN, PLAYER_PLANNER_CODE) + : ThreadedDriver(cf, section, true) { + this->have_offline_planner = false; // Must have a position device to control if (cf->ReadDeviceAddr(&this->position_id, section, "requires", PLAYER_POSITION2D_CODE, -1, "output") != 0) @@ -410,6 +417,20 @@ return; } + if (cf->ReadDeviceAddr(&this->device_addr, section, "provides", + PLAYER_PLANNER_CODE, -1, "") != 0) + { + PLAYER_ERROR("Wavefront must provide a Planner"); + this->SetError(-1); + return; + } + if (cf->ReadDeviceAddr(&this->offline_planner_id, section, "provides", + PLAYER_PLANNER_CODE, -1, "offline") != 0) + { + this->have_offline_planner = true; + PLAYER_WARN("Wavefront providing offline planner"); + } + // Can use a laser device memset(&this->laser_id,0,sizeof(player_devaddr_t)); cf->ReadDeviceAddr(&this->laser_id, section, "requires", @@ -460,6 +481,8 @@ if(this->velocity_control) PLAYER_WARN("Wavefront doing direct velocity control, but without a laser for obstacle detection; this is not safe!"); } + memset((void*)(&this->offline_goal), 0, sizeof(player_pose2d_t)); + memset((void*)(&this->offline_start), 0, sizeof(player_pose2d_t)); } @@ -500,7 +523,7 @@ PLAYER_ERROR("failed to allocate plan"); return(-1); } - + this->offline_plan = NULL; if(SetupMap() < 0) return(-1); if(SetupLocalize() < 0) @@ -539,6 +562,8 @@ if(this->plan) plan_free(this->plan); + if(this->offline_plan) + plan_free(this->offline_plan); free(this->waypoints); this->waypoints = NULL; @@ -579,6 +604,68 @@ } void +Wavefront::ComputeOfflineWaypoints(player_planner_waypoints_req_t* req, player_planner_waypoints_req_t* reply) +{ + double sx, sy, sa, gx, gy, ga; + + sx = this->offline_start.px; + sy = this->offline_start.py; + sa = this->offline_start.pa; + + gx = this->offline_goal.px; + gy = this->offline_goal.py; + ga = this->offline_goal.pa; + + // If there is no offline_plan, create by duplicating plan + if(!this->offline_plan) + this->offline_plan = plan_copy(this->plan); + + // Compute path in offline plan + if(plan_do_global(this->offline_plan, sx, sy, gx, gy) < 0) + { + puts("Wavefront: offline path computation failed"); + } + + // Extract waypoints along the path to the goal from the start position + plan_update_waypoints(this->offline_plan, sx, sy); + + // Fill in reply + // - waypoints + if((reply->waypoints_count = this->offline_plan->waypoint_count)) + { + reply->waypoints = (player_pose2d_t*)calloc(sizeof(reply->waypoints[0]),reply->waypoints_count); + + double distance = 0; + double last_wx, last_wy; + for(int i=0;i<(int)reply->waypoints_count;i++) + { + // Convert and copy waypoint + double wx, wy; + plan_convert_waypoint(this->offline_plan, + this->offline_plan->waypoints[i], + &wx, &wy); + reply->waypoints[i].px = wx; + reply->waypoints[i].py = wy; + reply->waypoints[i].pa = 0.0; + // Update path length + if(i != 0) + { + distance += sqrt(pow(wx-last_wx, 2) + pow(wy-last_wy, 2)); + } + last_wx = wx; + last_wy = wy; + } + reply->waypoints_distance = distance; + } + else // no waypoints + { + reply->waypoints = NULL; + reply->waypoints_distance = 0.0; + } +} + + +void Wavefront::ProcessLaserScan(player_laser_data_scanpose_t* data) { double t0,t1; @@ -1543,6 +1630,10 @@ plan_compute_cspace(this->plan); //draw_cspace(this->plan,"cspace.png"); + if (this->offline_plan) { + plan_free(this->offline_plan); + this->offline_plan = NULL; + } return(0); } @@ -1659,7 +1750,13 @@ HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_PLANNER_REQ_GET_WAYPOINTS); HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_PLANNER_REQ_ENABLE); HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data, PLAYER_MSGTYPE_CMD, PLAYER_PLANNER_CMD_GOAL); - + if (this->have_offline_planner) + { + HANDLE_CAPABILITY_REQUEST (offline_planner_id, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_CAPABILITIES_REQ); + HANDLE_CAPABILITY_REQUEST (offline_planner_id, resp_queue, hdr, data, PLAYER_MSGTYPE_REQ, PLAYER_PLANNER_REQ_GET_WAYPOINTS); + HANDLE_CAPABILITY_REQUEST (offline_planner_id, resp_queue, hdr, data, PLAYER_MSGTYPE_CMD, PLAYER_PLANNER_CMD_GOAL); + HANDLE_CAPABILITY_REQUEST (offline_planner_id, resp_queue, hdr, data, PLAYER_MSGTYPE_CMD, PLAYER_PLANNER_CMD_START); + } // Is it new odometry data? if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_DATA, PLAYER_POSITION2D_DATA_STATE, @@ -1721,12 +1818,22 @@ reply.waypoints_count = this->waypoint_count; reply.waypoints = (player_pose2d_t*)calloc(sizeof(reply.waypoints[0]),this->waypoint_count); + double distance = 0; + double px, py, last_px, last_py; for(int i=0;i<(int)reply.waypoints_count;i++) { - reply.waypoints[i].px = this->waypoints[i][0]; - reply.waypoints[i].py = this->waypoints[i][1]; + // copy waypoint for length computation + px = reply.waypoints[i].px = this->waypoints[i][0]; + py = reply.waypoints[i].py = this->waypoints[i][1]; reply.waypoints[i].pa = 0.0; + if(i != 0) + { + distance += sqrt(pow(px-last_px, 2) + pow(py-last_py, 2)); + } + last_px = px; + last_py = py; } + reply.waypoints_distance = distance; this->Publish(this->device_addr, resp_queue, PLAYER_MSGTYPE_RESP_ACK, @@ -1735,6 +1842,47 @@ free(reply.waypoints); return(0); } + // Is it a start position for an offline computed path? + else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, + PLAYER_PLANNER_CMD_START, + this->offline_planner_id)) + { + assert(data); + this->offline_start.px = ((player_planner_cmd_t*)data)->goal.px; + this->offline_start.py = ((player_planner_cmd_t*)data)->goal.py; + this->offline_start.pa = ((player_planner_cmd_t*)data)->goal.pa; + return(0); + } + // Is it a goal position for an offline computed path? + else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_CMD, + PLAYER_PLANNER_CMD_GOAL, + this->offline_planner_id)) + { + assert(data); + this->offline_goal.px = ((player_planner_cmd_t*)data)->goal.px; + this->offline_goal.py = ((player_planner_cmd_t*)data)->goal.py; + this->offline_goal.pa = ((player_planner_cmd_t*)data)->goal.pa; + return(0); + } + + // Is it a request for an offline computed path? + else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, + PLAYER_PLANNER_REQ_GET_WAYPOINTS, + this->offline_planner_id)) + { + player_planner_waypoints_req_t reply; + + assert(data); + this->ComputeOfflineWaypoints((player_planner_waypoints_req_t*)data, &reply); + + this->Publish(this->offline_planner_id, resp_queue, + PLAYER_MSGTYPE_RESP_ACK, + PLAYER_PLANNER_REQ_GET_WAYPOINTS, + (void*)&reply); + if(reply.waypoints) + free(reply.waypoints); + return(0); + } // Is it a request to enable or disable the planner? else if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_PLANNER_REQ_ENABLE, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Managing the Performance of Cloud-Based Applications Take advantage of what the Cloud has to offer - Avoid Common Pitfalls. Read the Whitepaper. http://pubads.g.doubleclick.net/gampad/clk?id=121054471&iu=/4140/ostg.clktrk _______________________________________________ Playerstage-commit mailing list Playerstage-commit@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/playerstage-commit