Exemplo n.º 1
0
static void read_sample_from_ring(void *arg, long period)
{
    ringbuffer_t *rb = (ringbuffer_t *) arg;
    hal_delayline_t *hd = rb->scratchpad;
    const sample_t *s;
    ringsize_t size;

    // detect rising edge on abort pin, and flush rb if so
    if (*(hd->abort) && (*(hd->abort) ^ hd->last_abort)) {
	int dropped = record_flush_reader(rb);
	rtapi_print_msg(RTAPI_MSG_INFO,
			"%s: %s aborted - dropped %d samples\n",
			cname, hd->name, dropped);
    }

    // if pin_delay < 0 then use 0, otherwise
    // use delay pin value

    // if time has decreased, then take action by setting the output_ts to the
    // result of input_ts - delay. Otherwise do nothing. This will result in
    // loss of some records. Make sure you're in a safe situation!
    // The situation of increasing the time will be acted upon in
    // write_sample_to_ring()
    if ( *(hd->pin_delay) < (hal_u32_t)(hd->input_ts - hd->output_ts)) {
	if ( *(hd->pin_delay) < 0) {
	    hd->delay = 0;
	}
	else {
	    hd->delay = *(hd->pin_delay);
	}
	// set the new timestamp
	hd->input_ts =  hd->input_ts - (__u64)(hd->delay);
    }

    // peek at the head of the queue
    while (record_read(rb, (const void **)&s, &size) == 0) {

	// do nothing if timestamp is in the future
	if (s->timestamp > hd->output_ts)
	    goto NOTYET;

	if (s->timestamp == hd->output_ts)
	    // the time is right
	    apply(s, hd);
	else
	    // skip old samples and bump an error counter
	    *(hd->too_old) += 1;

	// sanity: if (size != hd->sample_size).. terribly wrong.
	record_shift(rb); // consume record
    }
 NOTYET:
    hd->output_ts++; // always bump the timestamp
    hd->last_abort = *(hd->abort);
}
Exemplo n.º 2
0
// thread function, per-instance
// interpolates all joints of this instance
static int update(void *arg, const hal_funct_args_t *fa)
{
    struct inst_data *ip = (struct inst_data *) arg;
    double period = ((double) fa_period(fa)) * 1e-9;

    int i;
    if (segment_completed(ip, period)) {
		// check for a new JointTrajectoryPoint
		void *data;
		ringsize_t size;
		if (record_read(&ip->traj, (const void**)&data, &size) == 0) {

		    // protobuf-decode it
		    pb_istream_t stream = pb_istream_from_buffer(data, size);
		    pb_JointTrajectoryPoint rx =  pb_JointTrajectoryPoint_init_zero;
		    if (!pb_decode(&stream, pb_JointTrajectoryPoint_fields, &rx)) {
				rtapi_print_msg(RTAPI_MSG_ERR, "%s: pb_decode(JointTrajectoryPoint) failed: '%s'",
					compname, PB_GET_ERROR(&stream));
		    } else {
			// decode ok - start a new segment
				double duration = *(ip->duration) = rx.time_from_start - ip->time_from_start;
	            // the very first point in the ringbuffer is not a segment.
	            // therefore we need to "jump" to these initial settings for the
	            // interpolator to calculate the correct path.
	            // for example, a path can start at position, velocity and acceleration
	            // who are non-zero. In a typical ROS message the first point has a
	            // duration of "0.0"
	            if (duration == 0.0) {
	                // set the start positions
	                // or try out to drop this point later on
	                for (i = 0; i < ip->count; i++) {
	                    struct joint *jp = &ip->joints[i];
						*(jp->traj_busy) = true;
	                    *(jp->curr_pos) = *(jp->end_pos) = rx.positions[i];
	                    *(jp->curr_vel) = *(jp->end_vel) = rx.velocities[i];
	                    *(jp->curr_acc) = *(jp->end_acc) = rx.accelerations[i];
	                    jp->coeff[0] = *(jp->end_pos);
	                    jp->coeff[1] = 0.0;
	                    jp->coeff[2] = 0.0;
	                    jp->coeff[3] = 0.0;
	                    jp->coeff[4] = 0.0;
	                    jp->coeff[5] = 0.0;
	                }
	                // so when we have read the first point, we need to discard everythin
	                // else and make sure we will read the second point, as to complete the
	                // first segment
	            } else {
				    generatePowers(*(ip->degree), duration, ip->powers);
	                ip->time_from_start =  rx.time_from_start;
	                *(ip->progress) = 0.0;
	                for (i = 0; i < rx.positions_count; i++) {
			            struct joint *jp = &ip->joints[i];
						*(jp->traj_busy) = true;
			            double pos2 = *(jp->end_pos) = rx.positions[i];
			    		double vel2 = *(jp->end_vel) = rx.velocities[i];
			    		double acc2 = *(jp->end_acc) = rx.accelerations[i];
	                    double pos1 = *(jp->curr_pos);
	                    double vel1 = *(jp->curr_vel);
	                    double acc1 = *(jp->curr_acc);
					    switch (*(ip->degree)) {
					    case 1:
							jp->coeff[0] = pos1;
							jp->coeff[1] = (pos2 - pos1) / duration;
							jp->coeff[2] = 0.0;
							jp->coeff[3] = 0.0;
							jp->coeff[4] = 0.0;
							jp->coeff[5] = 0.0;
						break;
					    case 3:
							jp->coeff[0] = pos1;
							jp->coeff[1] = vel1;
							jp->coeff[2] = (-3.0*pos1 + 3.0*pos2 - 2.0*vel1*ip->powers[1] - vel2*ip->powers[1]) / ip->powers[2];
							jp->coeff[3] = (2.0*pos1 - 2.0*pos2 + vel1*ip->powers[1] + vel2*ip->powers[1]) / ip->powers[3];
							jp->coeff[4] = 0.0;
							jp->coeff[5] = 0.0;
						break;
					    case 5:
							jp->coeff[0] = pos1;
							jp->coeff[1] = vel1;
							jp->coeff[2] = 0.5 * acc1;
							jp->coeff[3] =  (-20.0*pos1 + 20.0*pos2 - 3.0*acc1*ip->powers[2] + acc2*ip->powers[2] -
									 12.0*vel1*ip->powers[1] - 8.0*vel2*ip->powers[1]) / (2.0*ip->powers[3]);
							jp->coeff[4] =  (30.0*pos1 - 30.0*pos2 + 3.0*acc1*ip->powers[2] - 2.0*acc2*ip->powers[2] +
									 16.0*vel1*ip->powers[1] + 14.0*vel2*ip->powers[1]) / (2.0*ip->powers[4]);
							jp->coeff[5] =  (-12.0*pos1 + 12.0*pos2 - acc1*ip->powers[2] + acc2*ip->powers[2] -
									 6.0*vel1*ip->powers[1] - 6.0*vel2*ip->powers[1]) / (2.0*ip->powers[5]);
						break;
					    }
					}
	        	}
		    }
		    record_shift(&ip->traj);   // consume record
		} else {
	        // segment completed and no new point in ringbuffer
	        for (i = 0; i < ip->count; i++) {
	            struct joint *jp = &ip->joints[i];
				*(jp->traj_busy) = false;
	            jp->coeff[0] = *(jp->end_pos);
	            jp->coeff[1] = 0.0;
	            jp->coeff[2] = 0.0;
	            jp->coeff[3] = 0.0;
	            jp->coeff[4] = 0.0;
	            jp->coeff[5] = 0.0;
	        }
	    }
    }

    *(ip->progress) += period;

    generatePowers(*(ip->degree), *(ip->progress), ip->pnow);
    for (i = 0; i < ip->count; i++) {
		struct joint *jp = &ip->joints[i];
		interpolate_joint(ip, jp, *(ip->progress), 0);
    }
    return 0;
}
Exemplo n.º 3
0
static int message_thread()
{
    rtapi_msgheader_t *msg;
    size_t msg_size;
    size_t payload_length;
    int retval;
    char *cp;
    int sigfd;
    sigset_t sigset;

    // sigset of all the signals that we're interested in
    retval = sigemptyset(&sigset);        assert(retval == 0);
    retval = sigaddset(&sigset, SIGINT);  assert(retval == 0);
    retval = sigaddset(&sigset, SIGKILL); assert(retval == 0);
    retval = sigaddset(&sigset, SIGTERM); assert(retval == 0);
    retval = sigaddset(&sigset, SIGSEGV); assert(retval == 0);
    retval = sigaddset(&sigset, SIGFPE);  assert(retval == 0);

    // block the signals in order for signalfd to receive them
    retval = sigprocmask(SIG_BLOCK, &sigset, NULL); assert(retval == 0);

    sigfd = signalfd(-1, &sigset, 0);
    assert(sigfd != -1);

    struct pollfd pfd[1];
    int ret;

    pfd[0].fd = sigfd;
    pfd[0].events = POLLIN | POLLERR | POLLHUP;

    global_data->magic = GLOBAL_READY;

    do {
	if (global_data->rtapi_app_pid == 0) {
	    syslog_async(LOG_ERR,
		   "msgd:%d: rtapi_app exit detected - shutting down",
		   rtapi_instance);
	    msgd_exit++;
	}
	while ((retval = record_read(&rtapi_msg_buffer,
					   (const void **) &msg, &msg_size)) == 0) {
	    payload_length = msg_size - sizeof(rtapi_msgheader_t);

	    switch (msg->encoding) {
	    case MSG_ASCII:
		// strip trailing newlines
		while ((cp = strrchr(msg->buf,'\n')))
		    *cp = '\0';
		syslog_async(rtapi2syslog(msg->level), "%s:%d:%s %.*s",
		       msg->tag, msg->pid, origins[msg->origin],
		       (int) payload_length, msg->buf);
		break;
	    case MSG_STASHF:
		break;
	    case MSG_PROTOBUF:
		break;
	    default: ;
		// whine
	    }
	    record_shift(&rtapi_msg_buffer);
	    msg_poll = msg_poll_min;
	}

	ret = poll(pfd, 1, msg_poll);
	if (ret < 0) {
	    syslog_async(LOG_ERR, "msgd:%d: poll(): %s - shutting down\n",
		   rtapi_instance, strerror(errno));
	    msgd_exit++;
	} else if (pfd[0].revents & POLLIN) { // signal received
	    struct signalfd_siginfo info;
	    size_t bytes = read(sigfd, &info, sizeof(info));
	    assert(bytes == sizeof(info));
	    signal_handler(info.ssi_signo);
	}
	
	msg_poll += msg_poll_inc;
	if (msg_poll > msg_poll_max)
	    msg_poll = msg_poll_max;

    } while (!msgd_exit);

    return 0;
}