MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
mbc.c
Go to the documentation of this file.
1 /*
2  * MBDyn (C) is a multibody analysis code.
3  * http://www.mbdyn.org
4  *
5  * Copyright (C) 1996-2017
6  *
7  * Pierangelo Masarati <masarati@aero.polimi.it>
8  * Paolo Mantegazza <mantegazza@aero.polimi.it>
9  *
10  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
11  * via La Masa, 34 - 20156 Milano, Italy
12  * http://www.aero.polimi.it
13  *
14  * Changing this copyright notice is forbidden.
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation (version 2 of the License).
19  *
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29  */
30 
31 #include "mbconfig.h" /* This goes first in every *.c,*.cc file */
32 
33 #ifdef USE_SOCKET
34 
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <strings.h>
39 #include <signal.h>
40 #include <errno.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <netdb.h>
44 #include <sys/un.h>
45 #include <arpa/inet.h>
46 
47 #include "mbc.h"
48 #include "sock.h"
49 
50 /* private flags for internal use */
51 enum sock_flags_t {
52  MBC_SF_VALID = 0x1U
53 };
54 
55 static const char *
56 mbc_cmd2str(uint8_t cmd)
57 {
58  switch (cmd) {
59  case ES_REGULAR_DATA: return "REGULAR_DATA";
60  case ES_GOTO_NEXT_STEP: return "GOTO_NEXT_STEP";
61  case ES_ABORT: return "ABORT";
62  case ES_REGULAR_DATA_AND_GOTO_NEXT_STEP: return "REGULAR_DATA_AND_GOTO_NEXT_STEP";
63  case ES_NEGOTIATION: return "NEGOTIATION";
64  case ES_OK: return "OK";
65  default:
66  break;
67  }
68 
69  return "UNKNOWN";
70 }
71 
72 /* validate command
73  *
74  * command needs to be set in mbc->cmd
75  */
76 int
78 {
79  switch (mbc->cmd) {
80  case ES_REGULAR_DATA:
81  case ES_GOTO_NEXT_STEP:
82  case ES_ABORT:
84  case ES_NEGOTIATION:
85  case ES_OK:
86  return 0;
87  }
88 
89  fprintf(stderr, "unknown cmd (%lu) from peer\n", (unsigned long)mbc->cmd);
90  return -1;
91 }
92 
93 /* get command from peer
94  *
95  * command is stored in mbc->cmd
96  */
97 int
98 mbc_get_cmd(mbc_t *mbc)
99 {
100  ssize_t rc;
101 
102  rc = recv(mbc->sock, (void *)&mbc->cmd, sizeof(mbc->cmd),
103  mbc->recv_flags);
104  if (rc != sizeof(mbc->cmd)) {
105  fprintf(stderr, "recv(cmd=%lu) failed\n", (unsigned long)mbc->cmd);
106  return -1;
107  }
108 
109  if (mbc_check_cmd(mbc)) {
110  return -1;
111  }
112 
113  return 0;
114 }
115 
116 /* put command to peer
117  *
118  * command needs to be set in mbc->cmd
119  */
120 int
121 mbc_put_cmd(mbc_t *mbc)
122 {
123  ssize_t rc;
124 
125  if (mbc_check_cmd(mbc)) {
126  return -1;
127  }
128 
129  if (mbc->verbose) {
130  fprintf(stdout, "cmd to peer: %lu (%s)\n",
131  (unsigned long)mbc->cmd, mbc_cmd2str(mbc->cmd));
132  }
133 
134  rc = send(mbc->sock, (const void *)&mbc->cmd, sizeof(mbc->cmd),
135  mbc->send_flags);
136  if (rc != sizeof(mbc->cmd)) {
137  fprintf(stderr, "send(cmd=%lu) failed (%ld)\n", (unsigned long)mbc->cmd, (long)rc);
138  return -1;
139  }
140 
141  return 0;
142 }
143 
144 /* initialize communication - do not call directly */
145 static int
146 mbc_init(mbc_t *mbc, struct sockaddr *addr, socklen_t socklen)
147 {
148  unsigned long timeout = mbc->timeout*1000000;
149  unsigned long useconds = 100000;
150 
151  if (mbc->sock < 0) {
152  fprintf(stderr, "unable to create socket\n");
153  return -1;
154  }
155 
156  for ( ; ; ) {
157  if (connect(mbc->sock, addr, socklen) < 0) {
158  int save_errno = errno;
159  const char *msg;
160 
161  if (timeout != 0) {
162  switch (save_errno) {
163  case ECONNREFUSED: /* inet */
164  case ENOENT: /* unix */
165  /* Socket does not exist yet; retry */
166  /* TODO: replace usleep with nanosleep */
167  usleep(useconds);
168  if (mbc->timeout > 0) {
169  timeout -= useconds;
170  }
171  continue;
172  }
173  }
174 
175  /* Connect failed */
176  msg = strerror(save_errno);
177  fprintf(stderr, "unable to connect to peer (%ld: %s)\n",
178  (long)save_errno, msg);
179  return -1;
180  }
181 
182  break;
183  }
184 
185  /* MSG_NOSIGNAL disables SIGPIPE
186  * MSG_WAITALL blocks recv() until all data is available
187  */
188  mbc->recv_flags |= (MSG_NOSIGNAL | MSG_WAITALL);
189  mbc->send_flags |= MSG_NOSIGNAL;
190 
191  mbc->sock_flags = MBC_SF_VALID;
192 
193  return 0;
194 }
195 
196 /* initialize communication using inet socket
197  *
198  * mbc must be a pointer to a valid mbc_t structure
199  * host and port must be defined
200  */
201 int
202 mbc_inet_init(mbc_t *mbc, const char *host, short unsigned port)
203 {
204  struct sockaddr_in addr = { 0 };
205 
206  if (host == NULL) {
207  fprintf(stderr, "host must be defined\n");
208  return -1;
209  }
210 
211  if (port == 0) {
212  fprintf(stderr, "port must be defined\n");
213  return -1;
214  }
215 
216  mbc->sock = mbdyn_make_inet_socket(&addr, host, port, 0, NULL);
217 
218  return mbc_init(mbc, (struct sockaddr *)&addr, sizeof(addr));
219 }
220 
221 /* initialize communication using unix socket
222  *
223  * mbc must be a pointer to a valid mbc_t structure
224  * path must be defined
225  */
226 int
227 mbc_unix_init(mbc_t *mbc, const char *path)
228 {
229  struct sockaddr_un addr = { 0 };
230 
231  if (path == NULL) {
232  fprintf(stderr, "path must be defined\n");
233  return -1;
234  }
235 
236  mbc->sock = mbdyn_make_named_socket(&addr, path, 0, NULL);
237 
238  return mbc_init(mbc, (struct sockaddr *)&addr, sizeof(addr));
239 }
240 
241 /* destroy communication
242  *
243  * does NOT free the mbc structure
244  */
245 static int
246 mbc_destroy(mbc_t *mbc)
247 {
248  /* TODO: send "abort"? */
249  if (mbc->sock >= 0) {
250  close(mbc->sock);
251  mbc->sock = -1;
252  }
253 
254  return 0;
255 }
256 
257 /*
258  * reference node stuff
259  */
260 
261 static int
262 mbc_rigid_init(mbc_rigid_t *mbc, unsigned refnode,
263  unsigned labels, unsigned *rotp, unsigned accels)
264 {
265  uint32_t offset = 0;
266  int do_retry = 1;
267 
268  mbc->k_size = 0;
269  mbc->r_k_label = -1;
270  mbc->r_k_x = -1;
271  mbc->r_k_theta = -1;
272  mbc->r_k_r = -1;
273  mbc->r_k_euler_123 = -1;
274  mbc->r_k_xp = -1;
275  mbc->r_k_omega = -1;
276  mbc->r_k_xpp = -1;
277  mbc->r_k_omegap = -1;
278  mbc->d_size = 0;
279  mbc->r_d_label = -1;
280  mbc->r_d_f = -1;
281  mbc->r_d_m = -1;
282 
283  if (!refnode) {
284  return 0;
285  }
286 
287  if (labels) {
288  mbc->r_k_label = offset/sizeof(uint32_t);
289  /* skip 2 uint32_t to ensure alignment of double */
290  offset += 2*sizeof(uint32_t);
291  }
292 
293  mbc->r_k_x = offset/sizeof(double);
294  offset += 3*sizeof(double);
295 
296 retry:;
297  switch (MBC_U_REF_NODE_ROT_2_ROT(*rotp)) {
298  case MBC_ROT_NONE:
299  if (do_retry) {
300  *rotp = MBC_U_ROT_2_REF_NODE_ROT(*rotp);
301  do_retry = 0;
302  goto retry;
303  }
304  fprintf(stderr, "rotation must be defined for reference node\n");
305  return -1;
306 
307  case MBC_ROT_THETA:
308  mbc->r_k_theta = offset/sizeof(double);
309  offset += 3*sizeof(double);
310  break;
311 
312  case MBC_ROT_MAT:
313  mbc->r_k_r = offset/sizeof(double);
314  offset += 9*sizeof(double);
315  break;
316 
317  case MBC_ROT_EULER_123:
318  mbc->r_k_euler_123 = offset/sizeof(double);
319  offset += 3*sizeof(double);
320  break;
321 
322  default:
323  fprintf(stderr, "unknown rotation mode 0x%lx\n", (unsigned long)*rotp);
324  return -1;
325  }
326 
327  mbc->r_k_xp = offset/sizeof(double);
328  offset += 3*sizeof(double);
329 
330  mbc->r_k_omega = offset/sizeof(double);
331  offset += 3*sizeof(double);
332 
333  if (accels) {
334  mbc->r_k_xpp = offset/sizeof(double);
335  offset += 3*sizeof(double);
336 
337  mbc->r_k_omegap = offset/sizeof(double);
338  offset += 3*sizeof(double);
339  }
340 
341  mbc->k_size = offset;
342 
343  if (labels) {
344  mbc->r_d_label = offset/sizeof(uint32_t);
345  /* skip 2 uint32_t to ensure alignment of double */
346  offset += 2*sizeof(uint32_t);
347  mbc->d_size += 2*sizeof(uint32_t);
348  }
349 
350  mbc->r_d_f = offset/sizeof(double);
351  offset += 3*sizeof(double);
352  mbc->d_size += 3*sizeof(double);
353 
354  mbc->r_d_m = offset/sizeof(double);
355  offset += 3*sizeof(double);
356  mbc->d_size += 3*sizeof(double);
357 
358  return 0;
359 }
360 
361 /*
362  * nodal stuff
363  */
364 
365 /* get nodal motion from peer
366  *
367  * if "rigid", access reference node motion
368  * using macros MBC_X, MBC_R, MBC_V, MBC_W
369  * if mbc->nodes > 0, access nodal motion using macros MBC_N_*
370  */
371 int
373 {
374  if (mbc_get_cmd((mbc_t*)mbc)) {
375  return -1;
376  }
377 
378  if (mbc->mbc.verbose) {
379  fprintf(stdout, "cmd from peer: %lu (%s)\n",
380  (unsigned long)mbc->mbc.cmd, mbc_cmd2str(mbc->mbc.cmd));
381  }
382 
383  if (mbc->mbc.cmd == ES_ABORT) {
384  fprintf(stdout, "got ABORT from peer\n");
385  return -1;
386  }
387 
388  if (mbc->mbc.cmd != ES_GOTO_NEXT_STEP) {
389  if (MBC_F_REF_NODE(mbc)) {
390  ssize_t rc;
391 
392  rc = recv(mbc->mbc.sock, (void *)MBC_R_KINEMATICS(mbc),
394  if (rc != MBC_R_KINEMATICS_SIZE(mbc)) {
395  fprintf(stderr, "recv(%lu) reference node failed (%ld)\n",
396  (unsigned long)MBC_R_KINEMATICS_SIZE(mbc), (long)rc);
397  return -1;
398  }
399  }
400 
401  if (mbc->nodes > 0) {
402  ssize_t rc;
403 
404  rc = recv(mbc->mbc.sock, (void *)MBC_N_KINEMATICS(mbc),
406  if (rc != MBC_N_KINEMATICS_SIZE(mbc)) {
407  fprintf(stderr, "recv(%lu) x, theta, xP, omega failed (%ld)\n",
408  (unsigned long)MBC_N_KINEMATICS_SIZE(mbc), (long)rc);
409  return -1;
410  }
411  }
412  }
413 
414  return 0;
415 }
416 
417 /* put forces to peer
418  *
419  * if "rigid", force and moment must be set in storage pointed to
420  * by macros MBC_F, MBC_M
421  * if mbc->nodes > 0, nodal forces must be set in storage pointed to
422  * by macro MBC_N_F, MBC_N_M
423  */
424 int
425 mbc_nodal_put_forces(mbc_nodal_t *mbc, int last)
426 {
427  if (last) {
428  if (mbc->mbc.data_and_next) {
430 
431  } else {
432  mbc->mbc.cmd = ES_GOTO_NEXT_STEP;
433  }
434 
435  } else {
436  mbc->mbc.cmd = ES_REGULAR_DATA;
437  }
438 
439  if (mbc_put_cmd((mbc_t *)mbc)) {
440  return -1;
441  }
442 
443  if (mbc->mbc.cmd != ES_GOTO_NEXT_STEP) {
444  /* reference node */
445  if (MBC_F_REF_NODE(mbc)) {
446  ssize_t rc;
447 
448  rc = send(mbc->mbc.sock, (const void *)MBC_R_DYNAMICS(mbc),
449  MBC_R_DYNAMICS_SIZE(mbc), mbc->mbc.send_flags);
450  if (rc != MBC_R_DYNAMICS_SIZE(mbc)) {
451  fprintf(stderr, "send(%lu) reference node failed (%ld)\n",
452  (unsigned long)MBC_R_DYNAMICS_SIZE(mbc), (long)rc);
453  return -1;
454  }
455  }
456 
457  /* nodal */
458  if (mbc->nodes > 0) {
459  ssize_t rc;
460 
461  rc = send(mbc->mbc.sock, (const void *)MBC_N_DYNAMICS(mbc),
462  MBC_N_DYNAMICS_SIZE(mbc), mbc->mbc.send_flags);
463  if (rc != MBC_N_DYNAMICS_SIZE(mbc)) {
464  fprintf(stderr, "send(%lu) nodes failed (%ld)\n",
465  (unsigned long)MBC_N_DYNAMICS_SIZE(mbc), (long)rc);
466  return -1;
467  }
468  }
469  }
470 
471  return 0;
472 }
473 
474 /* initialize nodal data
475  *
476  * mbc must be a pointer to a valid mbc_nodal_t structure
477  *
478  * at least reference node motion must be defined (refnode != 0),
479  * or nodes must be > 0
480  *
481  * if nodes > 0, mallocs memory that needs to be freed calling
482  * mbc_nodal_destroy()
483  *
484  * rot must be one of MBC_ROT_*
485  *
486  * if accelerations != 0 accelerations are also output
487  */
488 int
489 mbc_nodal_init(mbc_nodal_t *mbc, unsigned refnode, unsigned nodes,
490  unsigned labels, unsigned rot, unsigned accels)
491 {
492  mbc->nodes = nodes;
493  MBC_F_SET(mbc, MBC_NODAL);
494 
495  if (refnode) {
496  MBC_F_SET_REF_NODE(mbc);
497  }
498 
499  if (!MBC_F_REF_NODE(mbc) && mbc->nodes == 0) {
500  fprintf(stderr, "need at least 1 node or reference node data\n");
501  return -1;
502  }
503 
504  switch (rot & MBC_ROT_MASK) {
505  case MBC_ROT_NONE:
506  break;
507 
508  case MBC_ROT_MAT:
509  MBC_F_SET_ROT_MAT(mbc);
510  break;
511 
512  case MBC_ROT_THETA:
513  MBC_F_SET_ROT_THETA(mbc);
514  break;
515 
516  case MBC_ROT_EULER_123:
518  break;
519 
520  default:
521  fprintf(stderr, "unknown orientation parametrization 0x%lx in flags\n", (unsigned long)rot);
522  return -1;
523  }
524 
525  if (accels) {
526  MBC_F_SET_ACCELS(mbc);
527  }
528 
529  if (labels) {
530  MBC_F_SET_LABELS(mbc);
531  }
532 
533  if (mbc_rigid_init(&mbc->mbcr, refnode, labels, &rot, accels)) {
534  return -1;
535  }
536  MBC_F_SET(mbc, (rot & MBC_REF_NODE_ROT_MASK));
537 
538  mbc->n_ptr = NULL;
539  mbc->n_k_labels = NULL;
540  mbc->n_k_x = NULL;
541  mbc->n_k_theta = NULL;
542  mbc->n_k_r = NULL;
543  mbc->n_k_euler_123 = NULL;
544  mbc->n_k_xp = NULL;
545  mbc->n_k_omega = NULL;
546  mbc->n_k_xpp = NULL;
547  mbc->n_k_omegap = NULL;
548  mbc->n_d_labels = NULL;
549  mbc->n_d_f = NULL;
550  mbc->n_d_m = NULL;
551 
552  if (mbc->nodes > 0) {
553  char *ptr;
554 
555  mbc->k_size = (3 + 3); /* x, xp */
556 
557  switch (MBC_F_ROT(mbc)) {
558  case MBC_ROT_NONE:
559  break;
560 
561  case MBC_ROT_MAT:
562  mbc->k_size += 9 + 3;
563  break;
564 
565  case MBC_ROT_THETA:
566  case MBC_ROT_EULER_123:
567  mbc->k_size += 3 + 3;
568  break;
569  }
570 
571  if (MBC_F_ACCELS(mbc)) {
572  mbc->k_size += 3;
573  if (MBC_F_ROT(mbc) != MBC_ROT_NONE) {
574  mbc->k_size += 3;
575  }
576  }
577 
578  mbc->k_size *= mbc->nodes*sizeof(double);
579 
580  mbc->d_size = mbc->nodes*3*sizeof(double);
581  if (MBC_F_ROT(mbc) != MBC_ROT_NONE) {
582  mbc->d_size += mbc->nodes*3*sizeof(double);
583  }
584 
585  if (MBC_F_LABELS(mbc)) {
586  mbc->k_size += mbc->nodes*sizeof(uint32_t);
587  mbc->d_size += mbc->nodes*sizeof(uint32_t);
588  }
589 
590  mbc->n_ptr = (void *)malloc(MBC_N_SIZE(mbc));
591  if (mbc->n_ptr == NULL) {
592  fprintf(stderr, "nodal data malloc failed\n");
593  return -1;
594  }
595 
596  ptr = mbc->n_ptr;
597 
598  if (MBC_F_LABELS(mbc)) {
599  mbc->n_k_labels = (uint32_t *)ptr;
600  ptr += (nodes + nodes%2)*sizeof(uint32_t);
601  }
602 
603  mbc->n_k_x = (double *)ptr;
604  ptr += 3*sizeof(double)*nodes;
605 
606  switch (MBC_F_ROT(mbc)) {
607  case MBC_ROT_NONE:
608  break;
609 
610  case MBC_ROT_MAT:
611  mbc->n_k_r = (double *)ptr;
612  ptr += 9*sizeof(double)*nodes;
613  break;
614 
615  case MBC_ROT_THETA:
616  mbc->n_k_theta = (double *)ptr;
617  ptr += 3*sizeof(double)*nodes;
618  break;
619 
620  case MBC_ROT_EULER_123:
621  mbc->n_k_euler_123 = (double *)ptr;
622  ptr += 3*sizeof(double)*nodes;
623  break;
624  }
625 
626  mbc->n_k_xp = (double *)ptr;
627  ptr += 3*sizeof(double)*nodes;
628 
629  if (MBC_F_ROT(mbc) != MBC_ROT_NONE) {
630  mbc->n_k_omega = (double *)ptr;
631  ptr += 3*sizeof(double)*nodes;
632  }
633 
634  if (MBC_F_ACCELS(mbc)) {
635  mbc->n_k_xpp = (double *)ptr;
636  ptr += 3*sizeof(double)*nodes;
637 
638  if (MBC_F_ROT(mbc) != MBC_ROT_NONE) {
639  mbc->n_k_omegap = (double *)ptr;
640  ptr += 3*sizeof(double)*nodes;
641  }
642  }
643 
644  if (MBC_F_LABELS(mbc)) {
645  mbc->n_d_labels = (uint32_t *)ptr;
646  ptr += (nodes + nodes%2)*sizeof(uint32_t);
647  }
648 
649  mbc->n_d_f = (double *)ptr;
650  ptr += 3*sizeof(double)*nodes;
651 
652  if (MBC_F_ROT(mbc) != MBC_ROT_NONE) {
653  mbc->n_d_m = (double *)ptr;
654  ptr += 3*sizeof(double)*nodes;
655  }
656  }
657 
658  return 0;
659 }
660 
661 /* negotiate nodal data
662  *
663  * mbc must be a pointer to a valid mbc_nodal_t structure
664  *
665  * at least reference node motion must be defined (MBC_F_REF_NODE(mbc)),
666  * or nodes must be > 0
667  *
668  * the socket must be initialized and connected
669  * sends a negotiation request to the master
670  */
671 int
673 {
674  int rc;
675  uint32_t *uint32_ptr;
676  char buf[sizeof(uint32_t) + sizeof(uint32_t)];
677 
678  if (!MBC_F_REF_NODE(mbc) && mbc->nodes == 0) {
679  fprintf(stderr, "need at least 1 node or reference node data\n");
680  return -1;
681  }
682 
683  if (!(mbc->mbc.sock_flags & MBC_SF_VALID)) {
684  fprintf(stderr, "socket is not valid\n");
685  return -1;
686  }
687 
688  mbc->mbc.cmd = ES_NEGOTIATION;
689  mbc_put_cmd((mbc_t *)mbc);
690 
691  uint32_ptr = (uint32_t *)&buf[0];
692  uint32_ptr[0] = MBC_F(mbc);
693  uint32_ptr[1] = mbc->nodes;
694 
695  rc = send(mbc->mbc.sock, (const void *)buf, sizeof(buf),
696  mbc->mbc.send_flags);
697  if (rc != sizeof(buf)) {
698  fprintf(stderr, "send negotiate request failed (%ld)\n", (long)rc);
699  return -1;
700  }
701 
702  if (mbc_get_cmd((mbc_t*)mbc)) {
703  return -1;
704  }
705 
706  if (mbc->mbc.verbose) {
707  fprintf(stdout, "cmd from peer: %lu (%s)\n",
708  (unsigned long)mbc->mbc.cmd, mbc_cmd2str(mbc->mbc.cmd));
709  }
710 
711  switch (mbc->mbc.cmd) {
712  case ES_ABORT:
713  fprintf(stdout, "got ABORT from peer\n");
714  return -1;
715 
716  case ES_OK:
717  break;
718 
719  default:
720  fprintf(stdout, "unexpected cmd=%lu from peer\n", (unsigned long)mbc->mbc.cmd);
721  return -1;
722  }
723 
724  return 0;
725 }
726 
727 int
729 {
730  int rc;
731  uint32_t *uint32_ptr;
732  char buf[sizeof(uint32_t) + sizeof(uint32_t)];
733  unsigned uNodal;
734  unsigned uRef;
735  unsigned uLabels;
736  unsigned uAccels;
737 
738  if (mbc_get_cmd((mbc_t*)mbc)) {
739  return -1;
740  }
741 
742  if (mbc->mbc.verbose) {
743  fprintf(stdout, "cmd from peer: %lu (%s)\n",
744  (unsigned long)mbc->mbc.cmd, mbc_cmd2str(mbc->mbc.cmd));
745  }
746 
747  switch (mbc->mbc.cmd) {
748  case ES_NEGOTIATION:
749  break;
750 
751  default:
752  fprintf(stdout, "unexpected cmd=%lu from peer\n", (unsigned long)mbc->mbc.cmd);
753  return -1;
754  }
755 
756  rc = recv(mbc->mbc.sock, (void *)buf, sizeof(buf), mbc->mbc.recv_flags);
757  if (rc != sizeof(buf)) {
758  fprintf(stderr, "recv negotiate request failed\n");
759  return -1;
760  }
761 
762  rc = 0;
763 
764  uint32_ptr = (uint32_t *)&buf[0];
765  uNodal = (uint32_ptr[0] & MBC_MODAL_NODAL_MASK);
766  uRef = (uint32_ptr[0] & MBC_REF_NODE);
767  uLabels = (uint32_ptr[0] & MBC_LABELS);
768  uAccels = (uint32_ptr[0] & MBC_ACCELS);
769 
770  if (uNodal != MBC_NODAL) {
771  rc++;
772  }
773 
774  if ((uRef && !MBC_F_REF_NODE(mbc)) || (!uRef && MBC_F_REF_NODE(mbc))) {
775  rc++;
776  }
777 
778  if (uLabels != MBC_F_LABELS(mbc)) {
779  rc++;
780  }
781 
782  if (uAccels != MBC_F_ACCELS(mbc)) {
783  rc++;
784  }
785 
786  if (uint32_ptr[1] != mbc->nodes) {
787  rc++;
788  }
789 
790  if (rc) {
791  mbc->mbc.cmd = ES_ABORT;
792 
793  } else {
794  mbc->mbc.cmd = ES_OK;
795  }
796 
797  mbc_put_cmd((mbc_t *)mbc);
798 
799  return 0;
800 }
801 
802 /* destroy nodal data
803  *
804  * does NOT free the mbc structure
805  */
806 int
808 {
809  if (mbc->n_ptr) {
810  free(mbc->n_ptr);
811  mbc->n_k_labels = NULL;
812  mbc->n_k_x = NULL;
813  mbc->n_k_theta = NULL;
814  mbc->n_k_r = NULL;
815  mbc->n_k_euler_123 = NULL;
816  mbc->n_k_xp = NULL;
817  mbc->n_k_omega = NULL;
818  mbc->n_k_xpp = NULL;
819  mbc->n_k_omegap = NULL;
820  mbc->n_d_labels = NULL;
821  mbc->n_d_f = NULL;
822  mbc->n_d_m = NULL;
823  mbc->n_ptr = NULL;
824  }
825 
826  return mbc_destroy((mbc_t *)mbc);
827 }
828 
829 
830 
831 /*
832  * modal stuff
833  */
834 
835 /* get modal motion from peer
836  *
837  * if MBC_F_REF_NODE(mbc), access reference node motion
838  * using macros MBC_X, MBC_R, MBC_V, MBC_W
839  * if mbc->modes > 0, access modal motion using macros MBC_Q, MBC_QP
840  */
841 int
843 {
844  if (mbc_get_cmd((mbc_t*)mbc)) {
845  return -1;
846  }
847 
848  if (mbc->mbc.verbose) {
849  fprintf(stdout, "cmd from peer: %lu (%s)\n",
850  (unsigned long)mbc->mbc.cmd, mbc_cmd2str(mbc->mbc.cmd));
851  }
852 
853  if (mbc->mbc.cmd == ES_ABORT) {
854  fprintf(stdout, "got ABORT from peer\n");
855  return -1;
856  }
857 
858  if (mbc->mbc.cmd != ES_GOTO_NEXT_STEP) {
859  if (MBC_F_REF_NODE(mbc)) {
860  ssize_t rc;
861 
862  rc = recv(mbc->mbc.sock, (void *)MBC_R_KINEMATICS(mbc),
864  if (rc == -1) {
865  int save_errno = errno;
866  const char *msg;
867 
868  msg = strerror(save_errno);
869  fprintf(stderr, "recv(%lu) reference node failed (%ld: %s)\n",
870  (unsigned long)MBC_R_KINEMATICS_SIZE(mbc),
871  (long)save_errno, msg);
872  return -1;
873 
874  } else if ((unsigned long)rc != MBC_R_KINEMATICS_SIZE(mbc)) {
875  fprintf(stderr, "recv(%lu) reference node failed (%ld)\n",
876  (unsigned long)MBC_R_KINEMATICS_SIZE(mbc), (long)rc);
877  return -1;
878  }
879  }
880 
881  if (mbc->modes > 0) {
882  ssize_t rc;
883 
884  rc = recv(mbc->mbc.sock, (void *)MBC_M_KINEMATICS(mbc),
886  if (rc == -1) {
887  int save_errno = errno;
888  const char *msg;
889 
890  msg = strerror(save_errno);
891  fprintf(stderr, "recv(%lu) q, qP failed (%ld: %s)\n",
892  (unsigned long)MBC_M_KINEMATICS_SIZE(mbc),
893  (long)save_errno, msg);
894  return -1;
895 
896  } else if ((unsigned long)rc != MBC_M_KINEMATICS_SIZE(mbc)) {
897  fprintf(stderr, "recv(%lu) q, qP failed (%ld)\n",
898  (unsigned long)MBC_M_KINEMATICS_SIZE(mbc), (long)rc);
899  return -1;
900  }
901  }
902  }
903 
904  return 0;
905 }
906 
907 /* put forces to peer
908  *
909  * if MBC_F_REF_NODE(mbc), force and moment must be set in storage pointed to
910  * by macros MBC_F, MBC_M
911  * if mbc->modes > 0, modal forces must be set in storage pointed to
912  * by macro MBC_P
913  */
914 int
915 mbc_modal_put_forces(mbc_modal_t *mbc, int last)
916 {
917  if (last) {
918  if (mbc->mbc.data_and_next) {
920 
921  } else {
922  mbc->mbc.cmd = ES_GOTO_NEXT_STEP;
923  }
924 
925  } else {
926  mbc->mbc.cmd = ES_REGULAR_DATA;
927  }
928 
929  if (mbc_put_cmd((mbc_t *)mbc)) {
930  return -1;
931  }
932 
933  if (mbc->mbc.cmd != ES_GOTO_NEXT_STEP) {
934  /* reference node */
935  if (MBC_F_REF_NODE(mbc)) {
936  ssize_t rc;
937 
938  rc = send(mbc->mbc.sock, (const void *)MBC_R_DYNAMICS(mbc),
939  MBC_R_DYNAMICS_SIZE(mbc), mbc->mbc.send_flags);
940  if (rc == -1) {
941  int save_errno = errno;
942  const char *msg;
943 
944  msg = strerror(save_errno);
945  fprintf(stderr, "send(%lu) reference node failed (%ld: %s)\n",
946  (unsigned long)MBC_R_DYNAMICS_SIZE(mbc),
947  (long)save_errno, msg);
948  return -1;
949 
950  } else if ((unsigned long)rc != MBC_R_DYNAMICS_SIZE(mbc)) {
951  fprintf(stderr, "send(%lu) reference node failed (%ld)\n",
952  (unsigned long)MBC_R_DYNAMICS_SIZE(mbc), (long)rc);
953  return -1;
954  }
955  }
956 
957  /* modal */
958  if (mbc->modes > 0) {
959  ssize_t rc;
960 
961  rc = send(mbc->mbc.sock, (const void *)MBC_M_DYNAMICS(mbc),
962  MBC_M_DYNAMICS_SIZE(mbc), mbc->mbc.send_flags);
963  if (rc == -1) {
964  int save_errno = errno;
965  const char *msg;
966 
967  msg = strerror(save_errno);
968  fprintf(stderr, "send(%lu) modes failed (%ld: %s)\n",
969  (unsigned long)MBC_M_DYNAMICS_SIZE(mbc),
970  (long)save_errno, msg);
971  return -1;
972 
973  } else if ((unsigned long)rc != MBC_M_DYNAMICS_SIZE(mbc)) {
974  fprintf(stderr, "send(%lu) modes failed (%ld)\n",
975  (unsigned long)MBC_M_DYNAMICS_SIZE(mbc), (long)rc);
976  return -1;
977  }
978  }
979  }
980 
981  return 0;
982 }
983 
984 /* initialize modal data
985  *
986  * mbc must be a pointer to a valid mbc_modal_t structure
987  *
988  * at least reference node motion must be defined (MBC_F_REF_NODE(mbc)),
989  * or modes must be > 0
990  *
991  * if modes > 0, mallocs memory that needs to be freed calling
992  * mbc_modal_destroy()
993  */
994 int
995 mbc_modal_init(mbc_modal_t *mbc, int refnode, unsigned modes)
996 {
997  unsigned rot = MBC_ROT_MAT;
998 
999  MBC_F_SET(mbc, MBC_MODAL);
1000  mbc->modes = modes;
1001 
1002  if (refnode) {
1003  MBC_F_SET_REF_NODE(mbc);
1004  }
1005 
1006  if (!MBC_F_REF_NODE(mbc) && modes == 0) {
1007  fprintf(stderr, "need at least 1 mode or reference node data\n");
1008  return -1;
1009  }
1010 
1011  /* FIXME: rotation configurable? */
1012  if (mbc_rigid_init(&mbc->mbcr, refnode, 0, &rot, 0)) {
1013  return -1;
1014  }
1015  MBC_F_SET(mbc, (rot & MBC_REF_NODE_ROT_MASK));
1016 
1017  if (mbc->modes > 0) {
1018  mbc->m = (double *)malloc(MBC_M_SIZE(mbc));
1019  }
1020 
1021  return 0;
1022 }
1023 
1024 /* negotiate modal data
1025  *
1026  * mbc must be a pointer to a valid mbc_modal_t structure
1027  *
1028  * at least reference node motion must be defined (MBC_F_REF_NODE(mbc)),
1029  * or modes must be > 0
1030  *
1031  * the socket must be initialized and connected
1032  * sends a negotiation request to the master
1033  */
1034 int
1036 {
1037  int rc;
1038  uint32_t *uint32_ptr;
1039  char buf[sizeof(uint32_t) + sizeof(uint32_t)];
1040 
1041  if (!MBC_F_REF_NODE(mbc) && mbc->modes == 0) {
1042  fprintf(stderr, "need at least 1 mode or reference node data\n");
1043  return -1;
1044  }
1045 
1046  if (!(mbc->mbc.sock_flags & MBC_SF_VALID)) {
1047  fprintf(stderr, "socket is not valid\n");
1048  return -1;
1049  }
1050 
1051  mbc->mbc.cmd = ES_NEGOTIATION;
1052  mbc_put_cmd((mbc_t *)mbc);
1053 
1054  uint32_ptr = (uint32_t *)&buf[0];
1055  uint32_ptr[0] = (uint32_t)MBC_F(mbc);
1056  uint32_ptr[1] = mbc->modes;
1057 
1058  rc = send(mbc->mbc.sock, (const void *)buf, sizeof(buf),
1059  mbc->mbc.send_flags);
1060  if (rc != sizeof(buf)) {
1061  fprintf(stderr, "send negotiate request failed (%ld)\n", (long)rc);
1062  return -1;
1063  }
1064 
1065  if (mbc_get_cmd((mbc_t*)mbc)) {
1066  return -1;
1067  }
1068 
1069  if (mbc->mbc.verbose) {
1070  fprintf(stdout, "cmd from peer: %lu (%s)\n",
1071  (unsigned long)mbc->mbc.cmd, mbc_cmd2str(mbc->mbc.cmd));
1072  }
1073 
1074  switch (mbc->mbc.cmd) {
1075  case ES_ABORT:
1076  fprintf(stdout, "got ABORT from peer\n");
1077  return -1;
1078 
1079  case ES_OK:
1080  break;
1081 
1082  default:
1083  fprintf(stdout, "unexpected cmd=%lu from peer\n", (unsigned long)mbc->mbc.cmd);
1084  return -1;
1085  }
1086 
1087  return 0;
1088 }
1089 
1090 int
1092 {
1093  int rc;
1094  uint32_t *uint32_ptr;
1095  char buf[sizeof(uint32_t) + sizeof(uint32_t)];
1096  unsigned uModal;
1097  unsigned uRef;
1098 
1099  if (mbc_get_cmd((mbc_t*)mbc)) {
1100  return -1;
1101  }
1102 
1103  if (mbc->mbc.verbose) {
1104  fprintf(stdout, "cmd from peer: %lu (%s)\n",
1105  (unsigned long)mbc->mbc.cmd, mbc_cmd2str(mbc->mbc.cmd));
1106  }
1107 
1108  switch (mbc->mbc.cmd) {
1109  case ES_NEGOTIATION:
1110  break;
1111 
1112  default:
1113  fprintf(stdout, "unexpected cmd=%lu from peer\n", (unsigned long)mbc->mbc.cmd);
1114  return -1;
1115  }
1116 
1117  rc = recv(mbc->mbc.sock, (void *)buf, sizeof(buf), mbc->mbc.recv_flags);
1118  if (rc != sizeof(buf)) {
1119  fprintf(stderr, "recv negotiate request failed\n");
1120  return -1;
1121  }
1122 
1123  rc = 0;
1124 
1125  uint32_ptr = (uint32_t *)&buf[0];
1126  uModal = uint32_ptr[0] & MBC_MODAL_NODAL_MASK;
1127  uRef = uint32_ptr[0] & MBC_REF_NODE;
1128 
1129  if (uModal != MBC_MODAL) {
1130  rc++;
1131  }
1132 
1133  if ((uRef && !MBC_F_REF_NODE(mbc)) || (!uRef && MBC_F_REF_NODE(mbc))) {
1134  rc++;
1135  }
1136 
1137  if (uint32_ptr[1] != mbc->modes) {
1138  rc++;
1139  }
1140 
1141  if (rc) {
1142  mbc->mbc.cmd = ES_ABORT;
1143 
1144  } else {
1145  mbc->mbc.cmd = ES_OK;
1146  }
1147 
1148  mbc_put_cmd((mbc_t *)mbc);
1149 
1150  return 0;
1151 }
1152 
1153 /* destroy modal data
1154  *
1155  * does NOT free the mbc structure
1156  */
1157 int
1159 {
1160  if (mbc->m) {
1161  free(mbc->m);
1162  mbc->m = NULL;
1163  }
1164 
1165  return mbc_destroy((mbc_t *)mbc);
1166 }
1167 
1168 #endif /* USE_SOCKET */
#define MBC_F_LABELS(mbc)
Definition: mbc.h:241
int mbc_nodal_negotiate_response(mbc_nodal_t *mbc)
Unused.
mbc_t mbc
Definition: mbc.h:335
Definition: mbc.h:58
#define MBC_M_DYNAMICS_SIZE(mbc)
Definition: mbc.h:522
char * n_ptr
Definition: mbc.h:342
int mbc_nodal_get_motion(mbc_nodal_t *mbc)
Get nodal motion from peer.
double * n_k_r
Definition: mbc.h:348
static int timeout
#define MBC_M_KINEMATICS_SIZE(mbc)
Definition: mbc.h:521
#define MBC_N_DYNAMICS(mbc)
Definition: mbc.h:377
nodal stuff (partially opaque).
Definition: mbc.h:509
#define MBC_F_SET_ROT_MAT(mbc)
Definition: mbc.h:256
double * n_d_m
Definition: mbc.h:360
int32_t r_d_label
Definition: mbc.h:278
int32_t r_d_m
Definition: mbc.h:280
mbc_rigid_t mbcr
Definition: mbc.h:336
double * n_k_xpp
Definition: mbc.h:353
int mbc_modal_destroy(mbc_modal_t *mbc)
Destroy modal data.
int32_t r_k_r
Definition: mbc.h:271
#define MBC_F_SET_REF_NODE(mbc)
Definition: mbc.h:252
unsigned sock_flags
Definition: mbc.h:108
int mbc_nodal_init(mbc_nodal_t *mbc, unsigned refnode, unsigned nodes, unsigned labels, unsigned rot, unsigned accels)
Initialize nodal data.
int32_t r_k_euler_123
Definition: mbc.h:272
Definition: mbc.h:65
int32_t r_d_f
Definition: mbc.h:279
mbc_rigid_t mbcr
Definition: mbc.h:511
int mbc_modal_negotiate_response(mbc_modal_t *mbc)
Unused.
int verbose
Definition: mbc.h:128
#define MBC_M_DYNAMICS(mbc)
Definition: mbc.h:520
int32_t r_k_xpp
Definition: mbc.h:275
double * n_k_euler_123
Definition: mbc.h:349
#define MBC_N_DYNAMICS_SIZE(mbc)
Definition: mbc.h:375
#define MBC_F_SET_ROT_THETA(mbc)
Definition: mbc.h:255
double * n_k_omegap
Definition: mbc.h:354
uint32_t * n_k_labels
Definition: mbc.h:344
int32_t r_k_label
Definition: mbc.h:268
static unsigned rot
#define MBC_R_KINEMATICS_SIZE(mbc)
Definition: mbc.h:294
#define MBC_F_ACCELS(mbc)
Definition: mbc.h:242
Definition: mbc.h:71
int mbdyn_make_inet_socket(struct sockaddr_in *name, const char *hostname, unsigned short int port, int dobind, int *perror)
double * n_k_omega
Definition: mbc.h:351
char data_and_next
Definition: mbc.h:125
#define MBC_F_SET_ACCELS(mbc)
Definition: mbc.h:254
#define MBC_N_KINEMATICS_SIZE(mbc)
Definition: mbc.h:374
int32_t r_k_omega
Definition: mbc.h:274
int send_flags
Definition: mbc.h:114
int sock
Definition: mbc.h:105
static int labels
uint32_t * n_d_labels
Definition: mbc.h:358
int mbc_modal_negotiate_request(mbc_modal_t *mbc)
Negotiate modal data.
Definition: mbc.h:66
uint32_t d_size
Definition: mbc.h:277
#define MBC_F_SET(mbc, f)
Definition: mbc.h:237
#define MBC_U_REF_NODE_ROT_2_ROT(u)
Definition: mbc.h:247
int32_t r_k_xp
Definition: mbc.h:273
int32_t r_k_x
Definition: mbc.h:269
#define MBC_R_DYNAMICS(mbc)
Definition: mbc.h:298
int recv_flags
Definition: mbc.h:111
uint32_t modes
Definition: mbc.h:514
const char * host
Definition: autopilot.c:142
int mbc_modal_init(mbc_modal_t *mbc, int refnode, unsigned modes)
Initialize modal data.
#define MBC_R_DYNAMICS_SIZE(mbc)
Definition: mbc.h:295
#define MBC_F_ROT(mbc)
Definition: mbc.h:243
int mbc_put_cmd(mbc_t *mbc)
Opaque.
Connection data structure (partially opaque)
Definition: mbc.h:103
int timeout
Definition: mbc.h:137
#define MBC_N_SIZE(mbc)
Definition: mbc.h:378
Definition: mbc.h:55
uint32_t d_size
Definition: mbc.h:356
int32_t r_k_omegap
Definition: mbc.h:276
#define MBC_M_SIZE(mbc)
Definition: mbc.h:523
double * n_d_f
Definition: mbc.h:359
#define MSG_NOSIGNAL
Definition: sock.h:69
uint32_t k_size
Definition: mbc.h:340
int mbc_nodal_put_forces(mbc_nodal_t *mbc, int last)
Put forces to peer.
int mbc_get_cmd(mbc_t *mbc)
Opaque.
static int nodes
static mbc_nodal_t * mbc
int mbdyn_make_named_socket(struct sockaddr_un *name, const char *path, int dobind, int *perror)
#define MBC_F(mbc)
Definition: mbc.h:235
#define MBC_R_KINEMATICS(mbc)
Definition: mbc.h:297
#define MBC_F_REF_NODE(mbc)
Definition: mbc.h:240
double * n_k_xp
Definition: mbc.h:350
int mbc_unix_init(mbc_t *mbc, const char *path)
Initialize communication using "unix" socket.
int mbc_check_cmd(mbc_t *mbc)
Opaque.
int mbc_nodal_negotiate_request(mbc_nodal_t *mbc)
Negotiate nodal data.
struct mbrtai_msg_t msg
#define MBC_U_ROT_2_REF_NODE_ROT(u)
Definition: mbc.h:248
double * m
Definition: mbc.h:515
int mbc_inet_init(mbc_t *mbc, const char *host, short unsigned port)
Initialize communication using "inet" socket.
uint32_t nodes
Definition: mbc.h:339
#define MBC_F_SET_LABELS(mbc)
Definition: mbc.h:253
int mbc_modal_get_motion(mbc_modal_t *mbc)
Get modal motion from peer.
double * n_k_x
Definition: mbc.h:345
Nodal stuff (partially opaque).
Definition: mbc.h:334
int32_t r_k_theta
Definition: mbc.h:270
Reference node (AKA "rigid") stuff (partially opaque).
Definition: mbc.h:233
unsigned short int port
Definition: autopilot.c:143
static doublereal buf[BUFSIZE]
Definition: discctrl.cc:333
#define MBC_F_SET_ROT_EULER_123(mbc)
Definition: mbc.h:257
uint32_t k_size
Definition: mbc.h:267
#define MBC_N_KINEMATICS(mbc)
Definition: mbc.h:376
Definition: mbc.h:73
uint8_t cmd
Definition: mbc.h:117
int mbc_nodal_destroy(mbc_nodal_t *mbc)
Destroy nodal data.
double * n_k_theta
Definition: mbc.h:347
mbc_t mbc
Definition: mbc.h:510
static int refnode
const char * path
Definition: autopilot.c:141
int mbc_modal_put_forces(mbc_modal_t *mbc, int last)
Put forces to peer.
#define MBC_M_KINEMATICS(mbc)
Definition: mbc.h:519