From e6ed9ee6dff78ae400d804c4ccba07e00af00e66 Mon Sep 17 00:00:00 2001 From: muelmarc <muelmarc@student.ethz.ch> Date: Fri, 7 Apr 2017 17:10:06 +0200 Subject: [PATCH] added area and controlleroutput structs to PPSClient for testing; added CentralManagerService to launch file --- .../src/d_fall_pps/crazyradio/CrazyRadio.py | 2 +- pps_ws/src/d_fall_pps/launch/ppsLaunch.launch | 4 + .../src/d_fall_pps/launch/studentParams.yaml | 2 +- .../d_fall_pps/src/CentralManagerService.cpp | 12 ++ pps_ws/src/d_fall_pps/src/PPSClient.cpp | 141 ++++++++++++++---- 5 files changed, 132 insertions(+), 29 deletions(-) diff --git a/pps_ws/src/d_fall_pps/crazyradio/CrazyRadio.py b/pps_ws/src/d_fall_pps/crazyradio/CrazyRadio.py index 3d628118..86d82df6 100755 --- a/pps_ws/src/d_fall_pps/crazyradio/CrazyRadio.py +++ b/pps_ws/src/d_fall_pps/crazyradio/CrazyRadio.py @@ -94,7 +94,7 @@ class PPSRadioClient: def motorCommandCallback(data): """Callback for motor controller actions""" - cf_client._send_to_commander(0, 0, 0, 0, data.cmd1, data.cmd2 * 1000, data.cmd3 * 1000, data.cmd4 * 1000, CONTROLLER_MOTOR) + cf_client._send_to_commander(0, 0, 0, 0, data.cmd1, data.cmd2, data.cmd3, data.cmd4, CONTROLLER_MOTOR) rospy.loginfo("motor controller callback: %s, %s, %s, %s", data.cmd1, data.cmd2, data.cmd3, data.cmd4) def angleCommandCallback(data): diff --git a/pps_ws/src/d_fall_pps/launch/ppsLaunch.launch b/pps_ws/src/d_fall_pps/launch/ppsLaunch.launch index bb283c22..c47d076f 100644 --- a/pps_ws/src/d_fall_pps/launch/ppsLaunch.launch +++ b/pps_ws/src/d_fall_pps/launch/ppsLaunch.launch @@ -1,4 +1,7 @@ <launch> + + <node pkg="d_fall_pps" name="CentralManagerService" output="screen" type="CentralManagerService"> + </node> <node pkg="d_fall_pps" name="CrazyRadio" output="screen" type="CrazyRadio.py"> <rosparam command="load" file="$(find d_fall_pps)/launch/studentParams.yaml" /> @@ -15,6 +18,7 @@ <node pkg="d_fall_pps" name="SafeControllerService" output="screen" type="SafeControllerService"> </node> + <!-- When we have a GUI, this has to be adapted and included <node pkg="d_fall_pps" name="GUI" output="screen" type="GUI"> <rosparam command="load" file="$(find d_fall_pps)/launch/ControlParams.yaml" /> diff --git a/pps_ws/src/d_fall_pps/launch/studentParams.yaml b/pps_ws/src/d_fall_pps/launch/studentParams.yaml index 739ad896..a9845472 100644 --- a/pps_ws/src/d_fall_pps/launch/studentParams.yaml +++ b/pps_ws/src/d_fall_pps/launch/studentParams.yaml @@ -1,5 +1,5 @@ TeamName: 'Two' -CrazyFlieName: "cfTwo" +CrazyFlieName: "cfFour" CrazyFlieAddress: "radio://0/99/2M" SafeController: "" SafeControllerType: "" diff --git a/pps_ws/src/d_fall_pps/src/CentralManagerService.cpp b/pps_ws/src/d_fall_pps/src/CentralManagerService.cpp index 2cb409de..98a52e98 100644 --- a/pps_ws/src/d_fall_pps/src/CentralManagerService.cpp +++ b/pps_ws/src/d_fall_pps/src/CentralManagerService.cpp @@ -25,6 +25,18 @@ using namespace d_fall_pps; //send them back the CrazyflieContext (containing (maybe among other things) the area to fly in) bool returnCrazyflieContext(CentralManager::Request &request, CentralManager::Response &response) { ROS_INFO("central manager"); + + + //TBD: crazyflie-dependent area assignment instead of hardcoding + //request contains string crazyflieName + //respond with area boundaries upon request + response.context.localArea.xmin = -1000; + response.context.localArea.xmax = 1000; + response.context.localArea.ymin = -1000; + response.context.localArea.ymax = 1000; + response.context.localArea.zmin = -200; + response.context.localArea.zmax = 800; + return true; } diff --git a/pps_ws/src/d_fall_pps/src/PPSClient.cpp b/pps_ws/src/d_fall_pps/src/PPSClient.cpp index 276b2824..d174e138 100644 --- a/pps_ws/src/d_fall_pps/src/PPSClient.cpp +++ b/pps_ws/src/d_fall_pps/src/PPSClient.cpp @@ -24,8 +24,15 @@ #include "ros/ros.h" -#include "d_fall_pps/ViconData.h" + +//include autogenerated headers from srv files #include "d_fall_pps/RateController.h" +#include "d_fall_pps/AngleController.h" +#include "d_fall_pps/MotorController.h" +#include "d_fall_pps/CentralManager.h" + +//include autogenerated headers from msg files +#include "d_fall_pps/ViconData.h" #include "d_fall_pps/AngleCommand.h" #include "d_fall_pps/RateCommand.h" #include "d_fall_pps/MotorCommand.h" @@ -40,6 +47,7 @@ std::string cflie; //global sevices ros::ServiceClient rateClient; +ros::ServiceClient centralClient; ros::Publisher angleCommandPublisher; ros::Publisher rateCommandPublisher; @@ -49,21 +57,55 @@ ros::Publisher motorCommandPublisher; //ros::NodeHandle nodeHandle; -//acceptance test for crazyflie position and attitude -bool safetyCheck(ViconData data){ - CrazyflieContext CrazyflieContext; - - return true; -} +//move this section to a separate file that is included>>>>>>>>> +struct AreaBoundaries{ + float areaBoundxmin; + float areaBoundxmax; + float areaBoundymin; + float areaBoundymax; + float areaBoundzmin; + float areaBoundzmax; +}; + +AreaBoundaries Area; + + +//struct consistent with dusans controller +struct ControllerOutput +{ + //ControllerOutput():roll(0),pitch(0),yaw(0),thrust(0),motorCmd1(0),motorCmd2(0),motorCmd3(0),motorCmd4(0) {} + float roll; + float pitch; + float yaw; + float thrust; + float motorCmd1; + float motorCmd2; + float motorCmd3; + float motorCmd4; + uint8_t onboardControllerType; +}; + +ControllerOutput ControlCommandTest; +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<move this section to a separate file that is included //extract data from "data" and publish/add to service for controller //not void: sould give back controlldata -void ppsClientToController(ViconData data, bool autocontrol){ +void ppsClientToController(ViconData data, bool autocontrolOn){ if(data.crazyflieName == cflie){ - //TODO: - //Some way of choosing the correct controller: Safe or Custom - //using the area data + //call safecontroller if autocontrol is true + if(autocontrolOn){ + ControlCommandTest.motorCmd1 = 0; + ControlCommandTest.motorCmd2 = 0; + ControlCommandTest.motorCmd3 = 0; + ControlCommandTest.motorCmd4 = 0; + } + else { + ControlCommandTest.motorCmd1 = 1000; + ControlCommandTest.motorCmd2 = 1000; + ControlCommandTest.motorCmd3 = 1000; + ControlCommandTest.motorCmd4 = 1000; + } //TODO: //communicating with Controller @@ -94,24 +136,37 @@ void ppsClientToController(ViconData data, bool autocontrol){ } } - -//debugging -//int callbackCalls = 0; +//acceptance test for crazyflie position and attitude +bool safetyCheck(ViconData data){ + CrazyflieContext CrazyflieContext; + //ROS_INFO("in safetyCheck"); + //ROS_INFO_STREAM("ViconData: " << data.x << ", " << data.y << ", " << data.z); + + //position check + + //attitude check + + //all checks passed + return false; +} //is called upon every new arrival of data in main void viconCallback(const d_fall_pps::ViconData& data){ - //debugging - //++callbackCalls; - //ROS_INFO("Callback called #%d",callbackCalls); - //ROS_INFO("Received Pitch in this callback: %f", data.pitch); - //ROS_INFO("received data:"); ROS_INFO_STREAM(data); + ROS_INFO("in viconCallback"); + //ROS_INFO_STREAM(data); //ROS_INFO("My teamname is:"); ROS_INFO_STREAM(team); //ROS_INFO("My crazyflie is:"); ROS_INFO_STREAM(cflie); - //forward data to safety check - bool autocontrolOn = safetyCheck(data); + if(data.crazyflieName == cflie){ + //forward data to safety check + bool autocontrolOn = safetyCheck(data); + ROS_INFO_STREAM("autocontrolOn: " << autocontrolOn); + ppsClientToController(data, autocontrolOn); + } + else { + ROS_INFO("ViconData from other crazyflie received"); + } - ppsClientToController(data, autocontrolOn); } @@ -147,10 +202,10 @@ void callbackRateCommand(const ros::TimerEvent&) void callbackMotorCommand(const ros::TimerEvent&) { d_fall_pps::MotorCommand motorCommandPkg; - motorCommandPkg.cmd1 = 3; - motorCommandPkg.cmd2 = 3; - motorCommandPkg.cmd3 = 3; - motorCommandPkg.cmd4 = 3; + motorCommandPkg.cmd1 = ControlCommandTest.motorCmd1; + motorCommandPkg.cmd2 = ControlCommandTest.motorCmd2; + motorCommandPkg.cmd3 = ControlCommandTest.motorCmd3; + motorCommandPkg.cmd4 = ControlCommandTest.motorCmd4; motorCommandPublisher.publish(motorCommandPkg); ROS_INFO_STREAM("MotorCommandTimer pubslishes: " << motorCommandPkg.cmd1 << ", " << motorCommandPkg.cmd2 << ", " << motorCommandPkg.cmd3 << ", " << motorCommandPkg.cmd4); @@ -196,10 +251,42 @@ int main(int argc, char* argv[]){ motorCommandPublisher = nodeHandle.advertise <d_fall_pps::MotorCommand>("MotorCommand", 1); - //service: now only one available: to add several services depending on controller + //service + //to be expanded with additional services depending on controller (currently only one available) rateClient = nodeHandle.serviceClient<d_fall_pps::RateController>("/SafeControllerService/RateController"); + + //rateClient = nodeHandle.serviceClient<d_fall_pps::RateController>("/SafeControllerService/RateController", true); + //http://wiki.ros.org/roscpp/Overview/Services + //2.1 Persistenct Connection: ROS also allows for persistent connections to services. With a persistent connection, a client stays connected to a service. + // Otherwise, a client normally does a lookup and reconnects to a service each time. + + //service + centralClient = nodeHandle.serviceClient<d_fall_pps::CentralManager>("/CentralManagerService/CentralManager"); + + + //TBD: some sort of init procedure to get data from CentralManager upfront + //this is only for testing>>>>>>>>>>>>>>>>>>>>>>>>>>>> + CentralManager ManagerSettings; + if(centralClient.call(ManagerSettings)){ + + Area.areaBoundxmin = ManagerSettings.response.context.localArea.xmin; + Area.areaBoundxmax = ManagerSettings.response.context.localArea.xmin; + Area.areaBoundymin = ManagerSettings.response.context.localArea.xmin; + Area.areaBoundymax = ManagerSettings.response.context.localArea.xmin; + Area.areaBoundzmin = ManagerSettings.response.context.localArea.xmin; + Area.areaBoundzmax = ManagerSettings.response.context.localArea.xmin; + ROS_INFO("CentralManager responded"); + ROS_INFO("AreaBoundaries Set"); + + } + else{ + ROS_ERROR("Failed to call CentralManagerService. Callback is aborted"); + //return some useful stuff + return 0; + } + //<<<<<<<<<<<<<<<<<<<<<<<this is only for testing ros::spin(); return 0; -- GitLab