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