void handle_update_request( Train_update_request *update_request, Train_status *train_status, Train_server_data *server_data ){
	// What type of request is this? 
	if ( update_request->update_type == MOVE_FREE_UPDATE ){
		// The train has been ordered to move freely. 
		// If there was a previous goal, remove it. 
		initialize_goal( train_status ); 

		// TODO: Make the sensor detective check all sensors -> We are assuming that there's only 1 train in the track. 

		// Send the commands
		int cmd_type = update_request->cmd.cmd_type; 
		switch( cmd_type ){
			case TRAIN_CMD_TYPE:
				train_status->motion_data.original_train_speed = 0;
				train_status->motion_data.distance_type = LONG_DISTANCE; 
				send_train_move_command( update_request->cmd.param, 0, train_status, server_data ); 
				break; 
			case REVERSE_CMD_TYPE:
				train_status->motion_data.original_train_speed = train_status->motion_data.train_speed; 
				train_status->motion_data.distance_type = LONG_DISTANCE; 
				send_train_move_command( TRAIN_STOP_CMD_SPEED, 0, train_status, server_data );
				train_status->is_reversing = 1; 
				break; 
			default:
				// Should never get here
				bwassert( 0, "TRAIN_MOTION: update_train_status -> Invalid command type." );
				break; 
		}
	}
	else if ( update_request->update_type == CHANGE_GOAL_UPDATE ){
		// There's a new goal. 
		// 1. Erase previous goal information 
		initialize_goal( train_status ); 

		// 2. Get a new path
		// NOTE: For the edge we always consider straight line. If the user wants to move to a curve branch, 
		// then he needs to give another landmark. 
		train_status->current_goal.landmark = ( track_node * ) update_request->cmd.element_id;	// CAREFUL!!!
		train_status->current_goal.offset = update_request->cmd.param;
		train_status->current_goal.edge = &( train_status->current_goal.landmark->edge[ DIR_AHEAD ] ); 

		int path_found = request_new_path( train_status, server_data );
		bwassert( path_found, "TRAIN_MOTION: Path couldn't be found" ); 

		// 3. Now the train has a goal. Update the status accordingly.
		train_status->train_state = TRAIN_STATE_MOVE_TO_GOAL; 
	}
}
int track_train_short_distance( Train_status *train_status, Train_server_data *server_data ){
	int continue_execution = 0; 
	if ( train_status->motion_state == TRAIN_STILL ){
		// For short distances the only important state is when the train is still. 
		// We don't care about the other states because the distances are too small. 
		if ( has_train_arrived( train_status ) ){
			// The train has reached its destination
			// - Remove the current goal
			initialize_goal( train_status );

			continue_execution = 1; 
		}

		// Release all the reserved track; keep only the current size of the train. 
		reserve_distance( 0, train_status, server_data );
	}

	return continue_execution;
}
Example #3
0
void initialize_tactic_module() {
    initialize_goal();
    initialize_proof_state();
    initialize_expr_to_tactic();
    initialize_apply_tactic();
    initialize_rename_tactic();
    initialize_intros_tactic();
    initialize_trace_tactic();
    initialize_exact_tactic();
    initialize_unfold_tactic();
    initialize_generalize_tactic();
    initialize_whnf_tactic();
    initialize_clear_tactic();
    initialize_revert_tactic();
    initialize_inversion_tactic();
    initialize_assert_tactic();
    initialize_class_instance_elaborator();
    initialize_rewrite_tactic();
    initialize_change_tactic();
    initialize_check_expr_tactic();
}
void predict_train_movement( int current_time, Train_status *train_status, Train_server_data *server_data ){
	// Initialization
	int cmd_delay, speed_to_use, distance_to_reserve, time_in_constant_speed; 
	int is_distance_reserved, next_update_time, accurate_current_time ; 

	// Is the train supposed to move?
	// - If not, there's no need to stay in this method. 
	if ( train_status->train_state == TRAIN_STATE_MOVE_FREE ){
		int original_speed = train_status->motion_data.original_train_speed; 
		int curr_speed = train_status->motion_data.train_speed; 

		if ( original_speed == curr_speed && curr_speed == 0 )
			return;
	}

	// If the train is moving a short distance track it somewhere else
	if ( train_status->motion_data.distance_type == SHORT_DISTANCE ){
		int continue_exec = track_train_short_distance( train_status, server_data );
		if ( !continue_exec )
			return; 
	}

	// Determine what's going to happen in the future, and how to react to it. 
	switch( train_status->motion_state ){
		case TRAIN_STILL:
			// -- Initialization --
			accurate_current_time = TimeInMs(); 
			cmd_delay = accurate_current_time; 

			// 1. DETERMINE DIRECTION
			//		- Is the train facing at the right direction?
			if ( train_status->train_state == TRAIN_STATE_MOVE_FREE ){
				if ( train_status->is_reversing ){
					// TODO: Do we need to add a delay because of this movement? 
					send_reverse_command( train_status, server_data );
				}

				speed_to_use = train_status->motion_data.original_train_speed;
			}
			else if ( train_status->train_state == TRAIN_STATE_MOVE_TO_GOAL ){
				if ( has_train_arrived( train_status ) ){
					// The train has reached its destination
					// - Remove the current goal
					initialize_goal( train_status );

					// TODO: Remove the sensor tracking of this part of the track 
					break; 
				}

				// Does the train need to reverse? 
				if ( requires_reversing( train_status ) ){
					train_status->is_reversing = 1; 
					cmd_delay += get_reverse_delay_time( server_data ); 
					send_reverse_command( train_status, server_data );

					// NOTE: We calculate the route again in case the "extra" space
					// used for reverse causes problems. 
					clear_train_motion_data( train_status );
					int path_found = request_new_path( train_status, server_data );
					bwassert( path_found, "TRAIN_MOTION: Path couldn't be found" ); 
				}

				// Calculate the next "straight" movement
				speed_to_use = calculate_speed_to_use( train_status, &server_data->calibration_data );
			}

			if ( train_status->motion_data.distance_type == SHORT_DISTANCE ){
				// Since the behavior of short distances is different, they are handled in a different function. 
				start_short_distance_movement( speed_to_use, train_status, server_data );
			}
			else{
				// 2. RESERVATION
				//		- The train is going to move, and it's already facing the right direction. 
				//		- How far should we reserve?
				distance_to_reserve = 
					//get_train_acceleration_distance( speed_to_use, server_data ) + // TODO: Make sure we don't need this part -> I don't think we need it. 
					get_train_stopping_distance( speed_to_use, server_data ) + 
					get_reservation_distance_buffer( server_data );

				is_distance_reserved = reserve_distance( distance_to_reserve, train_status, server_data ); 

				// 3. START MOVEMENT
				//		- If the reservation was successful, are there any switches that need to be moved? 
				//		- If the reservation was successful, start moving
				if ( is_distance_reserved ){
					if ( train_status->train_state == TRAIN_STATE_MOVE_TO_GOAL ){
						// Move switches within that distance
						int num_sw_changed = check_next_sw_pos( distance_to_reserve, train_status, server_data );
						if ( num_sw_changed ){
							//cmd_delay = current_time + get_sw_delay_time( server_data ); 
						}

						// Add the sensors to attribution list.
						add_sensors_attrib_list( distance_to_reserve, train_status, server_data ); 
					}

					// Start moving
					//bwprintf( COM2, "Starting Moving: [ train_id: %d speed: %d dir: %d ]\n", 
					//	train_status->train_id, speed_to_use, train_status->train_direction ); 
					send_train_move_command( speed_to_use, cmd_delay, train_status, server_data );
				}
			}

			break; 
		case TRAIN_ACCELERATING:
		case TRAIN_CONSTANT_SPEED:
			// When will the next update be done? 
			next_update_time = get_next_update_time( current_time );

			// 1. Calculate distance to reserve
			// -- Get the basic data
			int time_speed_change = train_status->time_speed_change;
			int time_to_reach_constant_sp = get_time_to_constant_speed( train_status, server_data );
			int time_to_start_deacceleration = get_time_to_start_deaccelerating( train_status, server_data ); 
			time_in_constant_speed = time_to_start_deacceleration - time_to_reach_constant_sp; 
			
			// -- The distance to reserve regardless of the amount of constant data traveled
			distance_to_reserve = 
				get_train_stopping_distance( train_status->motion_data.train_speed, server_data ) + 
				get_reservation_distance_buffer( server_data );  

			if ( time_speed_change + time_to_reach_constant_sp < next_update_time ){
				
				// The train will move some time at constant speed.
				// -- How much time will the train move at constant speed before the next update? 
				int init_time, end_time, time_const_speed_before_update; 
				//int time_const_speed_before_update;
				if ( train_status->train_state == TRAIN_STATE_MOVE_TO_GOAL ){

					// Check when the constant speed was reached in this update interval
					if( time_speed_change + time_to_reach_constant_sp <= current_time )
						init_time = current_time; 
					else
						init_time = time_speed_change + time_to_reach_constant_sp; 

					// Check when to stop counting constant speed in this update interval
					if ( time_speed_change + time_to_start_deacceleration < next_update_time )
						end_time = time_speed_change + time_to_start_deacceleration;
					else
						end_time = next_update_time;

					time_const_speed_before_update = end_time - init_time; 
				}
				else{
					time_const_speed_before_update = current_time - next_update_time; 
				}

				// -- The distance traveled during constant speed before the next update also needs to be reserved. 
				int train_speed = train_status->motion_data.train_speed;
				int distance_constant_speed = round_decimal_up( get_distance_in_constant_speed( time_const_speed_before_update, train_speed, server_data ) );
				distance_to_reserve += distance_constant_speed;

				bwdebug( DBG_USR, TRAIN_SRV_DEBUG_AREA, "TRAIN_MOTION: Train traveled at constant speed. [ train_id: %d distance_traveled: %d ]", 
					train_status->train_id, distance_constant_speed );
			}

			// 2. Reserve the distance
			//bwprintf( COM2, "[ RESERVATION -> Reserved_distance: %d ]\n", distance_to_reserve );
			is_distance_reserved = reserve_distance( distance_to_reserve, train_status, server_data ); 
			
			// 3. Prepare everything in the reserved distance for the train movement
			if ( is_distance_reserved ){
				
				// Check if there are switches to move in the reserved distance. 
				check_next_sw_pos( distance_to_reserve, train_status, server_data );

				// Does that train need to start de-accelerating?
				int temp_time = time_speed_change + time_to_start_deacceleration; 
				////bwprintf( COM2, "DEACCELERATE -> CURRENT_TIME: %d NEXT_UPD_TIME: %d TIME_SP_CHANGE: %d TIME_TO_DEACC: %d\n", 
				//	current_time, next_update_time, time_speed_change, time_to_start_deacceleration );
				if ( temp_time >= current_time && temp_time < next_update_time ){
					send_train_move_command( TRAIN_STOP_CMD_SPEED, temp_time, train_status, server_data );
				}

				// Add sensors to attribution list
				add_sensors_attrib_list( distance_to_reserve, train_status, server_data ); 
			}
			else{
				// The new distance couldn't be reserved. STOP RIGHT AWAY!!!
				bwdebug( DBG_USR, TRAIN_SRV_DEBUG_AREA, "TRAIN_MOTION: Couldn't reserve distance. Stopping!! [ train_id: %d distance_requested: %d ]", 
					train_status->train_id, distance_to_reserve ); 
				send_train_move_command( TRAIN_STOP_CMD_SPEED, 0, train_status, server_data );
			}

			break;
		case TRAIN_DEACCELERATING:
			bwdebug( DBG_USR, TRAIN_SRV_DEBUG_AREA, "TRAIN_MOTION: Deaccelerating. [ train_id: %d ]", train_status->train_id ); 

			distance_to_reserve = 0; 
			int distance_since_deacceleration = 
				train_status->distance_since_speed_change - train_status->distance_before_deacceleration;

			distance_to_reserve = 
				get_train_stopping_distance( train_status->motion_data.train_speed, server_data) - distance_since_deacceleration; 

			// The train doesn't care if it gets the reserved distance or not; it should but it's already stopping anyway
			reserve_distance( distance_to_reserve, train_status, server_data );

			// Add sensors to attribution list
			add_sensors_attrib_list( distance_to_reserve, train_status, server_data ); 

			break;
	}
}