UWBDataPublisher.cpp 6.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//    ROS node that publishes the localization data from sensor fusion of the crazyflie, using uwb for coordinates
//    Copyright (C) 2017  Michael Rogenmoser, Tiago Salzmann, Yvan Bosshard
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

17
18
#define DEG2RAD	0.01745329251

19
#include <stdlib.h>
20
#include <string.h>
21
22
23
24

#include <ros/package.h>
#include <rosbag/bag.h>

25
#include "d_fall_pps/CMQuery.h"
26
#include "d_fall_pps/Anchors.h"
27
28
#include "d_fall_pps/CrazyflieData.h"
#include "d_fall_pps/CrazyflieContext.h"
29

Yvan Bosshard's avatar
Yvan Bosshard committed
30
31
#include "IndoorNewton.h"

32
#include "UWBDataPublisher.h"
33

34
35
using namespace d_fall_pps;

Yvan Bosshard's avatar
Yvan Bosshard committed
36
37
// This is a test comment to check wtf git does

38
39
40
41
42
43
// the clientID defines namespace and identifier in the CentralManagerService
int clientID;

CrazyflieContext context;
rosbag::Bag bag;

44
ros::ServiceClient centralManager;
45
ros::ServiceClient uwbManager;
46
47
ros::Publisher UWBDataPublisher;

48
double rollPitchYaw[3];
49

50
UWBAnchorArray anchors;
51
52
53
54
55
56
57
double anchorPositions[3*UWB_NUM_ANCHORS];

double prevDistances[UWB_NUM_ANCHORS] = {0};

KalmanState xState;
KalmanState yState;
KalmanState zState;
58

59
60
61
62
int main(int argc, char* argv[])
{
    ros::init(argc, argv, "UWBDataPublisher");
    ros::NodeHandle nodeHandle("~");
63
    ros::NodeHandle namespaceNodeHandle = ros::NodeHandle();
64
65

    if(!loadParameters(nodeHandle))
66
    	return -1;
67

68
    centralManager = nodeHandle.serviceClient<CMQuery>("/CentralManagerService/Query", false);
69
	loadCrazyflieContext();
70
71
72
73
	ros::Subscriber dbChangedSubscriber = nodeHandle.subscribe("/my_GUI/DBChanged", 1, dbChangedCallback);

	uwbManager = nodeHandle.serviceClient<Anchors>("/UWBManagerService/UWBData", false);
	ros::Subscriber enableUWBSubscriber = nodeHandle.subscribe("/my_GUI/enableUWB", 1, uwbChangedCallback);
74
75
76

	// Subscribe to the anchor positions and all relevant Data from crazyradio
	ros::Subscriber cfRPYSubscriber = namespaceNodeHandle.subscribe("CrazyRadio/RPY",10,cfRPYCallback);
77
	ros::Subscriber uwbLocationSubscriber = namespaceNodeHandle.subscribe("CrazyRadio/AnchorDistances", 10, cfDistancesCallback);
Yvan Bosshard's avatar
Yvan Bosshard committed
78

79
	UWBDataPublisher = nodeHandle.advertise<CrazyflieData>("UWBData", 10);
80

81
82
83
    std::string package_path;
	package_path = ros::package::getPath("d_fall_pps") + "/";
	std::string record_file = package_path + "log/UWBDataPublisherLog.bag";
84
85
    bag.open(record_file, rosbag::bagmode::Write);

86
87
    initKalmanStates();

88
    ROS_INFO_STREAM("[UWBDataPublisher] started!");
89

90
    ros::spin();
91
92
93
94
95
    bag.close();
    
    return 0;
}

96
97
98
99
100
void d_fall_pps::dbChangedCallback(const std_msgs::Int32& msg)
{
	d_fall_pps::loadCrazyflieContext();
}

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
void d_fall_pps::uwbChangedCallback(const std_msgs::Int32& msg)
{
	d_fall_pps::loadUWBSettings();
}

void d_fall_pps::loadUWBSettings()
{
	Anchors a;

	if(uwbManager.call(a))
	{
		anchors = a.response.anchorArray;
	}
	else
	{
		ROS_ERROR("[UWBDataPublisher] Could not update UWB Settings!");
	}

	for(int i = 0; i < UWB_NUM_ANCHORS; ++i)
	{
		anchorPositions[3*i] = anchors.data[i].x;
		anchorPositions[3*i + 1] = anchors.data[i].y;
		anchorPositions[3*i + 2] = anchors.data[i].z;
	}
}

127
128
129
//Callback function to handle roll pitch yaw information from CF
void d_fall_pps::cfRPYCallback(const std_msgs::Float32MultiArray &arrRPY)
{
130
131
132
	rollPitchYaw[0] = arrRPY.data[0] * DEG2RAD;
	rollPitchYaw[1] = arrRPY.data[1] * DEG2RAD;
	rollPitchYaw[2] = arrRPY.data[2] * DEG2RAD;
133
134
}

135
// Callback functions to handle times information from CF
136
void d_fall_pps::cfDistancesCallback(const std_msgs::UInt32MultiArray &distances)
137
138
139
140
{
	CrazyflieData data;
    
    double arrXYZ[3] = {0};
141
    calculateXYZ(distances, arrXYZ);
142
143
144
145
146
147
148
149
150
151
152
153
154
155
	
	data.crazyflieName = context.crazyflieName;
	data.x = arrXYZ[0];
	data.y = arrXYZ[1];
	data.z = arrXYZ[2];
	data.roll = rollPitchYaw[0];
	data.pitch = rollPitchYaw[1];
	data.yaw = rollPitchYaw[2];
	data.occluded = false;
	data.acquiringTime = 0; //???
	
	UWBDataPublisher.publish(data);
}

156
//calculates position from anchor locations and distances -> forces algorithm?
157
void d_fall_pps::calculateXYZ(const std_msgs::UInt32MultiArray& distances, double(&xyz)[3])
158
{
Yvan Bosshard's avatar
Yvan Bosshard committed
159
160
161
162
163
164
165
166
	double dist[UWB_NUM_ANCHORS];
	double result[3];

	for(unsigned int i = 0; i < UWB_NUM_ANCHORS; i++)
	{
		dist[i] = distances.data[i] / 100.0; //in dm

		if(distances.data[i] == 0)
167
168
		{
			dist[i] = prevDistances[i];
Yvan Bosshard's avatar
Yvan Bosshard committed
169
			ROS_WARN("[UWBDataPublisher] bad reading from Anchor %i", i);
170
171
172
		}
		else
			prevDistances[i] = dist[i];
Yvan Bosshard's avatar
Yvan Bosshard committed
173
174
	}

175
176
177
178
179
	IndoorNewton(anchorPositions, dist, result, 50);

	updateKalmanState(xState, result[0] / 10.0);
	updateKalmanState(yState, result[1] / 10.0);
	updateKalmanState(zState, result[2] / 10.0);
Yvan Bosshard's avatar
Yvan Bosshard committed
180

181
182
183
184
185
186
187
	
	// Use this for Kalmanfiltered position
	//xyz[0] = xState.x;
	//xyz[1] = yState.x;
	//xyz[2] = zState.x;

	// Use this for unfiltered position
Yvan Bosshard's avatar
Yvan Bosshard committed
188
189
190
	xyz[0] = result[0] / 10.0;
	xyz[1] = result[1] / 10.0;
	xyz[2] = result[2] / 10.0;
191
}
192

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
void d_fall_pps::initKalmanStates()
{
	// Init x state
	// TODO Update
	xState.x = 0;
	xState.q = 0.005;
	xState.r = 6;
	xState.p = 0;

	// Init y state
	// TODO Update
	yState.x = 0;
	yState.q = 0.005;
	yState.r = 6;
	yState.p = 0;

	// Init z state
	// TODO Update
	zState.x = 0;
	zState.q = 0.005;
	zState.r = 6;
	zState.p = 0;
}
216

217
218
219
220
221
222
void d_fall_pps::updateKalmanState(KalmanState& state, double measurment)
{
	state.p += state.q;
	state.k = state.p / (state.p + state.r);
	state.x += state.k * (measurment - state.x);
	state.p *= (1 - state.k);
223
224
225
226
227
228
229
230
231
232
233
234
}

// Loads the current context of the client
void d_fall_pps::loadCrazyflieContext()
{
	CMQuery contextCall;
	contextCall.request.studentID = clientID;

	centralManager.waitForExistence(ros::Duration(-1));

	if(centralManager.call(contextCall))
	{
235
236
		context = contextCall.response.crazyflieContext;
		ROS_INFO_STREAM("[UWBDataPublisher] context updated");
237
238
239
240
241
242
243
244
245
246
247
248
249
	}
}

// Loads the parameters of the node handle
bool d_fall_pps::loadParameters(ros::NodeHandle &nodeHandle)
{
	if(!nodeHandle.getParam("clientID", clientID))
	{
		ROS_ERROR("Failed to get clientID!");
		return false;
	}

	return true;
250
251
252
}

// calculatse distances from passed microseconds
253
float d_fall_pps::tiagosAwesomeFormula(uint32_t ticks)
254
{
255
	return ticks * SPEED_OF_LIGHT / LOCO_DECK_FRQ;
256
	//return (time * 75.0 * (1.0 / (128.0 * 499.2)));
257
}