private Log() { mMicrologLogger = LoggerFactory.getLogger(); /* * Only write prints to logcat if this is a * debug build */ if (WakeMeSki.DEBUG) { mMicrologLogger.addAppender(new LogCatAppender()); } }
/** * Android activity to display the debug screen to modify server parameters using a GUI * * @author pkv * @author kshaurya */ public class AirboatControlActivity extends Activity { private static final com.google.code.microlog4android.Logger logger = LoggerFactory.getLogger(); private static final String logTag = AirboatControlActivity.class.getName(); // Update rates for PID, velocity and status public static final long VEL_UPDATE_MS = 400; public static final long PID_UPDATE_MS = 1000; // Ranges for thrust and rudder signals public static final double THRUST_MIN = 0.0; public static final double THRUST_MAX = 10.0; public static final double RUDDER_MIN = -10.0; public static final double RUDDER_MAX = 10.0; // Contains a reference to the airboat service, or null if service is not running private AirboatService _airboatService = null; // Indicates if we have a valid reference to the airboat service. private boolean _isBound = false; // Stores current velocity values private Twist _velocities = new Twist(); // Timing functions to regularly update GUI private Handler _velHandler = null; private Runnable _velCallback = null; private Handler _pidHandler = null; private Runnable _pidCallback = null; private AsyncTaskFactory<Void, Void, double[][]> _updatePid = null; // Create a factory interface that generates the necessary TimerTasks interface AsyncTaskFactory<A, B, C> { public AsyncTask<A, B, C> instance(); } // Converts from progress bar value to linear scaling between min and max private double fromProgressToRange(int progress, double min, double max) { return (min + (max - min) * (progress) / 100.0); } /** Sets PID gains if the thrust text boxes are edited */ private class PidKeyListener implements OnEditorActionListener { private final int _axis; private final EditText _pText, _iText, _dText; public PidKeyListener(int axis, EditText pText, EditText iText, EditText dText) { _axis = axis; _pText = pText; _iText = iText; _dText = dText; } public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { // Ignore key presses other than "Done" if (actionId != EditorInfo.IME_ACTION_DONE) return false; // Don't do anything if we can't get access to the controller if ((_airboatService == null) || (_airboatService.getServer() == null)) return false; // Set the PID gains using the values from the text boxes try { double kp = Double.parseDouble(_pText.getText().toString()); double ki = Double.parseDouble(_iText.getText().toString()); double kd = Double.parseDouble(_dText.getText().toString()); _airboatService.getServer().setPID(_axis, new double[] {kp, ki, kd}); } catch (NumberFormatException ex) { Log.w(logTag, "Failed to parse gain.", ex); } return false; } } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { // Create the "control" layout from the included XML file super.onCreate(savedInstanceState); setContentView(R.layout.control); // Get references to all the GUI elements final CheckBox connectedBox = (CheckBox) findViewById(R.id.AutonomousBox); final CheckBox autonomousBox = (CheckBox) findViewById(R.id.AutonomousBox); final TextView rudderValue = (TextView) findViewById(R.id.RudderValue); final SeekBar rudderSlider = (SeekBar) findViewById(R.id.RudderSlider); final EditText rudderPGain = (EditText) findViewById(R.id.RudderPGain); final EditText rudderIGain = (EditText) findViewById(R.id.RudderIGain); final EditText rudderDGain = (EditText) findViewById(R.id.RudderDGain); final TextView thrustValue = (TextView) findViewById(R.id.ThrustValue); final SeekBar thrustSlider = (SeekBar) findViewById(R.id.ThrustSlider); final EditText thrustPGain = (EditText) findViewById(R.id.ThrustPGain); final EditText thrustIGain = (EditText) findViewById(R.id.ThrustIGain); final EditText thrustDGain = (EditText) findViewById(R.id.ThrustDGain); // If the PID values for thrust are changed, send them to the server PidKeyListener thrustPidListener = new PidKeyListener(0, thrustPGain, thrustIGain, thrustDGain); thrustPGain.setOnEditorActionListener(thrustPidListener); thrustIGain.setOnEditorActionListener(thrustPidListener); thrustDGain.setOnEditorActionListener(thrustPidListener); // If the PID values for rudder are changed, send them to the server PidKeyListener rudderPidListener = new PidKeyListener(5, rudderPGain, rudderIGain, rudderDGain); rudderPGain.setOnEditorActionListener(rudderPidListener); rudderIGain.setOnEditorActionListener(rudderPidListener); rudderDGain.setOnEditorActionListener(rudderPidListener); // If the Autonomous check box is pressed, send a command to change its state autonomousBox.setOnClickListener( new OnClickListener() { public void onClick(View v) { // Don't do anything if we can't get access to the controller if ((_airboatService == null) || (_airboatService.getServer() == null)) return; // Stop navigation _airboatService.getServer().stopWaypoint(); } }); // When the thrust slider is moved, send a command to change it rudderSlider.setOnSeekBarChangeListener( new OnSeekBarChangeListener() { public void onStopTrackingTouch(SeekBar seekBar) {} public void onStartTrackingTouch(SeekBar seekBar) {} public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // Don't do anything if we can't get access to the controller if ((_airboatService == null) || (_airboatService.getServer() == null)) return; // Ignore our own update events if (!fromUser) return; // Send a new velocity command Twist twist = _airboatService.getServer().getVelocity().twist.twist; twist.angular.z = fromProgressToRange(rudderSlider.getProgress(), RUDDER_MIN, RUDDER_MAX); _airboatService.getServer().setVelocity(twist); } }); // When the thrust slider is moved, send a command to change it thrustSlider.setOnSeekBarChangeListener( new OnSeekBarChangeListener() { public void onStopTrackingTouch(SeekBar seekBar) {} public void onStartTrackingTouch(SeekBar seekBar) {} public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // Don't do anything if we can't get access to the controller if ((_airboatService == null) || (_airboatService.getServer() == null)) return; // Ignore our own update events if (!fromUser) return; // Send a new velocity command Twist twist = _airboatService.getServer().getVelocity().twist.twist; twist.linear.x = fromProgressToRange(thrustSlider.getProgress(), THRUST_MIN, THRUST_MAX); _airboatService.getServer().setVelocity(twist); } }); // Schedule a regular update of the velocity and status functions _velHandler = new Handler(); _velCallback = new Runnable() { // Initialize a formatter to display velocity strings in a reasonable format DecimalFormat velFormatter = new DecimalFormat("####.###"); public void run() { // Don't do anything if we can't get access to the controller if ((_airboatService == null) || (_airboatService.getServer() == null)) return; // Update the autonomous and connected values connectedBox.setChecked(_airboatService.getServer().isConnected()); autonomousBox.setChecked( _airboatService.getServer().getWaypointStatus() == WaypointState.GOING); // Update the velocities _velocities = _airboatService.getServer().getVelocity().twist.twist; thrustValue.setText(velFormatter.format(_velocities.linear.x) + " m/s"); thrustValue.invalidate(); rudderValue.setText(velFormatter.format(_velocities.angular.z) + " rad/s"); rudderValue.invalidate(); // Reschedule the next iteration of this update _velHandler.postDelayed(_velCallback, VEL_UPDATE_MS); } }; // Schedule a regular update of the PID functions _pidHandler = new Handler(); _pidCallback = new Runnable() { public void run() { _updatePid.instance().execute((Void) null); } }; _updatePid = new AsyncTaskFactory<Void, Void, double[][]>() { public AsyncTask<Void, Void, double[][]> instance() { return new AsyncTask<Void, Void, double[][]>() { @Override protected double[][] doInBackground(Void... params) { // Don't do anything if we can't get access to the controller if ((_airboatService == null) || (_airboatService.getServer() == null)) return new double[][] {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}; // Update the PID gains double[] pidThrust = _airboatService.getServer().getPID(0); double[] pidRudder = _airboatService.getServer().getPID(5); return new double[][] {pidThrust, pidRudder}; } @Override protected void onPostExecute(double[][] result) { if (!thrustPGain.hasFocus()) { thrustPGain.setText(Double.toString(result[0][0])); thrustPGain.invalidate(); } if (!thrustIGain.hasFocus()) { thrustIGain.setText(Double.toString(result[0][1])); thrustIGain.invalidate(); } if (!thrustDGain.hasFocus()) { thrustDGain.setText(Double.toString(result[0][2])); thrustDGain.invalidate(); } if (!rudderPGain.hasFocus()) { rudderPGain.setText(Double.toString(result[1][0])); rudderPGain.invalidate(); } if (!rudderIGain.hasFocus()) { rudderIGain.setText(Double.toString(result[1][1])); rudderIGain.invalidate(); } if (!rudderDGain.hasFocus()) { rudderDGain.setText(Double.toString(result[1][2])); rudderDGain.invalidate(); } logger.info("PID: " + "0 " + Arrays.toString(result[0])); logger.info("PID: " + "5 " + Arrays.toString(result[1])); // Reschedule the next iteration of this update _pidHandler.postDelayed(_pidCallback, PID_UPDATE_MS); } }; } }; } /** Listener that handles changes in connections to the airboat service */ private ServiceConnection _connection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { // This is called when the connection with the service has been // established, giving us the service object we can use to // interact with the service. _airboatService = ((AirboatService.AirboatBinder) service).getService(); } public void onServiceDisconnected(ComponentName className) { // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. _airboatService = null; } }; void doBindService() { // Establish a connection with the service. We use an explicit // class name because we want a specific service implementation. if (!_isBound) { bindService(new Intent(this, AirboatService.class), _connection, Context.BIND_AUTO_CREATE); _isBound = true; } } void doUnbindService() { // Detach our existing connection. if (_isBound) { unbindService(_connection); _isBound = false; } } @Override protected void onStart() { super.onStart(); doBindService(); _velHandler.removeCallbacks(_velCallback); _velHandler.post(_velCallback); _pidHandler.removeCallbacks(_pidCallback); _pidHandler.post(_pidCallback); } @Override protected void onStop() { super.onStop(); doUnbindService(); _velHandler.removeCallbacks(_velCallback); _pidHandler.removeCallbacks(_pidCallback); } }
public class ChatMessageViewAdapter extends BaseAdapter { private Logger LOGGER = LoggerFactory.getLogger(ChatMessageViewAdapter.class); public static interface IMsgViewType { int IMVT_COM_MSG = 0; int IMVT_TO_MSG = 1; } private List<ChatMsgEntity> chatLists; private Context ctx; private LayoutInflater mInflater; private MediaPlayer mMediaPlayer = new MediaPlayer(); public ChatMessageViewAdapter(Context context, List<ChatMsgEntity> chatLists) { ctx = context; this.chatLists = chatLists; mInflater = LayoutInflater.from(context); } public int getCount() { return chatLists.size(); } public Object getItem(int position) { return chatLists.get(position); } public long getItemId(int position) { return position; } public int getItemViewType(int position) { ChatMsgEntity entity = chatLists.get(position); if (entity.getMsgType()) { return IMsgViewType.IMVT_COM_MSG; } else { return IMsgViewType.IMVT_TO_MSG; } } public int getViewTypeCount() { return 2; } public View getView(int position, View convertView, ViewGroup parent) { final ChatMsgEntity entity = chatLists.get(position); boolean isComMsg = entity.getMsgType(); ViewHolder viewHolder = null; if (convertView == null) { if (isComMsg) { convertView = mInflater.inflate(R.layout.chatting_item_msg_text_left, null); } else { convertView = mInflater.inflate(R.layout.chatting_item_msg_text_right, null); } viewHolder = new ViewHolder(); viewHolder.tvSendTime = (TextView) convertView.findViewById(R.id.tv_sendtime); viewHolder.tvUserName = (TextView) convertView.findViewById(R.id.tv_username); viewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_chatcontent); viewHolder.tvTime = (TextView) convertView.findViewById(R.id.tv_time); viewHolder.isComMsg = isComMsg; convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.tvSendTime.setText(entity.getDate()); if (entity.getText().contains(".amr")) { viewHolder.tvContent.setText(""); viewHolder.tvContent.setCompoundDrawablesWithIntrinsicBounds( 0, 0, R.drawable.chatto_voice_playing, 0); viewHolder.tvTime.setText(entity.getTime()); } else { viewHolder.tvContent.setText(entity.getText()); viewHolder.tvContent.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); viewHolder.tvTime.setText(""); } viewHolder.tvContent.setOnClickListener( new OnClickListener() { public void onClick(View v) { if (entity.getText().contains(".amr")) { playMusic( android.os.Environment.getExternalStorageDirectory() + "/" + entity.getText()); } } }); viewHolder.tvUserName.setText(entity.getName()); return convertView; } static class ViewHolder { public TextView tvSendTime; public TextView tvUserName; public TextView tvContent; public TextView tvTime; public boolean isComMsg = true; } /** * @Description * * @param name */ private void playMusic(String name) { try { if (mMediaPlayer.isPlaying()) { mMediaPlayer.stop(); } mMediaPlayer.reset(); mMediaPlayer.setDataSource(name); mMediaPlayer.prepare(); mMediaPlayer.start(); mMediaPlayer.setOnCompletionListener( new OnCompletionListener() { public void onCompletion(MediaPlayer mp) {} }); } catch (Exception e) { LOGGER.error("播放出错", e); } } }