00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 package com.generalrobotix.ui.view.graph;
00011
00012 import java.util.*;
00013
00014 import javax.vecmath.AxisAngle4d;
00015 import javax.vecmath.Matrix3d;
00016
00017 import com.generalrobotix.ui.GrxTimeSeriesItem;
00018 import com.generalrobotix.ui.grxui.Activator;
00019 import com.generalrobotix.ui.item.GrxWorldStateItem;
00020 import com.generalrobotix.ui.item.GrxWorldStateItem.WorldStateEx;
00021 import com.generalrobotix.ui.item.GrxWorldStateItem.CharacterStateEx;
00022 import com.generalrobotix.ui.util.GrxDebugUtil;
00023 import com.generalrobotix.ui.view.graph.LogManager.LogHeader;
00024
00031 public class TrendGraphModel
00032 {
00033 private TrendGraph[] trendGraph_;
00034
00035 public static final double TIME_SCALE = 1000000;
00036 private static final double MAX_DIV = 10;
00037 private static final double LOG10 = Math.log(10);
00038
00039 private long stepTimeCount_;
00040
00041 private double stepTime_;
00042 private double totalTime_;
00043 private double currentTime_;
00044
00045 private double timeRange_;
00046 private double markerPos_;
00047
00048 private double baseTime_;
00049
00050 public int sampleCount_;
00051 public long baseCount_;
00052
00053 private AxisInfo timeAxisInfo_;
00054
00055 private HashMap<String, Integer > dataItemCount_;
00056
00057
00058 private HashMap<String, DataModel> dataModelMap_;
00059 private DataModel[] dataModelArray_;
00060 private HashMap<String, AttitudeDataModel> attitudeDataModelMap_;
00061
00062 private GrxWorldStateItem world_ = null;
00063
00064 private boolean markerFixed_;
00065 private double fixedMarkerPos_;
00066
00067
00068 private GraphPanel gPanel_= null;
00069
00070 private long prevLogSize_ = -1;
00071
00075 public TrendGraphModel(int numGraph) {
00076
00077
00078 timeAxisInfo_ = new AxisInfo(0,0);
00079 timeAxisInfo_.min = 0;
00080 timeAxisInfo_.minLimitEnabled = true;
00081 timeAxisInfo_.maxLimitEnabled = true;
00082 timeAxisInfo_.unitXOfs = 12;
00083 timeAxisInfo_.unitYOfs = 0;
00084 timeAxisInfo_.unitLabel = "(sec)";
00085 timeAxisInfo_.markerColor = Activator.getDefault().getColor( "markerColor" );
00086 timeAxisInfo_.markerVisible = true;
00087
00088 dataItemCount_ = new HashMap<String, Integer >();
00089 dataModelMap_ = new HashMap<String, DataModel>();
00090 attitudeDataModelMap_ = new HashMap<String, AttitudeDataModel>();
00091 dataModelArray_ = null;
00092
00093 trendGraph_ = new TrendGraph[numGraph];
00094 for (int i = 0; i < trendGraph_.length; i ++) {
00095 StringBuffer graphName = new StringBuffer("Graph");
00096 graphName.append(i);
00097 trendGraph_[i] = new TrendGraph(this, graphName.toString());
00098 }
00099 }
00100
00101 public int getNumGraph() {
00102 return trendGraph_.length;
00103 }
00104
00105 public TrendGraph getTrendGraph(int index) {
00106 return trendGraph_[index];
00107 }
00108
00109 public String getTrendGraphName(int index) {
00110 if (index < 0 || index >= trendGraph_.length) {
00111 throw new ArrayIndexOutOfBoundsException();
00112 }
00113 StringBuffer graphName = new StringBuffer("Graph");
00114 graphName.append(index);
00115 return graphName.toString();
00116 }
00117
00118 public void worldTimeChanged(Time time) {
00119 setCurrentTime(time.getUtime());
00120 for (int i = 0; i < trendGraph_.length; i ++) {
00121 trendGraph_[i].repaint();
00122 }
00123 }
00124
00125
00126
00132 public AxisInfo getTimeAxisInfo() {
00133 return timeAxisInfo_;
00134 }
00135
00141 public void setStepTime(
00142 long stepTime
00143 ) {
00144 stepTimeCount_ = stepTime;
00145 stepTime_ = stepTimeCount_ / TIME_SCALE;
00146
00147 sampleCount_ = (int)Math.floor(timeRange_ / stepTime_) + 2;
00148 baseCount_ = Math.round(baseTime_ / stepTime_);
00149
00150
00151 Iterator<DataModel> itr = dataModelMap_.values().iterator();
00152 while (itr.hasNext()) {
00153 DataModel dm = (DataModel)itr.next();
00154 dm.dataSeries.setSize(sampleCount_);
00155 dm.dataSeries.setXStep(stepTime_);
00156 dm.dataSeries.setXOffset(baseCount_);
00157 }
00158 Iterator<AttitudeDataModel> itr0 = attitudeDataModelMap_.values().iterator();
00159 while (itr0.hasNext()) {
00160 AttitudeDataModel ad = itr0.next();
00161 for(int i=0; i<3; i++){
00162 if(ad.rpySeries[i]!=null){
00163 ad.rpySeries[i].setSize(sampleCount_);
00164 ad.rpySeries[i].setXStep(stepTime_);
00165 ad.rpySeries[i].setXOffset(baseCount_);
00166 }
00167 }
00168 }
00169 }
00170
00176 public void setTotalTime(double totalTime) {
00177 totalTime_ = totalTime;
00178 timeAxisInfo_.max = totalTime_;
00179 }
00180
00187 public void setRangeAndPos(
00188 double timeRange,
00189 double markerPos
00190 ) {
00191 timeRange_ = timeRange;
00192 fixedMarkerPos_ = markerPos;
00193 timeAxisInfo_.extent = timeRange_;
00194 _updateDiv();
00195
00196 init();
00197 }
00198
00204 public double getTimeRange() {
00205 return timeRange_;
00206 }
00207
00213 public double getMarkerPos() {
00214 return fixedMarkerPos_;
00215 }
00216
00222 public double getStepTime() {
00223 return stepTime_;
00224 }
00225
00231 public double getTotalTime() {
00232 return totalTime_;
00233 }
00234
00240 public void setCurrentTime(long currentTime) {
00241 currentTime_ = currentTime / TIME_SCALE;
00242
00243 long oldBaseCount = baseCount_;
00244 long totalCount = Math.round(totalTime_ / stepTime_);
00245 markerFixed_ = (timeRange_ * fixedMarkerPos_ < totalTime_);
00246 if (markerFixed_) {
00247 markerPos_ = fixedMarkerPos_;
00248 baseTime_ = currentTime_ - timeRange_ * markerPos_;
00249 baseCount_ = Math.round(baseTime_ / stepTime_);
00250 } else {
00251 markerPos_ = currentTime_ / timeRange_;
00252 baseTime_ = 0;
00253 baseCount_ = 0;
00254 }
00255
00256 timeAxisInfo_.markerPos = markerPos_;
00257 timeAxisInfo_.base = baseTime_;
00258
00259 if (dataModelArray_ == null) {
00260 return;
00261 }
00262
00263 if(totalCount==0)
00264 return;
00265
00266
00267
00268 int diff = (int)(baseCount_ - oldBaseCount);
00269
00270
00271 Iterator<DataModel> itr = dataModelMap_.values().iterator();
00272 while (itr.hasNext()) {
00273 DataSeries ds = ((DataModel)itr.next()).dataSeries;
00274 ds.shift(diff);
00275 }
00276 Iterator<AttitudeDataModel> itr0 = attitudeDataModelMap_.values().iterator();
00277 while (itr0.hasNext()) {
00278 AttitudeDataModel ad = itr0.next();
00279 for(int i=0; i<3; i++){
00280 if(ad.rpySeries[i]!=null){
00281 ad.rpySeries[i].shift(diff);
00282 }
00283 }
00284 }
00285
00286 if(prevLogSize_ < totalCount)
00287 {
00288 int yet = (int)(baseCount_ + sampleCount_ - prevLogSize_);
00289 if(diff < yet)
00290 diff = yet;
00291 }
00292 prevLogSize_ = totalCount;
00293
00294 if (diff > 0) {
00295 if (diff >= sampleCount_) {
00296 _getData(baseCount_, 0, sampleCount_);
00297 } else {
00298 _getData(baseCount_, sampleCount_ - diff, diff);
00299 }
00300 } else {
00301 if (-diff >= sampleCount_) {
00302 _getData(baseCount_, 0, sampleCount_);
00303 } else {
00304 _getData(baseCount_, 0, -diff);
00305 }
00306 }
00307 }
00308
00315 public DataSeries addDataItem(
00316 DataItem dataItem
00317 ) {
00318 DataSeries ds;
00319 DataModel dm;
00320
00321 String key = dataItem.toString();
00322 Integer l = dataItemCount_.get(key);
00323 if (l == null) {
00324 if(key.contains("attitude")){
00325 AttitudeDataModel attitudeDataModel = attitudeDataModelMap_.get(dataItem.getAttributePath());
00326 if(attitudeDataModel==null){
00327 attitudeDataModel = new AttitudeDataModel();
00328 attitudeDataModelMap_.put(dataItem.getAttributePath(),attitudeDataModel);
00329 }
00330 ds = new DataSeries(sampleCount_, baseCount_ * stepTime_, stepTime_ );
00331 attitudeDataModel.setRPYSeries(dataItem.index, ds);
00332 for(int i=0; i<4; i++){
00333 DataItem di = new DataItem(dataItem.object, dataItem.node, dataItem.attribute, i, "");
00334 if(dataModelMap_.get(di.toString())==null){
00335 DataSeries dataSeries = new DataSeries(sampleCount_, baseCount_ * stepTime_, stepTime_ );
00336 dm = new DataModel(di, dataSeries);
00337 dataModelMap_.put(di.toString(), dm);
00338 attitudeDataModel.setAxisAngleSeries(i,dataSeries);
00339 }
00340 }
00341 dataItemCount_.put(key, new Integer(1));
00342 }else{
00343 dataItemCount_.put(key, new Integer(1));
00344 ds = new DataSeries(
00345 sampleCount_,
00346 baseCount_ * stepTime_,
00347 stepTime_
00348 );
00349 dm = new DataModel(dataItem, ds);
00350 dataModelMap_.put(key, dm);
00351 }
00352 dataModelArray_ = new DataModel[dataModelMap_.size()];
00353 dataModelMap_.values().toArray(dataModelArray_);
00354 } else {
00355 dataItemCount_.put(key, ++l);
00356 if(key.contains("attitude"))
00357 ds = attitudeDataModelMap_.get(dataItem.getAttributePath()).rpySeries[dataItem.index];
00358 else
00359 ds = ((DataModel)dataModelMap_.get(key)).dataSeries;
00360 }
00361
00362 initGetData();
00363 prevLogSize_ = -1;
00364 return ds;
00365 }
00366
00372 public void removeDataItem(
00373 DataItem dataItem
00374 ) {
00375 String key = dataItem.toString();
00376 Integer l = dataItemCount_.get(key);
00377 dataItemCount_.put(key, --l);
00378 if(key.contains("attitude")){
00379 if( l<= 0 ){
00380 dataItemCount_.remove(key);
00381 attitudeDataModelMap_.get(dataItem.getAttributePath()).setRPYSeries(dataItem.index, null);
00382 }
00383 AttitudeDataModel attitudeDataModel = attitudeDataModelMap_.get(dataItem.getAttributePath());
00384 if(attitudeDataModel.isDisused()){
00385 attitudeDataModelMap_.remove(dataItem.getAttributePath());
00386 for(int i=0; i<4; i++)
00387 dataModelMap_.remove(dataItem.getAttributePath()+"."+i);
00388 int size = dataModelMap_.size();
00389 if (size <= 0) {
00390 dataModelArray_ = null;
00391 } else {
00392 dataModelArray_ = new DataModel[size];
00393 dataModelMap_.values().toArray(dataModelArray_);
00394 }
00395 }
00396 }else{
00397 if (l <= 0) {
00398 dataItemCount_.remove(key);
00399 dataModelMap_.remove(key);
00400 int size = dataModelMap_.size();
00401 if (size <= 0) {
00402 dataModelArray_ = null;
00403 } else {
00404 dataModelArray_ = new DataModel[size];
00405 dataModelMap_.values().toArray(dataModelArray_);
00406 }
00407 }
00408 }
00409 initGetData();
00410 prevLogSize_ = -1;
00411 }
00412
00413
00414
00419 private void _updateDiv() {
00420 double sMin = timeAxisInfo_.extent / MAX_DIV;
00421 int eMin = (int)Math.floor(Math.log(sMin) / LOG10);
00422 double step = 0;
00423 String format = "0";
00424 int e = eMin;
00425 boolean found = false;
00426 while (!found) {
00427 int m = 1;
00428 for (int i = 1; i <= 3; i++) {
00429 step = m * Math.pow(10.0, e);
00430 if (sMin <= step) {
00431 if (e < 0) {
00432 char[] c = new char[-e + 2];
00433 c[0] = '0';
00434 c[1] = '.';
00435 for (int j = 0; j < -e; j++) {
00436 c[j + 2] = '0';
00437 }
00438 format = new String(c);
00439 }
00440 found = true;
00441 break;
00442 }
00443 m += (2 * i - 1);
00444 }
00445 e++;
00446 }
00447 timeAxisInfo_.tickEvery = step;
00448 timeAxisInfo_.labelEvery = step;
00449 timeAxisInfo_.gridEvery = step;
00450 timeAxisInfo_.labelFormat = format;
00451 }
00452
00453 public void setWorldState(GrxWorldStateItem world) {
00454 world_ = world;
00455 init();
00456 }
00457
00458
00459 private void init(){
00460 baseTime_ = 0;
00461 currentTime_ = 0;
00462 baseCount_ = 0;
00463 prevLogSize_ = -1;
00464 if(world_ != null){
00465 Double time = ((GrxTimeSeriesItem)world_).getTime(world_.getLogSize()-1);
00466 if(time != null)
00467 setTotalTime(time);
00468 else
00469 setTotalTime(0);
00470 try {
00471 double step = world_.getDbl("logTimeStep", 0.001);
00472 setStepTime((long)(1000000*step));
00473 } catch (Exception e) {
00474 GrxDebugUtil.printErr("Couldn't parse log step time.", e);
00475 }
00476 initGetData();
00477 }else{
00478 setTotalTime(0);
00479 setStepTime(1000);
00480 }
00481 }
00482
00483 public void initGetData(){
00484 if(dataModelArray_ != null && world_ != null)
00485 if (world_.isUseDsik()){
00486 world_.logger_.initGetData(dataModelArray_);
00487 }
00488 }
00489
00490 private void _getData(long origin, int offset, int count){
00491 if(world_ == null){
00492 return;
00493 } else if (world_.isUseDsik()){
00494 world_.logger_.getData(origin, offset, count);
00495 }else{
00496 int changePos = world_.getChangePosition();
00497 int counter = changePos - ((int)origin + offset);
00498
00499
00500 if( changePos >= 0 ){
00501 if( counter <= 0 ){
00502 world_.logger_.getData(-offset-counter, offset, count, dataModelArray_);
00503 return;
00504 }
00505
00506 if( counter <= count ){
00507 count -= counter;
00508 world_.logger_.getData(-offset-counter, offset + counter, count, dataModelArray_);
00509 count = counter;
00510 }
00511 }
00512
00513 WorldStateEx refWorld = world_.getValue( (int)origin + offset );
00514 if(refWorld == null){
00515 for(int h = 0; h < dataModelArray_.length; ++h){
00516 DataSeries ds = dataModelArray_[h].dataSeries;
00517 double[] dbArray = ds.getData();
00518 int localOffset = (ds.getHeadPos() + offset) % dbArray.length;
00519 for (int i = 0; i < count; ++i, ++localOffset){
00520 if(localOffset +i >= dbArray.length){
00521 localOffset = 0;
00522 }
00523 dbArray[localOffset] = Double.NaN;
00524 }
00525 }
00526 } else {
00527
00528 for(int h = 0; h < dataModelArray_.length; ++h){
00529 long recNo = origin + offset;
00530 DataItem localDataItem = dataModelArray_[h].dataItem;
00531 CharacterStateEx refCharacter = refWorld.get(localDataItem.object);
00532 CharacterStateEx localCharacter = refCharacter;
00533 DataSeries ds = dataModelArray_[h].dataSeries;
00534 double[] dbArray = ds.getData();
00535 int localOffset = (ds.getHeadPos() + offset) % dbArray.length;
00536 int index = world_.logger_.getIndex(localDataItem.object,
00537 localDataItem.node + "." + localDataItem.attribute + (localDataItem.index >= 0 ? "." + localDataItem.index : "") );
00538 ArrayList<Integer> arryLength = new ArrayList<Integer>();
00539 arryLength.add(refCharacter.position.length * 7);
00540 arryLength.add(arryLength.get(0) + refCharacter.sensorState.q.length);
00541 arryLength.add(arryLength.get(1) + refCharacter.sensorState.u.length);
00542 if(refCharacter.sensorState.force.length == 0){
00543 arryLength.add( arryLength.get(2));
00544 } else {
00545 arryLength.add( arryLength.get(2) +
00546 refCharacter.sensorState.force.length * refCharacter.sensorState.force[0].length);
00547 }
00548
00549 if(refCharacter.sensorState.rateGyro.length == 0){
00550 arryLength.add( arryLength.get(3));
00551 } else {
00552 arryLength.add( arryLength.get(3) +
00553 refCharacter.sensorState.rateGyro.length * refCharacter.sensorState.rateGyro[0].length);
00554 }
00555
00556 if(refCharacter.sensorState.accel.length == 0){
00557 arryLength.add( arryLength.get(4));
00558 } else {
00559 arryLength.add( arryLength.get(4) +
00560 refCharacter.sensorState.accel.length * refCharacter.sensorState.accel[0].length);
00561 }
00562 if(refCharacter.sensorState.range.length == 0){
00563 arryLength.add( arryLength.get(5));
00564 } else {
00565 arryLength.add( arryLength.get(5) +
00566 refCharacter.sensorState.range.length * refCharacter.sensorState.range[0].length);
00567 }
00568
00569 for (int i = 0; i < count; ++i, ++recNo, ++localOffset){
00570 if(localOffset >= dbArray.length){
00571 localOffset = 0;
00572 }
00573 if(recNo < 0 || recNo >= world_.getLogSize() || localCharacter == null){
00574 dbArray[localOffset] = Double.NaN;
00575 continue;
00576 }
00577 if (index <= arryLength.get(0)){
00578
00579
00580 } else if (index <= arryLength.get(2)){
00581 if( (index - 1) % 2 == 0 ){
00582 dbArray[localOffset] = localCharacter.sensorState.q[(index - arryLength.get(0) - 1)/2];
00583 } else {
00584 dbArray[localOffset] = localCharacter.sensorState.u[(index - arryLength.get(0) - 2)/2];
00585 }
00586 } else if (index <= arryLength.get(3) && localCharacter.sensorState.force.length > 0){
00587 int dim1 = (index - arryLength.get(2) - 1) / localCharacter.sensorState.force[0].length ;
00588 int dim2 = (index - arryLength.get(2) - 1) % localCharacter.sensorState.force[0].length ;
00589 dbArray[localOffset] = localCharacter.sensorState.force[dim1][dim2];
00590
00591 } else if (index <= arryLength.get(4) && localCharacter.sensorState.rateGyro.length > 0){
00592 int dim1 = (index - arryLength.get(3) - 1) / localCharacter.sensorState.rateGyro[0].length ;
00593 int dim2 = (index - arryLength.get(3) - 1) % localCharacter.sensorState.rateGyro[0].length ;
00594 dbArray[localOffset] = localCharacter.sensorState.rateGyro[dim1][dim2];
00595 } else if (index <= arryLength.get(5) && localCharacter.sensorState.accel.length > 0){
00596 int dim1 = (index - arryLength.get(4) - 1) / localCharacter.sensorState.accel[0].length ;
00597 int dim2 = (index - arryLength.get(4) - 1) % localCharacter.sensorState.accel[0].length ;
00598 dbArray[localOffset] = localCharacter.sensorState.accel[dim1][dim2];
00599 } else if(localCharacter.sensorState.range.length > 0) {
00600 int dim1 = (index - arryLength.get(5) - 1) / localCharacter.sensorState.range[0].length ;
00601 int dim2 = (index - arryLength.get(5) - 1) % localCharacter.sensorState.range[0].length ;
00602 dbArray[localOffset] = localCharacter.sensorState.range[dim1][dim2];
00603 }
00604 localCharacter = world_.getValue( (int)recNo ).get(localDataItem.object);
00605 }
00606 }
00607 }
00608 }
00609
00610
00611 Iterator<AttitudeDataModel> it = attitudeDataModelMap_.values().iterator();
00612 while(it.hasNext()){
00613 AttitudeDataModel attitudeDataModel = it.next();
00614 double[][] aa = new double[4][];
00615 int[] aapos = new int[4];
00616 int[] aaSize = new int[4];
00617 for(int i=0; i<4; i++){
00618 DataSeries ds = attitudeDataModel.axisAngleSeries[i];
00619 aaSize[i] = ds.getSize();
00620 aapos[i] = (ds.getHeadPos() + offset) % aaSize[i];
00621 aa[i] = attitudeDataModel.axisAngleSeries[i].getData();
00622 }
00623 double[][] rpy = {null, null, null};
00624 int[] rpypos = new int[3];
00625 int[] rpySize = new int[3];
00626 for(int i=0; i<3; i++){
00627 DataSeries ds = attitudeDataModel.rpySeries[i];
00628 if(ds!=null){
00629 rpySize[i] = ds.getSize();
00630 rpypos[i] = (ds.getHeadPos() + offset) % rpySize[i];
00631 rpy[i] = attitudeDataModel.rpySeries[i].getData();
00632 }
00633 }
00634 for (int i = 0; i < count; i++) {
00635 if(aa[0][aapos[0]] == Double.NaN || aa[1][aapos[1]] == Double.NaN || aa[2][aapos[2]] == Double.NaN || aa[3][aapos[3]] == Double.NaN){
00636 if(rpy[0]!=null) rpy[0][rpypos[0]] = Double.NaN;
00637 if(rpy[1]!=null) rpy[1][rpypos[1]] = Double.NaN;
00638 if(rpy[2]!=null) rpy[2][rpypos[2]] = Double.NaN;
00639 }else
00640 AxisAngleToRPY(aa, rpy, aapos, rpypos);
00641 for(int j=0; j<4; j++){
00642 if(aapos[j] < aaSize[j]-1)
00643 aapos[j]++;
00644 else
00645 aapos[j]=0;
00646 }
00647 for(int j=0; j<3; j++){
00648 if(rpypos[j] < rpySize[j]-1)
00649 rpypos[j]++;
00650 else
00651 rpypos[j]=0;
00652 }
00653 }
00654 }
00655 }
00656
00657 public void updateGraph(){
00658 if(world_!=null){
00659 Double time = world_.getTime();
00660 if(time!=null)
00661 setCurrentTime(new Time(time).getUtime());
00662 else
00663 setCurrentTime(0);
00664 }else
00665 setCurrentTime(0);
00666 gPanel_.redraw(gPanel_.getLocation().x,gPanel_.getLocation().y,gPanel_.getSize().x,gPanel_.getSize().y,true);
00667 }
00668
00669 public void clearDataItem() {
00670 for (int i = 0; i < getNumGraph(); i++) {
00671 TrendGraph t = getTrendGraph(i);
00672 t.clearDataItem();
00673 }
00674 }
00675
00676 public void setPanel(GraphPanel gPanel) {
00677 gPanel_ = gPanel;
00678
00679 }
00680
00681 private void AxisAngleToRPY(double[][] aa, double[][] rpy, int[] aapos, int[] rpypos){
00682 Matrix3d m = new Matrix3d();
00683 m.set(new AxisAngle4d(aa[0][aapos[0]], aa[1][aapos[1]], aa[2][aapos[2]], aa[3][aapos[3]]));
00684
00685
00686 double roll, pitch, yaw;
00687 if ((Math.abs(m.m00)<Math.abs(m.m20)) && (Math.abs(m.m10)<Math.abs(m.m20))) {
00688 double sp = -m.m20;
00689 if (sp < -1.0) {
00690 sp = -1;
00691 } else if (sp > 1.0) {
00692 sp = 1;
00693 }
00694 pitch = Math.asin(sp);
00695
00696 roll = Math.atan2(sp*m.m01+m.m12,
00697 sp*m.m02-m.m11);
00698
00699 if (m.m00>0.0) {
00700 if(roll < 0.0)
00701 roll += Math.PI;
00702 else
00703 roll -= Math.PI;
00704 }
00705 double sr=Math.sin(roll), cr=Math.cos(roll);
00706 if (sp > 0.0) {
00707 yaw = Math.atan2(sr*m.m11+cr*m.m12,
00708 sr*m.m01+cr*m.m02);
00709 } else {
00710 yaw = Math.atan2(-sr*m.m11-cr*m.m12,
00711 -sr*m.m01-cr*m.m02);
00712 }
00713 } else {
00714 yaw = Math.atan2(m.m10, m.m00);
00715 double sa = Math.sin(yaw);
00716 double ca = Math.cos(yaw);
00717 pitch = Math.atan2(-m.m20, ca*m.m00+sa*m.m10);
00718 roll = Math.atan2(sa*m.m02-ca*m.m12, -sa*m.m01+ca*m.m11);
00719 }
00720
00721 if(rpy[0]!=null) rpy[0][rpypos[0]] = roll;
00722 if(rpy[1]!=null) rpy[1][rpypos[1]] = pitch;
00723 if(rpy[2]!=null) rpy[2][rpypos[2]] = yaw;
00724 }
00725
00726 private class AttitudeDataModel{
00727 private DataSeries[] rpySeries = {null, null, null};
00728 private DataSeries[] axisAngleSeries = {null, null, null, null};
00729
00730 public AttitudeDataModel(){
00731 }
00732
00733 private void setAxisAngleSeries(int i, DataSeries dataSeries){
00734 axisAngleSeries[i] = dataSeries;
00735 }
00736
00737 private void setRPYSeries(int i, DataSeries dataSeries){
00738 rpySeries[i] = dataSeries;
00739 }
00740
00741 private boolean isDisused(){
00742 return rpySeries[0]==null && rpySeries[1]==null && rpySeries[2]==null ;
00743 }
00744 }
00745 }