int control_loop_run( void )
{
    int first_time = 1;

    next_period = get_utime( ) + us_period;

    while( running )
    {
        if( send_motor_signals( ) )
        {
            break;
        }

	if( javiator_port_get_data( &javiator_data ) )
        {
            fprintf( stderr, "ERROR: connection to JAviator broken\n" );
            heli_state = HELI_STATE_SHUTDOWN;
            perform_shut_down( );
            break;
	}

        if( check_terminal_connection( ) )
        {
            heli_state = HELI_STATE_SHUTDOWN;

            if( first_time )
            {
                fprintf( stderr, "ERROR: connection to Terminal broken\n" );
                first_time = 0;
            }
        }
        else
        {
            first_time = 1;
        }

        get_command_data( );
        get_control_params( );
        prepare_sensor_data( );
 
        switch( heli_state )
        {
            case HELI_STATE_GROUND:
                perform_ground_actions( );
                break;

            case HELI_STATE_FLYING:
                compute_motor_signals( );
                break;

            case HELI_STATE_SHUTDOWN:
                perform_shut_down( );
                break;

            default:
                fprintf( stderr, "ERROR: invalid altitude mode %d\n", heli_state );
        }

        send_report_to_terminal( );
        wait_for_next_period( );
    }

    iir_lp_filter_destroy( &iir_acc_x );
    iir_lp_filter_destroy( &iir_acc_y );
    iir_lp_filter_destroy( &iir_acc_z );
    iir_lp_filter_destroy( &iir_cmd_roll );
    iir_lp_filter_destroy( &iir_cmd_pitch );
    iir_lp_filter_destroy( &iir_cmd_yaw );
    iir_lp_filter_destroy( &iir_cmd_z );
    median_filter_destroy( &med_bat_level );
    position_ekf_destroy ( &ekf_pos_z );
    controller_destroy   ( &ctrl_roll );
    controller_destroy   ( &ctrl_pitch );
    controller_destroy   ( &ctrl_yaw );
    controller_destroy   ( &ctrl_z );

    return( 0 );
}
Пример #2
0
/*
 * main() - loop forever, reading the hdaps values and
 *          parking/unparking as necessary
 */
int main (int argc, char** argv)
{
	struct utsname sysinfo;
	struct list *p = NULL;
	int c, park_now, protect_factor;
	int x = 0, y = 0, z = 0;
	int fd, i, ret, threshold = 15, adaptive = 0,
	pidfile = 0, parked = 0, forceadd = 0;
	double unow = 0, parked_utime = 0;

	struct option longopts[] =
	{
		{"device", required_argument, NULL, 'd'},
		{"sensitivity", required_argument, NULL, 's'},
		{"adaptive", no_argument, NULL, 'a'},
		{"verbose", no_argument, NULL, 'v'},
		{"background", no_argument, NULL, 'b'},
		{"pidfile", optional_argument, NULL, 'p'},
		{"dry-run", no_argument, NULL, 't'},
		{"poll-sysfs", no_argument, NULL, 'y'},
		{"hardware-logic", no_argument, NULL, 'H'},
		{"software-logic", no_argument, NULL, 'S'},
		{"version", no_argument, NULL, 'V'},
		{"help", no_argument, NULL, 'h'},
		{"no-leds", no_argument, NULL, 'L'},
		{"syslog", no_argument, NULL, 'l'},
		{"force", no_argument, NULL, 'f'},
		{"force-rotational", no_argument, NULL, 'r'},
		{NULL, 0, NULL, 0}
	};

	if (uname(&sysinfo) < 0 || strcmp("2.6.27", sysinfo.release) <= 0) {
		protect_factor = 1000;
		kernel_interface = UNLOAD_HEADS;
	}
	else {
		protect_factor = 1;
		kernel_interface = PROTECT;
	}

	openlog(PACKAGE_NAME, LOG_PID, LOG_DAEMON);

	while ((c = getopt_long(argc, argv, "d:s:vbap::tyHSVhLlfr", longopts, NULL)) != -1) {
		switch (c) {
			case 'd':
				add_disk(optarg);
				break;
			case 's':
				threshold = atoi(optarg);
				break;
			case 'b':
				background = 1;
				break;
			case 'a':
				adaptive = 1;
				break;
			case 'v':
				verbose = 1;
				break;
			case 'p':
				pidfile = 1;
				if (optarg == NULL) {
					snprintf(pid_file, sizeof(pid_file), "%s", PID_FILE);
				} else {
					snprintf(pid_file, sizeof(pid_file), "%s", optarg);
				}
				break;
			case 't':
				printlog(stdout, "Dry run, will not actually park heads or freeze queue.");
				dry_run = 1;
				break;
			case 'y':
				poll_sysfs = 1;
				break;
			case 'H':
				hardware_logic = 1;
				position_interface = INTERFACE_FREEFALL;
				break;
			case 'S':
				force_software_logic = 1;
				break;
			case 'V':
				version();
				break;
			case 'l':
				dosyslog = 1;
				break;
			case 'L':
				use_leds = 0;
				break;
			case 'f':
				forceadd = 1;
				break;
			case 'r':
				forcerotational = 1;
				break;
			case 'h':
			default:
				usage();
				break;
		}
	}

	printlog(stdout, "Starting "PACKAGE_NAME);

	if (disklist && forceadd) {
		char protect_method[FILENAME_MAX] = "";
		p = disklist;
		while (p != NULL) {
			snprintf(protect_method, sizeof(protect_method), QUEUE_METHOD_FMT, p->name);
			if (kernel_interface == UNLOAD_HEADS)
				fd = open (p->protect_file, O_RDWR);
			else
				fd = open (protect_method, O_RDWR);
			if (fd > 0) {
				if (kernel_interface == UNLOAD_HEADS)
					ret = write(fd, FORCE_UNLOAD_HEADS, strlen(FORCE_UNLOAD_HEADS));
				else
					ret = write(fd, FORCE_PROTECT_METHOD, strlen(FORCE_PROTECT_METHOD));
				if (ret == -1)
					printlog(stderr, "Could not forcely enable UNLOAD feature for %s", p->name);
				else
					printlog(stdout, "Forcely enabled UNLOAD for %s", p->name);
				close(fd);
			}
			else
				printlog(stderr, "Could not open %s for forcely enabling UNLOAD feature", p->protect_file);

			p = p->next;
		}
	}

	if (disklist == NULL) {
		printlog(stdout, "WARNING: You did not supply any devices to protect, trying autodetection.");
		if (autodetect_devices() < 1)
			printlog(stderr, "Could not detect any devices.");
	}

	if (disklist == NULL)
		usage(argv);

	/* Let's see if we're on a ThinkPad or on an *Book */
	if (!position_interface)
		select_interface(0);
	if (!position_interface)
		select_interface(1);

	if (!position_interface && !hardware_logic) {
		printlog(stdout, "Could not find a suitable interface");
		return -1;
	}
	else
		printlog(stdout, "Selected interface: %s", interface_names[position_interface]);
	if (hardware_logic) {
		/* Open the file representing the hardware decision */
	        freefall_fd = open (FREEFALL_FILE, FREEFALL_FD_FLAGS);
		if (freefall_fd < 0) {
				printlog(stdout,
				        "ERROR: Failed openning the hardware logic file (%s). "
					"It is probably not supported on your system.",
				        strerror(errno));
				return errno;
		}
		else {
			printlog (stdout, "Uses hardware logic from " FREEFALL_FILE);
		}
	}
	if (!poll_sysfs && !hardware_logic) {
		if (position_interface == INTERFACE_HDAPS) {
			hdaps_input_nr = device_find_byphys("hdaps/input1");
			hdaps_input_fd = device_open(hdaps_input_nr);
			if (hdaps_input_fd < 0) {
				printlog(stdout,
				        "WARNING: Could not find hdaps input device (%s). "
				        "You may be using an incompatible version of the hdaps module. "
				        "Falling back to reading the position from sysfs (uses more power).\n"
				        "Use '-y' to silence this warning.",
				        strerror(errno));
				poll_sysfs = 1;
			}
			else {
				printlog(stdout, "Selected HDAPS input device: /dev/input/event%d", hdaps_input_nr);
			}
		} else if (position_interface == INTERFACE_AMS) {
			hdaps_input_nr = device_find_byname("Apple Motion Sensor");
			hdaps_input_fd = device_open(hdaps_input_nr);
			if (hdaps_input_fd < 0) {
				printlog(stdout,
					"WARNING: Could not find AMS input device, do you need to set joystick=1?");
				poll_sysfs = 1;
			}
			else {
				printlog(stdout, "Selected AMS input device /dev/input/event%d", hdaps_input_nr);
			}
		} else if (position_interface == INTERFACE_HP3D) {
			hdaps_input_nr = device_find_byname("ST LIS3LV02DL Accelerometer");
			hdaps_input_fd = device_open(hdaps_input_nr);
			if (hdaps_input_fd < 0) {
				printlog(stdout,
					"WARNING: Could not find HP3D input device");
				poll_sysfs = 1;
			}
			else {
				printlog(stdout, "Selected HP3D input device /dev/input/event%d", hdaps_input_nr);
			}
		} else if (position_interface == INTERFACE_APPLESMC) {
			hdaps_input_nr = device_find_byname("applesmc");
			hdaps_input_fd = device_open(hdaps_input_nr);
			if (hdaps_input_fd < 0) {
				printlog(stdout,
					"WARNING: Could not find APPLESMC input device");
				poll_sysfs = 1;
			}
			else {
				printlog(stdout, "Selected APPLESMC input device /dev/input/event%d", hdaps_input_nr);
			}
		}
	}
	if (position_interface != INTERFACE_HP3D && position_interface != INTERFACE_FREEFALL) {
		/* LEDs are not supported yet on other systems */
		use_leds = 0;
	}
	if (use_leds) {
		fd = open(HP3D_LED_FILE, O_WRONLY);
		if (fd < 0)
			use_leds = 0;
		else
			close(fd);
	}

	if (background) {
		verbose = 0;
		if (pidfile) {
			fd = open (pid_file, O_WRONLY | O_CREAT, 0644);
			if (fd < 0) {
				printlog (stderr, "Could not create pidfile: %s", pid_file);
				return 1;
			}
		}
		daemon(0,0);
		if (pidfile) {
			char buf[BUF_LEN];
			snprintf (buf, sizeof(buf), "%d\n", getpid());
			ret = write (fd, buf, strlen(buf));
			if (ret < 0) {
				printlog (stderr, "Could not write to pidfile %s", pid_file);
				return 1;
			}
			if (close (fd)) {
				printlog (stderr, "Could not close pidfile %s", pid_file);
				return 1;
			}
		}
	}

	mlockall(MCL_FUTURE);

	if (verbose) {
		p = disklist;
		while (p != NULL) {
			printf("disk: %s\n", p->name);
			p = p->next;
		}
		printf("threshold: %i\n", threshold);
		printf("read_method: %s\n", poll_sysfs ? "poll-sysfs" : (hardware_logic ? "hardware-logic" : "input-dev"));
	}

	/* check the protect attribute exists */
	/* wait for it if it's not there (in case the attribute hasn't been created yet) */
	p = disklist;
	while (p != NULL && !dry_run) {
		fd = open (p->protect_file, O_RDWR);
		if (background)
			for (i = 0; fd < 0 && i < 100; ++i) {
				usleep (100000);	/* 10 Hz */
				fd = open (p->protect_file, O_RDWR);
			}
		if (fd < 0) {
			printlog (stderr, "Could not open %s\nDoes your kernel/drive support IDLE_IMMEDIATE with UNLOAD?", p->protect_file);
			free_disk(disklist);
			return 1;
		}
		close (fd);
		p = p->next;
	}

	/* see if we can read the sensor */
	/* wait for it if it's not there (in case the attribute hasn't been created yet) */
	if (!hardware_logic) {
		ret = read_position_from_sysfs (&x, &y, &z);
		if (background)
			for (i = 0; ret && i < 100; ++i) {
				usleep (100000);	/* 10 Hz */
				ret = read_position_from_sysfs (&x, &y, &z);
			}
		if (ret) {
			printlog(stderr, "Could not read position from sysfs.");
			return 1;
		}
	}

	/* adapt to the driver's sampling rate */
	if (position_interface == INTERFACE_HDAPS)
		sampling_rate = read_int(HDAPS_SAMPLING_RATE_FILE);
	else if (position_interface == INTERFACE_HP3D)
		sampling_rate = read_int(HP3D_SAMPLING_RATE_FILE);
	if (sampling_rate <= 0)
		sampling_rate = DEFAULT_SAMPLING_RATE;
	if (verbose)
		printf("sampling_rate: %d\n", sampling_rate);

	signal(SIGUSR1, SIGUSR1_handler);

	signal(SIGTERM, SIGTERM_handler);

	while (running) {
		if (!hardware_logic) { /* The decision is made by the software */
			/* Get statistics and decide what to do */
			if (poll_sysfs) {
				usleep (1000000/sampling_rate);
				ret = read_position_from_sysfs (&x, &y, &z);
				unow = get_utime(); /* microsec */
			} else {
				double oldunow = unow;
				int oldx = x, oldy = y, oldz = z;
				ret = read_position_from_inputdev (&x, &y, &z, &unow);

				/*
				 * The input device issues events only when the position changed.
				 * The analysis state needs to know how long the position remained
				 * unchanged, so send analyze() a fake retroactive update before sending
				 * the new one.
				 */
				if (!ret && oldunow && unow-oldunow > 1.5/sampling_rate)
					analyze(oldx, oldy, unow-1.0/sampling_rate, threshold, adaptive, parked);

			}

			if (ret) {
				if (verbose)
					printf("readout error (%d)\n", ret);
				continue;
			}

			park_now = analyze(x, y, unow, threshold, adaptive, parked);
		}
		else /* if (hardware_logic) */ {
			unsigned char count; /* Number of fall events */
			if (!parked) {
				/* Wait for the hardware to notify a fall */
				ret = read(freefall_fd, &count, sizeof(count));
			}
			else {
				/*
				 * Poll to check if we no longer are falling
				 * (hardware_logic polls only when parked)
				 */
				usleep (1000000/sampling_rate);
				fcntl (freefall_fd, F_SETFL, FREEFALL_FD_FLAGS|O_NONBLOCK);
				ret = read(freefall_fd, &count, sizeof(count));
				fcntl (freefall_fd, F_SETFL, FREEFALL_FD_FLAGS);
				/*
				 * If the error is EAGAIN then it is not a real error but
				 * a sign that the fall has ended
				 */
				if (ret != sizeof(count) && errno == EAGAIN) {
					count = 0; /* set fall events count to 0 */
					ret = sizeof(count); /* Validate count */
				}
			}
			/* handle read errors */
			if (ret != sizeof(count)) {
				if (verbose)
					printf("readout error (%d)\n", ret);
				continue;
			}
			/* Display the read values in verbose mode */
			if (verbose)
				printf ("HW=%u\n", (unsigned) count);
			unow = get_utime(); /* microsec */
			park_now = (count > 0);
		}

		if (park_now && !pause_now) {
			if (!parked || unow>parked_utime+REFREEZE_SECONDS) {
				/* Not frozen or freeze about to expire */
				p = disklist;
				while (p != NULL) {
					write_protect(p->protect_file,
					      (FREEZE_SECONDS+FREEZE_EXTRA_SECONDS) * protect_factor);
					p = p->next;
				}
				/*
				 * Write protect before any output (xterm, or
				 * whatever else is handling our stdout, may be
				 * swapped out).
				 */
				if (!parked) {
				        printlog(stdout, "parking");
					if (use_leds)
						write_int (HP3D_LED_FILE, 1);
				}
				parked = 1;
				parked_utime = unow;
			}
		} else {
			if (parked &&
			    (pause_now || unow>parked_utime+FREEZE_SECONDS)) {
				/* Sanity check */
				p = disklist;
				while (p != NULL) {
					if (!dry_run && !read_int(p->protect_file))
						printlog(stderr, "Error! Not parked when we "
						       "thought we were... (paged out "
					               "and timer expired?)");
					/* Freeze has expired */
					write_protect(p->protect_file, 0); /* unprotect */
					if (use_leds)
						write_int (HP3D_LED_FILE, 0);
					p = p->next;
				}
				parked = 0;
				printlog(stdout, "un-parking");
			}
			while (pause_now) {
				pause_now = 0;
				printlog(stdout, "pausing for %d seconds", SIGUSR1_SLEEP_SEC);
				sleep(SIGUSR1_SLEEP_SEC);
			}
		}

	}

	free_disk(disklist);
	printlog(stdout, "Terminating "PACKAGE_NAME);
	closelog();
	if (pidfile)
		unlink(pid_file);
	munlockall();
	return ret;
}
Пример #3
0
int control_loop_run( void )
{
    int first_time = 1;
    long long start, end;
	long long loop_start;
    uint32_t  rem_time;

    next_period = get_utime( ) + us_period;

    while( running )
    {
        trace_data.value_3 = (int16_t)( period * 1000 );
        trace_data.value_4 = (int16_t)( heli_state );

        /* start of STAT_TO_JAV */
        start              = get_utime( );
        loop_start         = start;
        rem_time           = (uint32_t)( start % MAX_TIME );
        trace_data.value_5 = (int16_t)( rem_time >> 16 );
        trace_data.value_6 = (int16_t)( rem_time );

        if( send_motor_signals( ) )
        {
            break;
        }

        end = get_utime( );
        rem_time           = (uint32_t)( end % MAX_TIME );
        trace_data.value_7 = (int16_t)( rem_time >> 16 );
        trace_data.value_8 = (int16_t)( rem_time );
        calc_stats( end - start, STAT_TO_JAV );

        /* start of STAT_FROM_JAV */
	    start = get_utime( );

	    if( javiator_port_get_data( &javiator_data ) )
        {
            fprintf( stderr, "ERROR: connection to JAviator broken\n" );
            heli_state = HELI_STATE_SHUTDOWN;
            perform_shut_down( );
            break;
	    }

        if( ubisense_enabled )
        {
            if( (new_data_x = new_data_y = ubisense_port_is_new_data( )) )
            {
                ubisense_port_get_data( &sensor_data );
            }
        }

	    end = get_utime( );
        rem_time            = (uint32_t)( end % MAX_TIME );
        trace_data.value_9  = (int16_t)( rem_time >> 16 );
        trace_data.value_10 = (int16_t)( rem_time );
	    calc_stats( end - start, STAT_FROM_JAV );

        /* start of STAT_FROM_TERM */
        start = get_utime( );

        if( check_terminal_connection( ) )
        {
            heli_state = HELI_STATE_SHUTDOWN;

            if( first_time )
            {
                fprintf( stderr, "ERROR: connection to Terminal broken\n" );
                first_time = 0;
            }
        }
        else
        {
            first_time = 1;
        }

        get_command_data( );
        get_control_params( );

        end = get_utime( );
        rem_time            = (uint32_t)( end % MAX_TIME );
        trace_data.value_11 = (int16_t)( rem_time >> 16 );
        trace_data.value_12 = (int16_t)( rem_time );
        calc_stats( end - start, STAT_FROM_TERM );

        /* start of STAT_CONTROL */
        start = get_utime( );

        prepare_sensor_data( );
 
        switch( heli_state )
        {
            case HELI_STATE_GROUND:
                perform_ground_actions( );
                break;

            case HELI_STATE_FLYING:
                compute_motor_signals( );
                break;

            case HELI_STATE_SHUTDOWN:
                perform_shut_down( );
                break;

            default:
                fprintf( stderr, "ERROR: invalid altitude mode %d\n", heli_state );
        }

        end = get_utime( );
        rem_time            = (uint32_t)( end % MAX_TIME );
        trace_data.value_13 = (int16_t)( rem_time >> 16 );
        trace_data.value_14 = (int16_t)( rem_time );
        calc_stats( end - start, STAT_CONTROL );

        /* start of STAT_TO_TERM */
        start = get_utime( );

        send_report_to_terminal( );
        send_trace_data_to_terminal( );

        end = get_utime( );
        rem_time            = (uint32_t)( end % MAX_TIME );
        trace_data.value_15 = (int16_t)( rem_time >> 16 );
        trace_data.value_16 = (int16_t)( rem_time );
        calc_stats( end - start, STAT_TO_TERM );
        calc_stats( end - loop_start, STAT_ALL );

        /* start of STAT_SLEEP */
        start = get_utime( );

        wait_for_next_period( );

        end = get_utime( );
        calc_stats( end - start, STAT_SLEEP );

        if( ++loop_count < 0 )
        {
            fprintf( stderr, "WARNING: stats overrun\n" );
            memset( stats, 0, sizeof( stats ) );
            loop_count = 0;
        }
    }

    outlier_filter_destroy( &cof_out_x );
    outlier_filter_destroy( &cof_out_y );
    iir_lp_filter_destroy ( &iir_acc_x );
    iir_lp_filter_destroy ( &iir_acc_y );
    iir_lp_filter_destroy ( &iir_acc_z );
    iir_lp_filter_destroy ( &iir_cmd_roll );
    iir_lp_filter_destroy ( &iir_cmd_pitch );
    iir_lp_filter_destroy ( &iir_cmd_yaw );
    iir_lp_filter_destroy ( &iir_cmd_z );
    average_filter_destroy( &avg_bmu_maps );
    median_filter_destroy ( &med_bmu_temp );
    median_filter_destroy ( &med_bmu_batt );
    attitude_ekf_destroy  ( &ekf_att_roll );
    attitude_ekf_destroy  ( &ekf_att_pitch );
    attitude_ekf_destroy  ( &ekf_att_yaw );
    position_ekf_destroy  ( &ekf_pos_x );
    position_ekf_destroy  ( &ekf_pos_y );
    position_ekf_destroy  ( &ekf_pos_z );
    controller_destroy    ( &ctrl_roll );
    controller_destroy    ( &ctrl_pitch );
    controller_destroy    ( &ctrl_yaw );
    controller_destroy    ( &ctrl_x );
    controller_destroy    ( &ctrl_y );
    controller_destroy    ( &ctrl_z );

    print_stats( );
    return( 0 );
}