Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
nps_ivy.c
Go to the documentation of this file.
1#include "nps_ivy.h"
2
3#include <stdlib.h>
4#include <stdio.h>
5#include <sys/types.h>
6#include <unistd.h>
7#include <Ivy/ivy.h>
8
9#include <Ivy/ivyloop.h>
10
11#include "generated/airframe.h"
14#include "nps_main.h"
15#include "nps_autopilot.h"
16#include "nps_fdm.h"
17#include "nps_sensors.h"
18#include "nps_atmosphere.h"
19
20#include "generated/settings.h"
21#include "pprzlink/dl_protocol.h"
23
24#if USE_GPS
25#include "modules/gps/gps.h"
26#endif
27
30static int seq = 1;
31static int ap_launch_index;
32
33/* Gaia Ivy functions */
34static void on_WORLD_ENV(IvyClientPtr app __attribute__((unused)),
35 void *user_data __attribute__((unused)),
36 int argc, char *argv[]);
37
38/* Datalink Ivy functions */
39static void on_DL_SETTING(IvyClientPtr app __attribute__((unused)),
40 void *user_data __attribute__((unused)),
41 int argc, char *argv[]);
42
43static struct nps_ivy_metadata_t {
45 long int period_ns; // thread period in nanoseconds
47
48int find_launch_index(void);
50
52{
53 struct timespec now;
55 long int task_ns = (now.tv_sec - args->requestStart.tv_sec) * 1000000000L + (now.tv_nsec - args->requestStart.tv_nsec);
56
57 if (task_ns < args->period_ns)
58 {
59 return;
60 }
61 else
62 {
63 #ifdef PRINT_TIME
64 printf("IVY DISPLAY: task took longer than one period, exactly %f [ms], but the period is %f [ms]\n",
65 (double)task_ns / 1E6, (double)args->period_ns / 1E6);
66 #endif
67 clock_get_current_time(&args->requestStart);
69 }
70}
71
72void nps_ivy_init(char *ivy_bus, bool nodisplay)
73{
74 const char *agent_name = AIRFRAME_NAME"_NPS";
75 const char *ready_msg = AIRFRAME_NAME"_NPS Ready";
77
78 // bind on a general WORLD_ENV (not a reply to request)
79 IvyBindMsg(on_WORLD_ENV, NULL, "^(\\S*) WORLD_ENV (\\S*) (\\S*) (\\S*) (\\S*) (\\S*) (\\S*)");
80
81 // to be able to change datalink_enabled setting back on
82 IvyBindMsg(on_DL_SETTING, NULL, "^(\\S*) DL_SETTING (\\S*) (\\S*) (\\S*)");
83
84 // Register extra Ivy actions only if no_display is false
85 nps_ivy_metadata.period_ns = 3 * DISPLAY_DT * 1000000000L;
86 if (!nodisplay)
88
89#ifdef __APPLE__
90 const char *default_ivy_bus = "224.255.255.255";
91#else
92 const char *default_ivy_bus = "127.255.255.255";
93#endif
94 if (ivy_bus == NULL) {
96 } else {
97 IvyStart(ivy_bus);
98 }
99
101
103}
104
105/*
106 * Parse WORLD_ENV message from gaia.
107 *
108 */
109static void on_WORLD_ENV(IvyClientPtr app __attribute__((unused)),
110 void *user_data __attribute__((unused)),
111 int argc, char *argv[])
112{
113 if (argc < 6) { return; }
114
115 // wind speed in m/s
116 struct FloatVect3 wind;
117 wind.x = atof(argv[1]); //east
118 wind.y = atof(argv[2]); //north
119 wind.z = atof(argv[3]); //up
120
121 /* set wind speed in NED */
122 nps_atmosphere_set_wind_ned(wind.y, wind.x, -wind.z);
123
124 /* not used so far */
125 //float ir_contrast = atof(argv[4]);
126
127 /* set new time factor */
129
130#if USE_GPS
131 // directly set gps fix in modules/gps/gps_sim_nps.h
132 gps_has_fix = atoi(argv[6]); // gps_availability
133#endif
134
135}
136
137/*
138 * Send a WORLD_ENV_REQ message
139 */
140
141
143{
144 // First unbind from previous request if needed
145 if (ivyPtr != NULL) {
147 ivyPtr = NULL;
148 }
149
150 int pid = (int)getpid();
151
152 // Bind to the reply
153 ivyPtr = IvyBindMsg(on_WORLD_ENV, NULL, "^%d_%d (\\S*) WORLD_ENV (\\S*) (\\S*) (\\S*) (\\S*) (\\S*) (\\S*)", pid, seq);
154
155 // Send actual request
156 struct NpsFdm fdm_ivy;
157 memcpy(&fdm_ivy, &fdm, sizeof(struct NpsFdm));
158
159 IvySendMsg("nps %d_%d WORLD_ENV_REQ %f %f %f %f %f %f",
160 pid, seq,
161 DegOfRad(fdm_ivy.lla_pos_pprz.lat),
162 DegOfRad(fdm_ivy.lla_pos_pprz.lon),
163 (fdm_ivy.hmsl),
164 (fdm_ivy.ltpprz_pos.x),
165 (fdm_ivy.ltpprz_pos.y),
166 (fdm_ivy.ltpprz_pos.z));
167 seq++;
168
170}
171
173{
174#ifdef AP_LAUNCH
175 return AP_LAUNCH - 1; // index of AP_LAUNCH starts at 1, but it should be 0 here
176#else
177#if NB_SETTING > 0
178 static const char ap_launch[] = "aut_lau"; // short name
180
181 // list through the settings
182 // TODO: maybe search for a substring with if(strstr(sent, word) != NULL)
183 for (uint8_t idx=0;idx<NB_SETTING;idx++) {
184 if (strcmp(ap_settings[idx],ap_launch) == 0) {
185 return (int)idx;
186 }
187 }
188#endif
189 return -1;
190#endif
191}
192
193static void on_DL_SETTING(IvyClientPtr app __attribute__((unused)),
194 void *user_data __attribute__((unused)),
195 int argc, char *argv[])
196{
197 if (argc < 3) { return; }
198
199 if (atoi(argv[1]) != AC_ID) {
200 return;
201 }
202
203 /* HACK:
204 * we actually don't want to allow changing settings if datalink is disabled,
205 * but since we currently change this variable via settings we have to allow it
206 * TODO: only allow changing the datalink_enabled setting
207 */
208 uint8_t index = atoi(argv[2]);
209 float value = atof(argv[3]);
210#ifndef HITL
211 if (!datalink_enabled) {
212 DlSetting(index, value);
214 }
215#endif
216 printf("setting %d %f\n", index, value);
217
218 /*
219 * In case of HITL, update nps_autopilot.launch from DL_SETTINGS
220 * so the plane can be properly launched.
221 *
222 * In case of STIL nps_update_launch_from_dl() is an empty function
223 */
224 if ((ap_launch_index >= 0) || (ap_launch_index < NB_SETTING)) {
225 if (index==ap_launch_index){
227 }
228 }
229}
230
231
233{
234 struct NpsFdm fdm_ivy;
235 struct NpsSensors sensors_ivy;
236
237 // make a local copy with mutex
239 memcpy(&fdm_ivy, fdm_data, sizeof(fdm));
242
243 IvySendMsg("%d NPS_RATE_ATTITUDE %f %f %f %f %f %f",
244 AC_ID,
245 DegOfRad(fdm_ivy.body_ecef_rotvel.p),
246 DegOfRad(fdm_ivy.body_ecef_rotvel.q),
247 DegOfRad(fdm_ivy.body_ecef_rotvel.r),
248 DegOfRad(fdm_ivy.ltp_to_body_eulers.phi),
249 DegOfRad(fdm_ivy.ltp_to_body_eulers.theta),
250 DegOfRad(fdm_ivy.ltp_to_body_eulers.psi));
251 IvySendMsg("%d NPS_POS_LLH %f %f %f %f %f %f %f %f %f",
252 AC_ID,
253 (fdm_ivy.lla_pos_pprz.lat),
254 (fdm_ivy.lla_pos_geod.lat),
255 (fdm_ivy.lla_pos_geoc.lat),
256 (fdm_ivy.lla_pos_pprz.lon),
257 (fdm_ivy.lla_pos_geod.lon),
258 (fdm_ivy.lla_pos_pprz.alt),
259 (fdm_ivy.lla_pos_geod.alt),
260 (fdm_ivy.agl),
261 (fdm_ivy.hmsl));
262 IvySendMsg("%d NPS_SPEED_POS %f %f %f %f %f %f %f %f %f",
263 AC_ID,
264 (fdm_ivy.ltpprz_ecef_accel.x),
265 (fdm_ivy.ltpprz_ecef_accel.y),
266 (fdm_ivy.ltpprz_ecef_accel.z),
267 (fdm_ivy.ltpprz_ecef_vel.x),
268 (fdm_ivy.ltpprz_ecef_vel.y),
269 (fdm_ivy.ltpprz_ecef_vel.z),
270 (fdm_ivy.ltpprz_pos.x),
271 (fdm_ivy.ltpprz_pos.y),
272 (fdm_ivy.ltpprz_pos.z));
273 IvySendMsg("%d NPS_GYRO_BIAS %f %f %f",
274 AC_ID,
275 DegOfRad(RATE_FLOAT_OF_BFP(sensors_ivy.gyro.bias_random_walk_value.x) + sensors_ivy.gyro.bias_initial.x),
276 DegOfRad(RATE_FLOAT_OF_BFP(sensors_ivy.gyro.bias_random_walk_value.y) + sensors_ivy.gyro.bias_initial.y),
277 DegOfRad(RATE_FLOAT_OF_BFP(sensors_ivy.gyro.bias_random_walk_value.z) + sensors_ivy.gyro.bias_initial.z));
278
279 /* transform magnetic field to body frame */
280 struct DoubleVect3 h_body;
281 double_quat_vmult(&h_body, &fdm_ivy.ltp_to_body_quat, &fdm_ivy.ltp_h);
282
283 IvySendMsg("%d NPS_SENSORS_SCALED %f %f %f %f %f %f",
284 AC_ID,
285 ((sensors_ivy.accel.value.x - sensors_ivy.accel.neutral.x) / NPS_ACCEL_SENSITIVITY_XX),
286 ((sensors_ivy.accel.value.y - sensors_ivy.accel.neutral.y) / NPS_ACCEL_SENSITIVITY_YY),
287 ((sensors_ivy.accel.value.z - sensors_ivy.accel.neutral.z) / NPS_ACCEL_SENSITIVITY_ZZ),
288 h_body.x,
289 h_body.y,
290 h_body.z);
291
292 IvySendMsg("%d NPS_WIND %f %f %f",
293 AC_ID,
294 fdm_ivy.wind.x,
295 fdm_ivy.wind.y,
296 fdm_ivy.wind.z);
297
300 }
301}
302
303void nps_ivy_run(void)
304{
305 IvyMainLoop();
306}
#define sensors(...)
Device independent GPS code (interface)
bool gps_has_fix
Definition gps_sim_nps.c:30
void double_quat_vmult(struct DoubleVect3 *v_out, struct DoubleQuat *q, struct DoubleVect3 *v_in)
#define RATE_FLOAT_OF_BFP(_ai)
uint16_t foo
Definition main_demo5.c:58
void nps_atmosphere_set_wind_ned(double wind_north, double wind_east, double wind_down)
Atmosphere model (pressure, wind) for NPS.
struct NpsFdm fdm
Holds all necessary NPS FDM state information.
void nps_ivy_init(char *ivy_bus, bool nodisplay)
Definition nps_ivy.c:72
static void on_DL_SETTING(IvyClientPtr app, void *user_data, int argc, char *argv[])
Definition nps_ivy.c:193
struct timespec requestStart
Definition nps_ivy.c:44
void nps_ivy_run(void)
Definition nps_ivy.c:303
void nps_ivy_send_WORLD_ENV_REQ(void)
Definition nps_ivy.c:142
long int period_ns
Definition nps_ivy.c:45
static void on_WORLD_ENV(IvyClientPtr app, void *user_data, int argc, char *argv[])
Definition nps_ivy.c:109
bool nps_ivy_send_world_env
Definition nps_ivy.c:28
static MsgRcvPtr ivyPtr
Definition nps_ivy.c:29
void nps_ivy_beforeloop(struct nps_ivy_metadata_t *args)
Definition nps_ivy.c:51
static int seq
Definition nps_ivy.c:30
static struct nps_ivy_metadata_t nps_ivy_metadata
static int ap_launch_index
Definition nps_ivy.c:31
void nps_ivy_display(struct NpsFdm *fdm_data, struct NpsSensors *sensors_data)
Definition nps_ivy.c:232
int find_launch_index(void)
Definition nps_ivy.c:172
#define DISPLAY_DT
Definition nps_main.h:21
#define clock_get_current_time(_x)
Definition nps_main.h:17
void nps_update_launch_from_dl(uint8_t value)
void nps_set_time_factor(float time_factor)
pthread_mutex_t fdm_mutex
static uint32_t idx
Paparazzi double precision floating point algebra.
Paparazzi floating point algebra.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.