-
Notifications
You must be signed in to change notification settings - Fork 3
/
joint_stream.comp
228 lines (192 loc) · 6.87 KB
/
joint_stream.comp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
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
216
217
218
219
220
221
222
223
224
225
226
227
/******************************************************************************
*
* Copyright (C) 2015 Charles Steinkuehler (charles AT steinkuehler DOT net)
*
******************************************************************************
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
* THE AUTHORS OF THIS PROGRAM ACCEPT ABSOLUTELY NO LIABILITY FOR
* ANY HARM OR LOSS RESULTING FROM ITS USE. IT IS _EXTREMELY_ UNWISE
* TO RELY ON SOFTWARE ALONE FOR SAFETY. Any machinery capable of
* harming persons must have provisions for completely removing power
* from all motors, etc, before persons enter any danger area. All
* machinery must be designed to comply with local and national safety
* codes, and the authors of this software can not, and do not, take
* any responsibility for such compliance.
*
* This code was written as part of the Machinekit project. For more
* information, go to www.machinekit.io
*
******************************************************************************/
component joint_stream "Machinekit HAL component for streaming joint positions from ROS";
pin out float joint.##.pos-cmd [6] "Per-joint commanded position";
pin out u32 underrun "number of failed read attempts";
pin out u32 received "number of successful read attempts";
pin out u32 tooslow "number of times the reader couldnt keep up with the writer";
pin out u32 avail "number of bytes (valid data) currently available in the buffer";
pin out s32 time_s;
pin out s32 time_ns;
pin out s32 time_l;
pin out s32 time_c;
pin out s32 time_n;
function _;
option singleton yes;
option rtapi_app no;
license "GPLv2 or later";
description """
Streams joint positions from a ring-buffer to HAL pins
.LP
The `personality' value is the number of joints to control
.LP
ToDo more detail goes here
""";
;;
#define MAXSIZE 1024
#include "hal_priv.h"
#include "hal_ring.h" /* ringbuffer declarations */
typedef union {
hal_s32_t s[2];
hal_u32_t u[2];
hal_float_t f[1];
} hal_data_univ;
typedef struct {
hal_s32_t time;
hal_float_t joint[6];
} JointTrajPoint;
static char *ring = "ring_0";
RTAPI_MP_STRING(ring, "name of ring to attach");
static ringbuffer_t rb;
static char *name = "joint_stream";
static JointTrajPoint last_pt, curr_pt, next_pt;
FUNCTION(_) {
ringvec_t vec[2];
size_t size;
const void *data;
const double *dataf;
hal_data_univ *buf;
hal_s32_t sec, nsec, ustime;
hal_float_t alpha;
int i;
// If we're caught up...
if (curr_pt.time >= next_pt.time) {
// ...check for a new point
if (record_read(&rb, (const void**)&buf, &size) == 0) {
// Copy data to output
sec = buf[0].s[0];
nsec = buf[0].s[1];
for (i=0; i<6; i++) {
next_pt.joint[i] = buf[i+1].f[0];
rtapi_print_msg(RTAPI_MSG_INFO,"got %i:%g", i, buf[i+1].f[0]);
}
// consume record
record_shift(&rb);
received++;
// Process what we got
avail = size;
time_s = sec;
time_ns = nsec;
// Use 32-bit uS time values for simplicity, covers up to apx. +/- 35 min.
next_pt.time = sec * 1000000 + (nsec / 1000);
// If time_from_start is less than our current time, we have a new
// trajectory, so reset the times on the previous points, otherwise
// it's just the next point in the path
if (next_pt.time < curr_pt.time) {
curr_pt.time = 0;
last_pt.time = 0;
}
}
}
// If we're working towards a goal, keep going
if (curr_pt.time < next_pt.time) {
// Move forward to next time period
curr_pt.time += (period / 1000);
if (curr_pt.time >= next_pt.time) {
// We're done, stop at the target point
last_pt = next_pt;
curr_pt = next_pt;
} else {
// Otherwise, calculate the next interpolated point
//interpolate(&last_pt, &curr_pt, &next_pt);
if (next_pt.time > last_pt.time) {
alpha = (hal_float_t)(curr_pt.time - last_pt.time) / (hal_float_t)(next_pt.time - last_pt.time);
for (i=0; i<6; i++) {
curr_pt.joint[i] = last_pt.joint[i] + alpha * (next_pt.joint[i] - last_pt.joint[i]);
}
} else {
alpha = 1.0;
curr_pt = next_pt;
}
}
// Update the outputs
for (i=0; i<6; i++) {
joint_pos_cmd(i) = curr_pt.joint[i];
}
} else {
// The ring buffer is empty and we've finished our current point
underrun++;
}
// Debugging, possibly useful to trigger HALscope
time_l = last_pt.time;
time_c = curr_pt.time;
time_n = next_pt.time;
return;
}
int rtapi_app_main(void)
{
int retval;
comp_id = hal_init(name);
if (comp_id < 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"%s: ERROR: hal_init() failed: %d\n",
name, comp_id);
return -1;
}
if ((retval = hal_ring_attach(ring, &rb,NULL))) {
rtapi_print_msg(RTAPI_MSG_ERR,
"%s: ERROR: hal_ring_attach(%s) failed: %d\n",
name, ring, retval);
return -1;
}
rtapi_print_msg(RTAPI_MSG_INFO,
"%s: attached ring '%s' size=%zu type=%d"
" rmutex=%d wmutex=%d reader=%d writer=%d scratchpad=%zu\n",
name, ring, rb.header->size,
rb.header->type,
ring_use_rmutex(&rb), ring_use_wmutex(&rb),
rb.header->reader, rb.header->writer,
ring_scratchpad_size(&rb));
rb.header->reader = comp_id;
rb.header->reader_instance = rtapi_instance;
if ((retval = export(name, 0))) {
rtapi_print_msg(RTAPI_MSG_ERR,
"%s: ERROR: export(%s) failed: %d\n",
name, name, retval);
return -1;
}
hal_ready(comp_id);
return 0;
}
void rtapi_app_exit(void)
{
int retval;
rb.header->reader = 0;
if ((retval = hal_ring_detach(ring, &rb)) < 0)
rtapi_print_msg(RTAPI_MSG_ERR,
"%s: ERROR: hal_ring_detach(%s) failed: %d\n",
name, ring, retval);
hal_exit(comp_id);
}